I was hoping GHC would be able to pull the
Typeable
constraint from the context on theWrap
constructor
If it had a Wrap
constructor, it could pull the Typeable
constraint from it.
But it doesn't have a Wrap
constructor.
The difference is that the Eq
instance uses the value, so it's either a Wrap something
, where the Wrap
constructor makes the Eq
dictionary for the wrapped type available, and everything is fine, or it's ⊥
, and then everything is fine too, evaluating x == y
bottoms out.
Note that the derived
instance Eq (Wrapper a)
does not have an Eq
constraint on the type variable a
.
Prelude DerivT> (undefined :: Wrapper (Int -> Int)) == undefined
*** Exception: Prelude.undefined
Prelude DerivT> (undefined :: (Int -> Int)) == undefined
<interactive>:3:29:
No instance for (Eq (Int -> Int)) arising from a use of `=='
Possible fix: add an instance declaration for (Eq (Int -> Int))
In the expression: (undefined :: Int -> Int) == undefined
In an equation for `it':
it = (undefined :: Int -> Int) == undefined
But the Typeable
instance must not make use of the value, so there's no bottoming out if the supplied value isn't a Wrap something
.
Thus the derived instance Typeable1 Wrapper
supplies
instance Typeable t => Typeable (Wrapper t)
but not an unconstrained
instance Typeable (Wrapper t)
and that unconstrained instance cannot be derived by GHC.
Hence you have to either provide a constrained
instance Typeable t => BothEqAndTypeable (Wrapper t)
or an unconstrained
instance Typeable (Wrapper t)
yourself.