如何才能ETA-降低类型错误井类型的函数的结果?(How can eta-reduction of

2019-09-02 02:41发布

我玩弄面包车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-减少get

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-减少与单态的限制可能会混淆类型推断,尤其是当我们面对的是更高级别类型的组合,但在这种情况下,我不肯定发生了什么事。

是什么原因导致GHC拒绝ETA还原形式,这是在GHC的错误/限制或更高级别类型的一些根本问题?

Answer 1:

我会说,原因并不在η还原本身,问题是,随着RankNTypes你失去主要类型和类型推断。

同类型推断的问题与高阶行列推断的类型时λx.M服从规则

     Γ, x:σ |- M:ρ
----------------------
  Γ |- λx:σ.M : σ→ρ

我们不知道是什么类型σ我们应该选择x 。 在辛德米尔纳型系统的情况下,我们只限于类型量词免费类型x和推理是可能的,但不是任意排名类型。

因此,即使RankNTypes ,当编译器遇到的一个术语没有明确的类型信息,它诉诸辛德米尔纳并推断其秩1主要类型。 然而,在你的情况,你需要的类型getWith id是等级2,因此编译器本身不能推断它。

你明确的情况下,

get lens = getWith id lens

对应于其中的类型的情况x已经给出明确λ(x:σ).Mx 。 编译器知道类型lens类型检查前getWith id lens

在减少的情况下,

get = getWith id

编译器推断类型getWidth id在它自己的,所以它与辛德米尔纳坚持和推断秩-1型不足。



Answer 2:

其实这是相当直接:GHC 推断表达的类型,然后开始在整个统一他们= 。 这工作始终正常,当只有等级1类型身边,因为最具多态性的一个选择(这是明确的); 所以这是可能的任何统一都将取得成功。

但它不会选择一个更一般的秩-2型,即使这将是可能的,所以getWith id被推断为((a -> Const aa) -> c -> Const ac) -> (c -> a) ,而不是(forall f . Functor f => (a -> fa) -> c -> fc) -> (c -> a) 。 我想,如果没有GHC做这样的东西,传统的等级1的类型推断不会在所有的工作了。 或者它只是永远不会终止,因为不存在一个定义良好的最具多态性的秩n型。

这并不能解释为什么它不能从看到get的签名,它需要选择等级2这里,但想必有应该是一个很好的理由,以及。



文章来源: How can eta-reduction of a well typed function result in a type error?