Improve Typeable instances
Consider this example, taken from this email thread
newtype D a = D { getD :: Int }
class Typeable a => S a
instance Typeable a => S (D a)
This looks OK but it isn't:
Poly.hs:10:10: error:
• Could not deduce (Typeable k)
arising from the superclasses of an instance declaration
from the context: Typeable a
bound by the instance declaration at Poly.hs:10:10-30
The problem is that D
is poly-kinded, thus D :: forall k. k -> Type
. So the instance is really like this:
instance Typeable a => S (D @k (a::k))
And now GHC wants a Typeable k
instance so it can make the type representation for D @k a
.
But this is a bit funny. WE have Typeable (a::k)
, and we have a function
typeRepKind :: forall a (a::k). TypeRep a -> TypeRep k
So, given a TypeRep (a::k)
(or equivalently Typeable (a::k)
) we can easily get a TypeRep k
(or equivalently Typeable k
).
This ticket is to suggest that we automtate this. I can see two alternatives:
-
Change the definition of
Typeable
thus:class Typeable k => Typeable (a::k) where ...
That is, add the typerep of the kind as a superclass. This would require
UndecideableSuperclasses
(but only inData.Typeable
not in clients). It's a sort of infinite regress, but it bottoms out withTypeable Type
, which is its own superclass. -
Don't make a proper superclass (a field of the dictionary) but instead somehow use
typeRepKind
to make a kind of bespoke superclass, during superclass expansion.
(2) sounds a bit magical and ad-hoc; let's try (1) first.
Maybe this should be a GHC proposal, but I wanted to float it here first.