"Nested" elm 中的联合类型
"Nested" union types in elm
我正在学习 elm 并试图将我的思维方式从 TypeScript 的类型系统转变过来。我想知道像这样使用嵌套类型的最佳方法是什么:
type Player = X | O
type Cell = Player | Empty
viewCell: Cell -> string
viewCell cell =
case cell of
X -> "X"
O -> "O"
Empty -> " "
编译器抱怨
The first pattern is trying to match `X` values of type:
Player
But the expression between `case` and `of` is:
Cell
我可以像这样更改 viewCell,但我不知道如何获取播放器
viewCell: Cell -> String
viewCell cell =
case cell of
Player -> -- how to get the player ??
Empty -> " "
问题不在于显示值本身,而是 "destructuring" 可以这么说的嵌套联合类型。我想稍后像这样使用它:
check: (List Cell) -> string
check three =
case three of
[X, X, X] -> "X won"
[O, O, O] -> "O won"
_ -> "still going"
编译器也给我类似的抱怨
构造函数和类型唯一可以共享名称的情况是:
type Tag = Tag String
考虑一下你说过的
type Cell = Player | Empty
但可能还想要
type Winner = Player | None
那么 Player
是什么?是 Cell
还是 Winner
?不能两者都是。
简单的解决方案是:
type Cell = PlayerCell Player | Empty
type Winner = WinningPlayer Player | None
PlayerCell X
是玩家 X 的单元格。WinningPlayer O
是赢家。
解构时可以嵌套:
case cell of
PlayerCell X ->
...
PlayerCell O ->
...
Empty ->
...
事实上,你可以解构更复杂的数据结构:
case cellRow of
[ PlayerCell O, PlayerCell O, PlayerCell O] ->
...
在
type Cell = Player | Empty
Player
不是类型,而是Cell
类型的值。但是,您也可以给它一个参数,在这种情况下,它将是一个值构造函数,当给定一个参数 return 时,它是一个 Cell
类型的值。所以在
type Player = X | O
type Cell = Player Player | Empty
Player Player
中的第一个 Player
本质上是一个函数,当给定一个 Player
类型的值时,它将 return 一个 Cell
类型的值。或打字说 Player -> Cell
。
另请注意,类型和构造函数可以具有相同的名称,因为它们位于不同的域中。它们并不冲突,因为它们指的是不同的东西,一个指的是类型,另一个指的是值(构造函数)。但事实上你可以并不一定意味着你应该,因为它可能会非常混乱。
然后您可以在 Cell
和嵌套的 Player
上进行模式匹配,如下所示:
type Player = X | O
type Cell = Player Player | Empty
viewCell: Cell -> String
viewCell cell =
case cell of
Player X -> "X"
Player O -> "O"
Empty -> " "
这里的Player
和Empty
指的是Cell
的constructors/variants,不是类型。同样,X
和 O
指的是 Player
的变体,它们也不是类型。
我正在学习 elm 并试图将我的思维方式从 TypeScript 的类型系统转变过来。我想知道像这样使用嵌套类型的最佳方法是什么:
type Player = X | O
type Cell = Player | Empty
viewCell: Cell -> string
viewCell cell =
case cell of
X -> "X"
O -> "O"
Empty -> " "
编译器抱怨
The first pattern is trying to match `X` values of type:
Player
But the expression between `case` and `of` is:
Cell
我可以像这样更改 viewCell,但我不知道如何获取播放器
viewCell: Cell -> String
viewCell cell =
case cell of
Player -> -- how to get the player ??
Empty -> " "
问题不在于显示值本身,而是 "destructuring" 可以这么说的嵌套联合类型。我想稍后像这样使用它:
check: (List Cell) -> string
check three =
case three of
[X, X, X] -> "X won"
[O, O, O] -> "O won"
_ -> "still going"
编译器也给我类似的抱怨
构造函数和类型唯一可以共享名称的情况是:
type Tag = Tag String
考虑一下你说过的
type Cell = Player | Empty
但可能还想要
type Winner = Player | None
那么 Player
是什么?是 Cell
还是 Winner
?不能两者都是。
简单的解决方案是:
type Cell = PlayerCell Player | Empty
type Winner = WinningPlayer Player | None
PlayerCell X
是玩家 X 的单元格。WinningPlayer O
是赢家。
解构时可以嵌套:
case cell of
PlayerCell X ->
...
PlayerCell O ->
...
Empty ->
...
事实上,你可以解构更复杂的数据结构:
case cellRow of
[ PlayerCell O, PlayerCell O, PlayerCell O] ->
...
在
type Cell = Player | Empty
Player
不是类型,而是Cell
类型的值。但是,您也可以给它一个参数,在这种情况下,它将是一个值构造函数,当给定一个参数 return 时,它是一个 Cell
类型的值。所以在
type Player = X | O
type Cell = Player Player | Empty
Player Player
中的第一个 Player
本质上是一个函数,当给定一个 Player
类型的值时,它将 return 一个 Cell
类型的值。或打字说 Player -> Cell
。
另请注意,类型和构造函数可以具有相同的名称,因为它们位于不同的域中。它们并不冲突,因为它们指的是不同的东西,一个指的是类型,另一个指的是值(构造函数)。但事实上你可以并不一定意味着你应该,因为它可能会非常混乱。
然后您可以在 Cell
和嵌套的 Player
上进行模式匹配,如下所示:
type Player = X | O
type Cell = Player Player | Empty
viewCell: Cell -> String
viewCell cell =
case cell of
Player X -> "X"
Player O -> "O"
Empty -> " "
这里的Player
和Empty
指的是Cell
的constructors/variants,不是类型。同样,X
和 O
指的是 Player
的变体,它们也不是类型。