Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Cyclic Ord Relationship

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.

like image 363
user1079328 Avatar asked Apr 22 '26 23:04

user1079328


2 Answers

What you describe here is not an order relation. An order relation is:

  1. reflexive, all values x are less than or equal tot itself;
  2. antisymmetric: if x is less than or equal to y and y is less than or equal to x, then x is equal to y;
  3. transitive: if 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
like image 147
Willem Van Onsem Avatar answered Apr 26 '26 06:04

Willem Van Onsem


You can write generic variant of this function:

cyclicRelation :: (Bounded a, Ord a) => a -> a -> Ordering
cyclicRelation x y | x == minBound && y == maxBound = GT
                   | x == maxBound && y == minBound = LT
                   | otherwise                      = x `compare` y

Then just derive needed instances:

data Hand = P | S | R deriving (Show, Eq, Ord, Bounded)
like image 35
freestyle Avatar answered Apr 26 '26 04:04

freestyle