The GHC user's guide describes the impredicative polymorphism extension with reference to the following example:
f :: Maybe (forall a. [a] -> [a]) -> Maybe ([Int], [Char])
f (Just g) = Just (g [3], g "hello")
f Nothing = Nothing
However, when I define this example in a file and try to call it, I get a type error:
ghci> f (Just reverse)
<interactive>:8:9:
Couldn't match expected type `forall a. [a] -> [a]'
with actual type `[a0] -> [a0]'
In the first argument of `Just', namely `reverse'
In the first argument of `f', namely `(Just reverse)'
In the expression: f (Just reverse)
ghci> f (Just id)
<interactive>:9:9:
Couldn't match expected type `forall a. [a] -> [a]'
with actual type `a0 -> a0'
In the first argument of `Just', namely `id'
In the first argument of `f', namely `(Just id)'
In the expression: f (Just id)
Seemingly only undefined
, Nothing
, or Just undefined
satisfies the type-checker.
I have two questions, therefore:
- Can the above function be called with
Just f
for any non-bottomf
? - Can someone provide an example of a value only definable with impredicative polymorphism, and usable in a non-trivial way?
The latter is particularly with the HaskellWiki page on Impredicative Polymorphism in mind, which currently makes a decidedly unconvincing case for the existence of the extension.
forall a. [a] -> [a]
.forall a. Maybe ([a] -> [a])
fails, because the type checker seems to try to instantiatea
to bothInt
andChar
.Maybe (forall a. [a] -> [a])
fails, because it expectsforall a. [a] -> [a]
, but it gets a[a0] -> [a0]
wherea0
is fresh. So, withMaybe
, the nested type scheme is only instantiated once, but withoutMaybe
, everything is just fine. – Primp