如何分解作为一种类型的可区分联合?
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
假设我有以下(基本且毫无意义的)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