I was playing around with van Laarhoven lenses and ran into a problem where the type-checker rejects the eta-reduced form of a well-typed function:
{-# LANGUAGE RankNTypes #-}
import Control.Applicative
type Lens c a = forall f . Functor f => (a -> f a) -> (c -> f c)
getWith :: (a -> b) -> ((a -> Const b a) -> (c -> Const b c)) -> (c -> b)
getWith f l = getConst . l (Const . f)
get :: Lens c a -> c -> a
get lens = getWith id lens
The above type-checks but if I eta-reduce get
to
get :: Lens c a -> c -> a
get = getWith id
Then GHC (7.4.2) complains that
Couldn't match expected type `Lens c a'
with actual type `(a0 -> Const b0 a0) -> c0 -> Const b0 c0'
Expected type: Lens c a -> c -> a
Actual type: ((a0 -> Const b0 a0) -> c0 -> Const b0 c0)
-> c0 -> b0
In the return type of a call of `getWith'
In the expression: getWith id
I can understand that if the function didn't have an explicit type-signature then eta-reduction in combination with the monomorphism restriction might confuse the type inference, especially when we are dealing with higher rank types, but in this case I'm not sure what's going on.
What causes GHC to reject the eta-reduced form and is this a bug/limitation in GHC or some fundamental problem with higher rank types?
Lens
type expanded? – Ingo