Skip to content

Inferring non-tau kinds

While up to my usual type-level shenanigans, I found that I want this definition:

data TypeRep (a :: k) -- abstract

data TypeRepX :: (forall k. k -> Constraint) -> Type where
  TypeRepX :: forall k (c :: forall k'. k' -> Constraint) (a :: k).
              c a => TypeRep a -> TypeRepX c

Note TypeRepX's higher-rank kind. The idea is that I want to optionally constrain TypeRepX's payload. Without using a higher-rank kind, the constraint would necessary fix the kind of the payload, and I don't want that. For example, I sometimes use TypeRepX ConstTrue, where

class ConstTrue (a :: k)
instance ConstTrue a

This actually works just fine, and I've been using the above definition to good effect.

But then I wanted a Show instance:

instance Show (TypeRep a)  -- elsewhere

instance Show (TypeRepX c) where
  show (TypeRepX tr) = show t

Looks sensible. But GHC complains. This is because it tries to infer c's kind, by inventing a unification variable and then unifying. But this doesn't work, of course, because c's kind is not a tau-type, so unification fails, lest we let impredicativity sneak in. What's particularly vexing is that, even if I annotate c with the correct kind, unification still fails. This is because that c is a usage of c, not a binding of c. Indeed, there is no place in an instance declaration to bind a type variable explicitly, so I have no recourse.

I'm not sure what the solution is here. Somehow, it feels that inferring a non-tau kind for c is perfectly safe, because the kind is known from the use of TypeRepX. This would allow me to drop the kind annotation in the definition of TypeRepX, which looks redundant to me. But I'm not fully sure about this assumption.

At the least, we could introduce a spot for explicit binding of type variables in instance declarations.

I think, actually, I just figured it out. Use ExpTypes when kind-checking types. Then I think the normal bidirectional thing (actually already implemented) will do the Right Thing.

Trac metadata
Trac field Value
Version 8.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information