I have a data type with quite a few constructors, they are all simple enough that Haskell can automatically output an instance of Ord. How in:
data Foo a = A a | B Int deriving (Eq, Ord)
Now I want to add a third constructor, for example:
data Foo a = A a | B Int | C a (a -> Bool)
But now Haskell cannot manually output Eq and Ord to Foo for me. Now it happens that I have some domain-related knowledge about how two values built using C should be ordered:
instance Eq a => Eq (Foo a) where -- Boilerplate I don't want to write A x == A y = x == y B x == B y = x == y -- This is the case I really care about C xf == C yg = x == y && fx == gy _ == _ = False instance Ord a => Ord (Foo a) where -- Boilerplate I don't want to write A x `compare` A y = x `compare` y A x `compare` _ = LT B x `compare` B y = x `compare` y B x `compare` A _ = GT B _ `compare` _ = LT -- This is the case I really care about C xf `compare` C yg | x == y = fx `compare` gy | otherwise = x `compare` y C{} `compare` _ = GT
But for this, I also need to manually sort by the values of A and B, which is very tiring (especially for an Ord instance).
Is there any trick that would allow me to implement (==) and compare only with C code, but somehow get the default behavior for other constructors?
source share