簡體   English   中英

如何通過減少良好類型的函數來減少類型錯誤?

[英]How can eta-reduction of a well typed function result in a type error?

我正在玩van Laarhoven鏡頭並遇到一個問題,其中類型檢查器拒絕了et-reduced形式的良好類型的功能:

{-# 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-reduce 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-reduction可能會混淆類型推斷,特別是當我們處理更高級別的類型時,但在這種情況下我不是確定發生了什么。

是什么導致GHC拒絕eta減少形式,這是GHC中的錯誤/限制或更高等級類型的一些基本問題?

我要說的原因不在於η-減少本身,問題在於使用RankNTypes你會丟失主要類型和類型推斷。

高階排序類型推斷的問題是在推斷遵循規則的λx.M的類型時

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

我們不知道我們應該為x選擇什么類型的σ。 在Hindley-Milner類型系統的情況下,我們將自己限制為x類型 - 量詞 - 無類型,並且推理是可能的,但不是任意排序類型。

因此,即使使用RankNTypes ,當編譯器遇到沒有顯式類型信息的術語時,它會轉向Hindley-Milner並推斷出它的rank-1主體類型。 但是,在您的情況下, getWith id所需的類型是rank-2,因此編譯器無法自行推斷它。

你的明確案例

get lens = getWith id lens

對應於已經明確給出x的類型λ(x:σ).Mx 在類型檢查getWith id lens之前,編譯器知道lens類型。

在減少的情況下

get = getWith id

編譯器必須自己推斷getWidth id的類型,因此它堅持使用Hindley-Milner並推斷出rank-1類型不足。

實際上它非常簡單:GHC推斷每個表達式的類型,然后開始將它們統一在= 當只有rank-1類型時,這總是很好,因為選擇了最多態的(這是明確定義的); 所以任何可能的統一都會成功。

但它不會選擇更一般的rank-2-type,即使這是可能的,所以getWith id被推斷為((a -> Const aa) -> c -> Const ac) -> (c -> a) ,而不是(forall f . Functor f => (a -> fa) -> c -> fc) -> (c -> a) 我想如果GHC確實做了這樣的事情,傳統的1級類型推斷就不再適用了。 或者它永遠不會終止,因為不存在一個明確定義的最多態的rank-n類型。

這並沒有解釋為什么它不能從get的簽名中看到它需要在這里選擇排名-2,但可能也有一個很好的理由。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM