What is the difference between these?
{-# LANGUAGE RankNTypes #-}
f :: forall a. a -> Int
f _ = 1
g :: (forall a. a) -> Int
g _ = 1
In particular, why do I get an error with g ()
?
ghci> f ()
1
ghci> g ()
<interactive>:133:3:
Couldn't match expected type `a' with actual type `()'
`a' is a rigid type variable bound by
a type expected by the context: a at <interactive>:133:1
In the first argument of `g', namely `()'
In the expression: g ()
In an equation for `it': it = g ()
ghci> f undefined
1
ghci> g undefined
1
f
is just an ordinary polymorphic Haskell98 function, except theforall
is written out explicitly. So all the type variables in the signature are parameters the caller gets to choose (without any constraints); in your case it's resolveda ~ ()
.g
OTOH has a rank-2 type. It requires that its argument has the polymorphic typeforall a . a
.()
does not have such a type, it is monomorphic. Butundefined
has this type (in fact, only undefined, and error etc.), if we add the explicitforall
again.Perhaps it becomes clearer with a less trivial Rank2 function:
but I can't do