[Haskell-cafe] Inference for RankNTypes

Dan Doel dan.doel at gmail.com
Wed Jan 2 17:20:46 CET 2013

Your example doesn't work for the same reason the following doesn't work:

    id runST (<some st code>)

It requires the inferencer to instantiate certain variables of id's type to
polymorphic types based on runST (or flip's based on one), and then use
that information to check <some st code> (id in your example) as a
polymorphic type. At various times, GHC has had ad-hoc left-to-right
behavior that made this work, but it no longer does. Right now, I believe
it only has an ad-hoc check to make sure that:

    runST $ <some st code>

works, and not much else. Note that even left-to-right behavior covers all
cases, as you might have:

    f x y

such that y requires x to be checked polymorphically in the same way. There
are algorithms that can get this right in general, but it's a little
tricky, and they're rather different than GHC's algorithm, so I don't know
whether it's possible to make GHC behave correctly.

The reason it works when you factor out or annotate "flip one 'x'" is that
that is the eventual inferred type of the expression, and then it knows to
expect the id to be polymorphic. But when it's all at once, we just have a
chain of unifications relating things like: (forall a. a -> a) ~ beta ~
(alpha -> alpha), where beta is part of type checking flip, and alpha ->
alpha is the instantiation of id's type with unification variables, because
we didn't know that it was supposed to be a fully polymorphic use. And that
unification fails.

On Wed, Jan 2, 2013 at 8:21 AM, Francesco Mazzoli <f at mazzo.li> wrote:

> At Wed, 2 Jan 2013 14:49:51 +0200,
> Roman Cheplyaka wrote:
> > I don't see how this is relevant.
> Well, moving `flip one' in a let solves the problem, and The fact that
> let-bound
> variables are treated differently probably has a play here.  I originally
> thought that this was because the quantifications will be all to the left
> in the
> let-bound variable while without a let-bound variable the types are used
> directly.  However this doesn’t explain the behaviour I’m seeing.
> > GHC correctly infers the type of "flip one 'x'":
> >
> >   *Main> :t flip one 'x'
> >   flip one 'x' :: (forall a. a -> a) -> Char
> >
> > But then somehow it fails to apply this to id. And there are no bound
> > variables here that we should need to annotate.
> Right.  The weirdest thing is that annotating `flip one' (as in `three' in
> my
> code) or indeed `flip one 'x'' with the type that shows up in ghci makes
> things work:
>     five = (flip one 'x' :: (forall a. a -> a) -> Char) id
> Francesco
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130102/273e6feb/attachment.htm>

More information about the Haskell-Cafe mailing list