Skip to content

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:

  1. 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 in Data.Typeable not in clients). It's a sort of infinite regress, but it bottoms out with Typeable Type, which is its own superclass.

  2. 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.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information