
In transformers-0.5 it seems that I have to implement Eq1, Ord1, Show1 instances manually.
For better or worse, that is indeed the case. Before, Eq1/Ord1/Read1/Show1 relied on the type argument having an implicit dictionary to use, which is why you could get away with piggybacking off of your existing Eq/Ord/Read/Show instances. Now, Eq1, Eq2, and friends rely on explicit dictionary passing, so they're strictly more powerful than Eq et al.
Is there some assistance to define eq1 and compare1 for an ADT?
At the moment, no. Sometime in the future, I want to do two things which should make the situation a little better: 1. Write a language extension to derive Eq1/Eq2/etc. It definitely won't be making it into GHC 8.0 due to time constraints, plus I need to propose a design. And... 2. ...I should write a Template Haskell shim which implements the proposed design. I already have a package called deriving-compat [1] which has done this (but only for recent changes to -XDeriveFoldable), so that would probably be a logical place to put it. Until then, if you need to hand-roll Eq1/Eq2/etc. instances that align with your Eq instances, I'd recommend copying the output of ghc -ddump-deriv, copying the generated instances, and replacing the necessary calls with dictionary arguments. For example, given this instance: data Example a = Example Int a deriving Eq Compiling with ghc -ddump-deriv gives you this (after some code cleanup): instance Eq a => Eq (Example a) where Example i1 a1 == Example i2 a2 = i1 == i2 && a1 == a2 e1 /= e2 = not (e1 == e2) Then, you can create an Eq1 instance with some minor adjustments: instance Eq1 Example where liftEq eq (Example i1 a1) (Example i2 a2) = i1 == i2 && eq a1 a2
What are the use cases where eq1 was not powerful enough and liftEq is needed?
The previous type signature of Data.Functor.Classes in transformers-0.4 resulted in some awkward instances, a prime example being found in Data.Functor.Compose: import Data.Functor.Classes(Eq1(..)) newtype Compose f g a = Compose (f (g a)) instance (Functor f, Eq1 f, Eq1 g, Eq a) => Eq (Compose f g a) where Compose x == Compose y = eq1 (fmap Apply x) (fmap Apply y) instance (Functor f, Eq1 f, Eq1 g) => Eq1 (Compose f g) where eq1 = (==) newtype Apply g a = Apply (g a) instance (Eq1 g, Eq a) => Eq (Apply g a) where Apply x == Apply y = eq1 x y This is a super-kludgey instance because it requires f to be a Functor instance. In general, having these Functor constraints pop up everywhere results in less efficient instances, and it won't work at all for many GADT-like constructions that can't have legal Functor instances. With the new API, there is no need for these Functor constraints: import Data.Functor.Classes(Eq1(..)) newtype Compose f g a = Compose (f (g a)) instance (Eq1 f, Eq1 g) => Eq1 (Compose f g) where liftEq eq (Compose x) (Compose y) = liftEq (liftEq eq) x y Ryan S. ----- [1] http://hackage.haskell.org/package/deriving-compat