I am working with Data.Typeable and in particular I want to be able to generate correct types of a particular kind (say *
). The problem that I'm running into is that TypeRep allows us to do the following (working with the version in GHC 7.8):
let maybeType = typeRep (Proxy :: Proxy Maybe)
let maybeCon = fst (splitTyConApp maybeType)
let badType = mkTyConApp maybeCon [maybeType]
Here badType
is in a sense the representation of the type Maybe Maybe, which is not a valid type of any Kind:
> :k Maybe (Maybe)
<interactive>:1:8:
Expecting one more argument to ‘Maybe’
The first argument of ‘Maybe’ should have kind ‘*’,
but ‘Maybe’ has kind ‘* -> *’
In a type in a GHCi command: Maybe (Maybe)
I'm not looking for enforcing this at type level, but I would like to be able to write a program that is smart enough to avoid constructing such types at runtime. I can do this with data-level terms with TypeRep
. Ideally, I would have something like
data KindRep = Star | KFun KindRep KindRep
and have a function kindOf
with kindOf Int = Star
(probably really kindOf (Proxy :: Proxy Int) = Star
) and kindOf Maybe = KFun Star Star
, so that I could "kind-check" my TypeRep value.
I think I can do this manually with a polykinded typeclass like Typeable
, but I'd prefer to not have to write my own instances for everything. I'd also prefer to not revert to GHC 7.6 and use the fact that there are separate type classes for Typeable types of different kinds. I am open to methods that get this information from GHC.
typeOf1
andTypeable1
(and friends) are still exported fromData.Typeable
... they are usable in 7.8. – Nathan Howell