Deriving Data for poly-kinded datatypes

Ryan Scott at
Thu Feb 23 19:51:41 UTC 2017

Hi Pedro,

I'm quite confused by a peculiarity of deriving Data (more info in
Trac #13327 [1]). In particular, if you write this:

    data T phantom = T
      deriving Data

Then the derived Data instance is NOT this:

    instance Typeable phantom => Data (T phantom) where

But instead, it's this:

    instance Data phantom => Data (T phantom) where
      dataCast1 f = gcast1 f

The gcast1 part is why it requires the stronger (Data phantom)
context, as you noted in Trac #4028 [2].

What confuses me, however, is that is apparently does not carry over
to poly-kinded datatypes. For instance, if you write this:

    data T (phantom :: k) = T
      deriving Data

Then you do NOT get this instance:

    instance Data (phantom :: *) => Data (T phantom) where
      dataCast1 f = gcast1 f

But instead, you get this instance!

    instance (Typeable k, Typeable (phantom :: k)) => Data (T phantom) where
      -- No implementation for dataCast1

This is quite surprising to me. I'm not knowledgeable enough about
Data to know for sure if this is an oversight, expected behavior, or
something else, so I was hoping you (or someone else highly
knowledgeable about SYB-style generic programming) could help me out

In particular:

1. Does emitting "dataCast1 f = gcast1 f" for datatypes of kind (k ->
*) make sense? Or does it only make sense for types of kind (* -> *)?
2. Is there an alternate way to define dataCast1 that doesn't require
the stronger Data context, but instead only requires the more general
Typeable context?

Ryan S.

More information about the ghc-devs mailing list