我有歧视的联盟:
type Attribute =
| A of o : A
| B of o : B
| None
我有一个函数,它返回一个属性列表(属性列表)。
let attributes = foo some another
我需要一个create函数,它获取Attributes列表并返回Result类型,其中:
type Result =
{
a : A[]
b : B[]
}
Th函数必须获取列表的每个元素并将其添加到Result类型的相应数组中。
这是我的尝试:
let justDoIt (attributes : Attribute list) : Result =
let result = {
a = Array.empty;
b = Array.empty
}
let accumulate (a : Attribute) (accum : Result) : Result =
match a with
| A o -> o :?> A |> Array.append accum.a
accum
let rec foo (attributes : Attribute list) (accum : Result) : Result =
match attributes with
| [] -> accum
| hd::tail -> foo tail (accumulate hd accum)
foo attributes result
当我想要将歧视联盟转换为特定类型时,我在accumulate
函数中遇到了问题。
有没有办法,或者用不同的方法解决这个任务会更好?
更新:
type A =
{
Some : int
}
type B =
{
Another : string
}
答案 0 :(得分:3)
您可以使用Seq.fold
(而不是自己编写递归处理)。如果将结果存储为列表,它看起来会更好,因为您可以使用::
运算符追加新元素:
let justDoIt attributes =
attributes |> Seq.fold (fun ({ a = alist; b = blist } as st) it ->
match it with
| A a -> { st with a = a :: alist }
| B b -> { st with b = b :: blist }
| _ -> st ) { a = []; b = [] }
答案 1 :(得分:1)
在这种情况下,您根本不需要强制转换函数:
let justDoIt (attributes : Attribute list) : Result =
let result = {
a = Array.empty;
b = Array.empty
}
let accumulate (a : Attribute) (accum : Result) : Result =
match a with
| A o -> { accum with a = Array.append (accum.a) [|o|] } // don't need to cast as 'o' is already of type 'A'
| B o -> { accum with b = Array.append (accum.b) [|o|] }
| None -> accum
let rec foo (attributes : Attribute list) (accum : Result) : Result =
match attributes with
| [] -> accum
| hd::tail -> foo tail (accumulate hd accum)
foo attributes result
但是,如果您将DU的案例命名为不同的类型,则会让您感到困惑。记录Result
也是不可变的,因此您必须使用with
关键字创建修改后的记录。