如何分解作为一种类型的可区分联合?

How do I decompose a discriminated union that is a type?

假设我有以下(基本且毫无意义的)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

..有效,但无法访问 Point

中的两个 int

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

type Point = Point of int * int 是一个 single-case 有区别的联合,而不仅仅是一个元组。

你像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

您的类型 Point 与您的类型 MyUnion 具有完全相同的性质。唯一的区别是 Point 有一个构造函数,而 MyUnion 有多个。而已。

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

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

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

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

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
      | MyPoint (Point (x,y)) -> printfn "You gave me a point (%d, %d)" x y