如何分解属于某种类型的歧视联盟?

时间:2018-04-08 21:53:20

标签: f# discriminated-union

假设我有以下(基本的,略显无意义的)F#...

type Point = Point of int * int
type MyUnion =
    | MyInt of int
    | MyString of string
    | MyTwoStrings of string * string
    | MyPoint of Point

...然后我可以写一个这样的函数......

let MyUnionType myunion =
  match myunion with
  | MyInt n -> printfn "You gave me an Int (%d)" n
  | MyString s -> printfn "You gave me a string (%s)" s
  | MyTwoStrings (s1, s2) -> printfn "You gave me two strings (\"%s\", \"%s\")" s1 s2
  // Missing case here...

这适用于MyUnionType的前三个版本,但我无法在MyPoint

时找出如何编写匹配的子句

我尝试了以下内容,类似于MyTwoStrings案例......

| MyPoint (p1, p2) -> printfn "You gave me a point (%d, %d)" p1 p2

...但是这会产生编译错误,指出(p1, p2)预计会有Point类型,但类型为'a * 'b

我尝试了以下内容......

| MyPoint p -> printfn "You gave me a point (%A)" p

..哪有效,但无法让我访问int

中的两个Point

如何获取int中的两个Point值?

2 个答案:

答案 0 :(得分:8)

type Point = Point of int * int是一个单一案例的歧视联盟,而不仅仅是一个元组。

你构建它像let p = Point(0, 0),所以你需要以类似的方式解构它。您的上一个示例是一个很好的起点:| MyPoint p -> ...Point值绑定到p,以便稍后解构它:

| MyPoint p ->
    let (Point (p1, p2)) = p
    printfn "You gave me a point (%i, %i)" p1 p2

或者你可以在match本身中结合解构:

| MyPoint (Point (p1, p2)) -> printfn "You gave me a point (%i, %i)" p1 p2

答案 1 :(得分:5)

您的类型$CLOUDSDK_PYTHON与您的类型Point具有完全相同的性质。唯一的区别是MyUnion有一个构造函数,但Point有几个。就是这样。

MyUnion的构造函数与类型本身具有相同的名称这一事实完全无关紧要。类型名称和构造函数名称位于不同的名称空间中。它们可以相同也可以不同,不会改变任何东西。

因此,获取Point类型内容的方式与Point完全相同,例如:

MyUnion

然后,这种模式也可以嵌套在另一种模式中:

let sumCoords p = match p with
    | Point (x,y) = x + y