铸造没有共同祖先的歧视联盟

时间:2015-07-07 17:42:00

标签: f#

我有歧视的联盟:

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
 }

2 个答案:

答案 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关键字创建修改后的记录。