我在玩 van Laarhoven 镜头时遇到了一个问题,即类型检查器拒绝了良好类型函数的 eta 缩减形式:
{-# 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
上述类型检查,但如果我 eta-reduceget
到
get :: Lens c a -> c -> a
get = getWith id
然后 GHC (7.4.2) 抱怨说
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
我可以理解,如果函数没有明确的类型签名,那么 eta-reduction 与单态限制相结合可能会混淆类型推断,尤其是当我们处理更高级别的类型时,但在这种情况下我不是确定发生了什么。
是什么导致 GHC 拒绝 eta-reduced 形式,这是 GHC 中的错误/限制还是更高级别类型的一些基本问题?