"Nested" union types in elm

Nini Michaels

I'm learning elm and trying to switch my mindset from TypeScript's type system. I was wondering what's the best way to use nested types like this:

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

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

the compiler complains

The first pattern is trying to match `X` values of type:

    Player

But the expression between `case` and `of` is:

    Cell

I can change viewCell like so, but then I don't know how to get the player

viewCell: Cell -> String
viewCell cell = 
  case cell of
    Player -> -- how to get the player ??
    Empty -> " "

The problem is not displaying the values per se, rather "destructuring" the nested union type so to speak. I want to use it later on in something like this:

check: (List Cell) -> string
check three =
  case three of
    [X, X, X] -> "X won"
    [O, O, O] -> "O won"
    _ -> "still going"

which also gives me similar complaints from the compiler

z5h

The only time a constructor and type can share a name is if you do something like:

type Tag = Tag String

Consider that you've said

type Cell = Player | Empty

but might also want

type Winner = Player | None

So what's Player? Is it a Cell or a Winner? It can't be both.

The simple solution is:

type Cell = PlayerCell Player | Empty

type Winner = WinningPlayer Player | None

PlayerCell X is a cell with player X. WinningPlayer O is a winner.

When destructuring, you can nest:

case cell of
  PlayerCell X -> 
    ...
  PlayerCell O -> 
    ...
  Empty -> 
    ...

In fact, you can destructure more complex data structures:

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

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related