Skip to content

Set `ImpredicativeTypes` during :print command. (#14828)

Roland Senn requested to merge RolandSenn/ghc:T14828 into master

If ImpredicativeTypes is not enabled, then :print <term> will fail if the type of <term> has nested foralls or =>s. This is because the GHCi debugger's internals will attempt to unify a metavariable with the type of <term> and then display the result, but if the type has nested foralls or =>s, then unification will fail. As a result, :print will bail out and the unhelpful result will be <term> = (_t1::t1) (where t1 is a metavariable).

Beware: <term> can have nested foralls even if its definition doesn't use RankNTypes! Here is an example from #14828 (closed):

  class Functor f where
    fmap :: (a -> b) -> f a -> f b

Somewhat surprisingly, :print fmap considers the type of fmap to have nested foralls. This is because the GHCi debugger sees the type fmap :: forall f. Functor f => forall a b. (a -> b) -> f a -> f b. We could envision deeply instantiating this type to get the type forall f a b. Functor f => (a -> b) -> f a -> f b, but this trick wouldn't work for higher-rank types.

Instead, we adopt a simpler fix: enable ImpredicativeTypes when using :print and friends in the GHCi debugger. This is allows metavariables to unify with types that have nested (or higher-rank) foralls/=>s, which makes :print fmap display as fmap = (_t1::forall a b. Functor f => (a -> b) -> f a -> f b), as expected.

Although ImpredicativeTypes is a somewhat unpredictable from a type inference perspective, there is no danger in using it in the GHCi debugger, since all of the terms that the GHCi debugger deals with have already been typechecked.

Edited by Ben Gamari

Merge request reports