[Haskell-cafe] GHC 8 + ImpredictiveTypes + $

Niklas Hambüchen mail at nh2.me
Fri Jun 10 09:23:03 UTC 2016


> Now, I say 'trivial' since the actual fix is incredibly minor - a change
> of compose (.) to apply ($). What was less trivial was the (additional)
> hair loss arriving at the fix

Tell me about it - when experimentally making a larger project work with
GHC 8, I spent a lot of time trying to understand the problem and was
rather disappointed that the climax of this effort was to replace `a = f
. g` by `a x = f (g x)` in two places.

The 8.0 migration guide
https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0 already has a
section about "Impredicative types brokenness" - I would have
appreciated if it contained the simple sentence "In many cases, this can
be fixed by rewriting `a = f . g` to `a x = f (g x)`."

Maybe somebody can add it.

> * I assume previously GHC did not fully check type aliases that were
> impredictive prior to GHC 8?

Yes,
https://ghc.haskell.org/trac/ghc/wiki/Migration/8.0#Requirementforimpredicativetypes:
"In previous versions of GHC, it was possible to hide an impredicative
type behind a type synonym, because GHC did not always expand type
synonyms when checking for impredicativity."

> * What does this imply for a type alias such as for the alias RunInBase
> used in monad-control that contains RankNTypes:
> http://hackage.haskell.org/package/monad-control-1.0.1.0/docs/Control-Monad-Trans-Control.html#t:RunInBase -
> Is such an alias not safe in some sense? (Was it never safe?)

I'll let others answer this one.

> * How does the use of ($) vs (.) fix this particular issue? (I'd naively
> assume the usage here would be equivalent.) I recall reading about ($)'s
> magical type alias somewhere - is this related?

This page (I'm not sure if you already knew it before asking the question)

  https://ghc.haskell.org/trac/ghc/wiki/ImpredicativePolymorphism

describes the difference between `test1 x = foo (bar x)` and `test2 =
foo . bar`; it also has a "Special case for ($)" section which I believe
is the answer to your question. The summary is:

  " But Haskell programmers use ($) so much, to avoid writing
parentheses, that GHC's type inference has an ad-hoc special case for
($) that allows it to do type inference for (e1 $ e2), even when
impredicative polymorphism is needed. "

Niklas


More information about the Haskell-Cafe mailing list