假设我有一个由三个案例组成的受歧视联合。CaseA
和C
each 需要一个构造函数来输入X
和Y
。我有一个由不同 DU 类型组成的列表,我想将该列表过滤为单个 DU 类型。目前,我有一个列表,其中包含A
,B
和C
。现在,如果我只想过滤 DU 列表以键入 case A
,我该如何做到这一点而不必将构造函数传递给 case A
?(或传递默认构造函数,我也不知道该怎么做)
type X = {
Id: string
Name: string
}
type Y = {
Id: int
}
type DU =
| A of a:X
| B
| C of b:Y
let extractDUTypesFromList (listDU: List<DU>) (typ: DU) : List<DU> =
listDU
|> List.filter (fun m -> m = typ)
let a = (A {Id = "1"; Name = "Test"})
let aa = (A {Id = "2"; Name = "Test 2"})
let b = B
let c = (C {Id = 1})
let listDU: List<DU> = [a; b; c; aa]
let filteredDUList: List<DU> = // this list will only contain case A
extractDUTypesFromList listDU (A _) // doesn't work
为了像这样过滤,我们需要与 DU 构造函数相反的函数,它是一个主动识别器。
不幸的是,您必须手动创建它们,虽然我建议让 F# 编译器自动派生它们,但这是一个很好的示例,说明了为什么此类建议很重要。
// Active recognizers (ideally autogenerated)
let (|A|_|) = function | A x -> Some x | _ -> None
let (|B|_|) = function | B -> Some () | _ -> None
let (|C|_|) = function | C x -> Some x | _ -> None
let inline extractDUTypesFromList (listDU: List<DU>) (typ: DU -> Option<'t>) : List<DU> =
listDU
|> List.choose (fun x -> typ x |> Option.map (fun _ -> x))
let a = (A {Id = "1"; Name = "Test"})
let aa = (A {Id = "2"; Name = "Test 2"})
let b = B
let c = (C {Id = 1})
let listDU: List<DU> = [a; b; c; aa]
let filteredDUList: List<DU> = // this list will only contain case A
extractDUTypesFromList listDU (|A|_|)
结果是
val filteredDUList : List<DU> = [A { Id = "1"
Name = "Test" }; A { Id = "2"
Name = "Test 2" }]
无需说您可以创建普通函数而不是主动识别器,因为仅在这种用法中我们根本不使用模式匹配,我的意思是您可以tryA
按照建议命名函数,而不是(|A|_|)
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句