Как я могу разложить дискриминационный союз, который является типом?
Предположим, у меня есть следующее (основное и немного бессмысленное) 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 ответа
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
Ваш тип 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