Either
isn’t simply a union of types; it’s a tagged union, which means every value has to explicitly specify which “side” of the type the wrapped value occurs on. Here’s an example, (with a Show
instance derived for your Card
type):
*Main> Card Hearts Jack
<interactive>:3:13: error:
• Couldn't match type ‘Court’ with ‘Either Pip Court’
Expected type: Rank
Actual type: Court
• In the second argument of ‘Card’, namely ‘Jack’
In the expression: Card Hearts Jack
In an equation for ‘it’: it = Card Hearts Jack
Card
expects an argument of type Either Pip Court
, but you gave it a plain Court
value. With an explicit wrap:
*Main> Card Hearts (Right Jack)
Card Hearts (Right Jack)
The same applies to creating a numbered card:
*Main> Card Hearts 3
<interactive>:5:13: error:
• No instance for (Num Rank) arising from the literal ‘3’
• In the second argument of ‘Card’, namely ‘3’
In the expression: Card Hearts 3
In an equation for ‘it’: it = Card Hearts 3
*Main> Card Hearts (Left 3)
Card Hearts (Left 3)
You don’t need to change the definition of snap
, because there is already an Eq
instance for Either
as long as both wrapped types have Eq
instances themselves; it considers any Right
value unequal to any Left
value, and matching Right
or Left
values are equal if the wrapped values are equal.
*Main> snap (Card Hearts (Right Jack)) (Card Hearts (Left 3))
"..."
*Main> snap (Card Hearts (Right Jack)) (Card Spades (Right Jack))
"SNAP"
0
solved Couldn’t match type Synonym with Either