4

您知道要解开单个联合类型的值,您必须这样做:

type Foo = Foo of int*string

let processFoo foo =
    let (Foo (t1,t2)) = foo
    printfn "%A %A" t1 t2 

但我的问题是:如果有办法为列表做到这一点?:

let processFooList (foolist:Foo list )  =
    let ??? = foolist // how to get a int*string list
    ...

谢谢。

4

3 回答 3

3

最好的方法是使用与List.maplike结合的函数

let processFooList (foolist:Foo list )  = foolist |> List.map (function |Foo(t1,t2)->t1,t2)
于 2013-12-07T03:28:17.853 回答
1

没有用于将列表从 转换为 的预定义活动模式Fooint * string但您可以将命名模式§7.2(解构单一案例联合)与投影结合到您自己的单一案例活动模式§7.2.3中。

let asTuple (Foo(t1, t2)) = t1, t2      // extract tuple from single Foo
let (|FooList|) =  List.map asTuple     // apply to list

用作函数参数:

let processFooList (FooList fooList) =  // now you can extract tuples from Foo list
    ...                                 // fooList is an (int * string) list

在 let-binding 中使用:

let (FooList fooList) = 
    [ Foo(1, "a"); Foo(2, "b") ]
printfn "%A" fooList                    // prints [(1, "a"); (2, "b")]
于 2013-12-07T18:38:14.503 回答
0

提炼/总结/重申/重新发布其他两个答案,您引用的行:

let ??? = foolist // how to get a int*string list

可以变成:

let ``???`` = foolist |> List.map (function |Foo(x,y) -> x,y)

如果您正在编写转换,则可以使用以下任一方法在定义了活动模式的参数中进行匹配:

let (|FooList|) = List.map <| fun (Foo(t1, t2)) -> t1,t2
let (|FooList|) = List.map <| function |Foo(t1, t2) -> t1,t2

然后可以按如下方式消费:

let processFooList (fooList:Foo list )  =
    // do something with fooList
于 2013-12-08T02:05:33.507 回答