Types &引用;嵌套的;elm中的并集类型

Types &引用;嵌套的;elm中的并集类型,types,elm,union-types,Types,Elm,Union Types,我正在学习elm,并试图从TypeScript的类型系统转换我的思维方式。我想知道使用嵌套类型的最佳方式是什么: type Player = X | O type Cell = Player | Empty viewCell: Cell -> string viewCell cell = case cell of X -> "X" O -> "O" Empty -> " " check: (List Cell) -> string

我正在学习elm,并试图从TypeScript的类型系统转换我的思维方式。我想知道使用嵌套类型的最佳方式是什么:

type Player = X | O
type Cell = Player | Empty

viewCell: Cell -> string
viewCell cell = 
  case cell of
    X -> "X"
    O -> "O"
    Empty -> " "
check: (List Cell) -> string
check three =
  case three of
    [X, X, X] -> "X won"
    [O, O, O] -> "O won"
    _ -> "still going"
type Player = X | O
type Cell = Player Player | Empty

viewCell: Cell -> String
viewCell cell = 
  case cell of
    Player X -> "X"
    Player 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 -> " "
问题不是显示值本身,而是“解构”嵌套的联合类型。我想稍后在类似这样的内容中使用它:

type Player = X | O
type Cell = Player | Empty

viewCell: Cell -> string
viewCell cell = 
  case cell of
    X -> "X"
    O -> "O"
    Empty -> " "
check: (List Cell) -> string
check three =
  case three of
    [X, X, X] -> "X won"
    [O, O, O] -> "O won"
    _ -> "still going"
type Player = X | O
type Cell = Player Player | Empty

viewCell: Cell -> String
viewCell cell = 
  case cell of
    Player X -> "X"
    Player O -> "O"
    Empty -> " "

这也给了我编译器类似的抱怨

构造函数和类型唯一可以共享名称的时候是如果您执行以下操作:

type Tag=Tag String

考虑一下你说过的话

type Cell=Player|Empty

但也可能需要

type Winner=Player |无

那么什么是
Player
?它是
单元格
还是
赢家
?不可能两者都有

简单的解决办法是:

type Cell=PlayerCell Player|Empty

type Winner=WinningPlayer | None

PlayerCell X
是一个包含玩家X的单元格。
winning玩家O
是赢家

分解结构时,可以嵌套:

case cell of
  PlayerCell X -> 
    ...
  PlayerCell O -> 
    ...
  Empty -> 
    ...
事实上,您可以分解更复杂的数据结构:

  case cellRow of 
    [ PlayerCell O, PlayerCell O, PlayerCell O] -> 
      ... 

Player
不是一个类型,而是一个类型为
Cell
的值。但是,您也可以给它一个参数,在这种情况下,它将是一个值构造函数,当给它一个参数时,它将返回一个类型为
Cell
的值。所以在

type Player = X | O
type Cell = Player Player | Empty
Player-Player
中的第一个
Player
基本上是一个函数,当给定类型为
Player
的值时,该函数将返回类型为
Cell
的值。或者键入speak中的
Player->Cell

还要注意,类型和构造函数可以具有相同的名称,因为它们位于不同的域中。它们并不冲突,因为它们引用不同的东西,一个引用类型,另一个引用值(构造函数)。但事实上,你可以,并不一定意味着你应该,因为它可以相当混乱

然后,您可以在
单元格
和嵌套的
播放器
上进行模式匹配,如下所示:

type Player = X | O
type Cell = Player | Empty

viewCell: Cell -> string
viewCell cell = 
  case cell of
    X -> "X"
    O -> "O"
    Empty -> " "
check: (List Cell) -> string
check three =
  case three of
    [X, X, X] -> "X won"
    [O, O, O] -> "O won"
    _ -> "still going"
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
这里指的是
单元格的构造函数/变体,而不是类型。同样地,
X
O
指的是
Player
的变体,它们也不是类型。

谢谢!所以我想没有办法像我的第一个例子那样“解构”类型?您是否有任何书籍或文章推荐,以更好地理解elm的类型系统?我认为初学者elm Slack是学习基础知识时快速获得答案的好地方。在我的答案中添加了更复杂的分解。