Let's say I have a data type that represents a deck of poker cards like so
data Suit = Clubs | Spades | Hearts | Diamonds deriving (Eq)
instance Show Suit where
show Diamonds = "♦"
show Hearts = "♥"
show Spades = "♠"
show Clubs = "♣"
data Value = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace deriving (Eq, Ord)
data Card = Card {
value :: Value
, suit :: Suit
} deriving (Eq, Ord)
instance Show Card where show (Card v s) = show s ++ show v
Haskell helps me already a lot by allow me to derive Eq
and Ord
without explicitly specifying those relations.
This is especially useful, because I want to use Ord
to ultimately compare the value of two hands according to Poker rules.
Now in Poker, the suits do not really matter in terms of ordering. Therefore I tried
instance Ord Suit where
compare Clubs Spades = EQ
compare Clubs Hearts = EQ
compare Clubs Diamonds = EQ
compare Spades Hearts = EQ
compare Spades Diamonds = EQ
compare Hearts Diamonds = EQ
This is already a bit verbose ... and it does not even work:
*P054> a
♠A
*P054> b
♣A
*P054> a < b
*** Exception: P054.hs:(12,9)-(17,36): Non-exhaustive patterns in function compare
So how can I properly define an ordering on Suit
that expresses the fact that all suits are equal?
You are missing several combinations, e.g. all with Clubs
on the right hand side. If all are equal, what are the possible results of compare
, regardless of the input? There is only one: EQ
. Therefore we don't even need to look at a
or b
:
instance Ord Suit where
compare _ _ = EQ
However, that Ord
instance is rather useless. Alternatively you can create a custom instance for Card
,
instance Ord Card where
compare a b = compare (value a) (value b)
-- compare = compare `on` value -- using `on` from Data.Function
-- compare = comparing value -- using `comparing` from Data.Ord