Reputation: 1965
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?
Upvotes: 2
Views: 3795
Reputation: 105876
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
Upvotes: 7