I was trying to define a data type for rock paper scissors and came up with something like this:
data Hand = P | S | R deriving (Show, Eq)
instance Ord Hand where
compare R P = LT
compare P R = GT
compare R S = GT
compare S R = LT
compare P S = LT
compare S P = GT
compare _ _ = EQ
While writing all that I was wondering if there's any way to define the data type to just have it derive Ord and then specify that
compare R P = LT
and compare P R = GT
instead of having to write all the comparisons by hand, for three elements it's okay but it would get tedious with each added element.
What you describe here is not an order relation. An order relation is:
x
are less than or equal tot itself;x
is less than or equal to y
and y
is less than or equal to x
, then x
is equal to y
;x
is less than or equal to y
, and y
is less than or equal to z
, then x
is less than or equal to z
.Your definition is not transitive. Indeed: S
is less than R
, R
is less than P
, but S
is not less than P
. I therefore would strongly advice you not to use Ord
, since for instance sorting, etc. make use of these invariants.
What you can do is let it derive from Ord
automatically:
data Hand = P | S | R deriving (Show, Eq, Ord)
and then define a function beats
:
beats :: Hand -> Hand -> Ordering
beats R P = LT
beats P R = GT
beats x y = compare x y