Moving forall with coerce

David Feuer david.feuer at
Mon Oct 19 21:02:36 UTC 2015

It appears, as far as I can tell, that GHC can't move a forall past an
-> with coerce. I was playing around with the MonadTrans instance for
Codensity, wanting (essentially) to write

lift = coerce (>>=)

This is legal:

instance MonadTrans Codensity where
  lift = frob
frob :: forall m a . Monad m => m a -> Codensity m a
frob = coerce (blah (Mag (>>=)) :: m a -> Mag2 m a)
newtype Mag m a = Mag (forall b . m a -> (a -> m b) -> m b)
newtype Mag2 m a = Mag2 (forall b . (a -> m b) -> m b)
blah :: Mag m a -> m a -> Mag2 m a
blah (Mag p) q = Mag2 (p q)

The problem is that there doesn't *seem* to be a way to implement blah
as a coercion. GHC doesn't recognize that

Mag m a

has the same representation as

m a -> Mag2 m a

The essential difference, as far as I can see, is that the `forall b`
is shifted across `m a ->`. It seems that this really shouldn't be an
issue, because

1. b is not free in `m a`
2. Type lambdas all compile away

Would it be worth trying to extend the Coercible mechanism to deal
with these kinds of situations? Or is there already some way to do it
that I've missed?


More information about the ghc-devs mailing list