I want to create a data type which can take a tuple, of either length 2 or 3, and that should contain types deriving Num and Ord. Then, I want to pattern match on the length of this tuple in my type class instances so that I can decide which function to use based on the tuple length. Take a look at the non-compilable, pseudo-code below. There are at least two problems:
Dominatesis not a derivable classI don't know how to get the tuple, e.g. to call
fitnesses, to get the variable out of the data type when pattern matching in the instance.
Code:
data Fits = I2 (Int, Int) | F2 (Float, Float) | I3 (Int, Int, Int) | F3 (Float, Float, Float)
data Ind = Ind { fitnesses :: Fits
, otherInfo :: String
} deriving (Dominates)
class Dominates a where
dominates :: a -> a -> bool
instance Dominates Ind where
dominates x@(_,_) y@(_,_) = x `dominates2` y -- takes two tuples of length 2
dominates x@(_,_,_) y@(_,_,_) = x `dominates3` y -- takes two tuples of length 3
Update:
data Ind = Ind { fitnesses :: Fits
, otherInfo :: String
}
instance Eq Ind where
(Ind{ fitnesses = I2 x@(a1,a2) }) == (Ind{ fitnesses = I2 y@(b1,b2) }) = indCmp2 x y == EQ
instance Ord Ind where
(Ind{ fitnesses = I2 x@(a1,a2) }) `compare` (Ind{ fitnesses = I2 y@(b1,b2) }) = indCmp2 x y
indCmp2 :: (Num a, Ord a) => (a, a) -> (a, a) -> Ordering
indCmp2 x y
| a0 < b0 = LT
| a0 > b0 = GT
-- Can assume (fst x) == (fst y) beneath
| a1 < b1 = LT
| a1 > b1 = GT
| a1 == b1 = EQ
where
a0 = fst x
a1 = snd x
b0 = fst y
b1 = snd y
This compiles. Why is it necessary to make an instance of Eq, if I only want Ord? Without the Eq-instance the compiler complains "no instance for (Eq Ind)".