簡體   English   中英

GHC / GHCi意外接受的代碼

[英]Code unexpectedly accepted by GHC/GHCi

我不明白為什么這段代碼應該通過類型檢查:

foo :: (Maybe a, Maybe b)
foo = let x = Nothing in (x,x)

由於每個組件都綁定到相同的變量x ,所以我希望此表達式的最通用類型是(Maybe a, Maybe a) 如果使用where而不是let我將得到相同的結果。 我想念什么嗎?

簡而言之, x的類型由let推廣。 這是Hindley-Milner類型推斷算法中的關鍵步驟。

具體來說, let x = Nothing最初為x分配類型Maybe t ,其中t是新鮮的類型變量。 然后,對類型進行泛化,通用地量化其所有類型變量(技術上:除了在其他地方使用的變量,但這里我們只有t )。 這導致x :: forall t. Maybe t x :: forall t. Maybe t 請注意,此類型與Nothing :: forall t. Maybe t完全相同Nothing :: forall t. Maybe t Nothing :: forall t. Maybe t

因此,每次我們在代碼中使用x時,它都表示可能不同的類型Maybe t ,就像Nothing一樣。 因此,使用(x, x)(Nothing, Nothing)類型相同。

相反,lambda 具有相同的概括步驟。 相比之下(\\x -> (x, x)) Nothing “ only”的類型為forall t. (Maybe t, Maybe t) forall t. (Maybe t, Maybe t) ,其中兩個組件都被強制為相同類型。 在這里x再次被賦予類型Maybe t ,其中t fresh,但是沒有被概括。 然后(x, x)被分配類型(Maybe t, Maybe t) 僅在最高級別上,我們才一般性地加上了forall t ,但是在這一點上太晚了,無法獲得異構對。

暫無
暫無

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

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