Either
- это не просто объединение типов;это теговое объединение, что означает, что каждое значение должно явно указывать, на какой «стороне» типа встречается переносимое значение.Вот пример (с экземпляром Show
, полученным для вашего типа Card
):
*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
ожидает аргумент типа Either Pip Court
, но вы дали ему простой Court
значение.С явным переносом:
*Main> Card Hearts (Right Jack)
Card Hearts (Right Jack)
То же самое относится к созданию пронумерованной карты:
*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)
Вам не нужно изменять определение snap
, потому что уже естьэкземпляр Eq
для Either
, если оба упакованных типа имеют сами экземпляры Eq
;оно считает любое значение Right
неравным любому значению Left
, и совпадающие значения Right
или Left
равны, если заключенные в них значения равны.
*Main> snap (Card Hearts (Right Jack)) (Card Hearts (Left 3))
"..."
*Main> snap (Card Hearts (Right Jack)) (Card Spades (Right Jack))
"SNAP"