簡體   English   中英

“Eta reduce”並不總是在Haskell中舉行?

[英]"Eta reduce" is not always held in Haskell?

我發現我可以說

{-# LANGUAGE RankNTypes #-}
f1 :: (forall b.b -> b) -> (forall c.c -> c)
f1 f = id f

(並且 HLint 告訴我我可以在這里做“Eta reduce”),但是

f2 :: (forall b.b -> b) -> (forall c.c -> c)
f2 = id

編譯失敗:

Couldn't match expected type `c -> c'
            with actual type `forall b. b -> b'
Expected type: (forall b. b -> b) -> c -> c
  Actual type: (forall b. b -> b) -> forall b. b -> b
In the expression: id
In an equation for `f2': f2 = id

實際上我在更復雜的情況下也有類似的問題,但這是我能想到的最簡單的例子。 因此,要么 HLint 無法在此處提供適當的建議,要么編譯器應檢測到這種情況,是嗎?

更新

另一個令人着迷的問題看起來很相似。 然而,盡管這兩個答案都非常有用,但都不讓我滿意,因為它們似乎沒有觸及問題的核心。

例如,我什至不允許為建議的 rank 2 類型分配id

f2 :: (forall b.b -> b) -> (forall c.c -> c)
f2 = id :: (forall b.b -> b) -> (forall c.c -> c)

如果問題僅與類型推斷有關,則應使用顯式類型符號來解決它(id 具有類型a -> a ,並且它已被約束為(forall bb -> b) -> (forall cc -> c) 。因此證明這種使用是合理的, (forall bb -> b)必須匹配(forall cc -> c) ,這是真的)。 但上面的例子表明情況並非如此。 因此,這是“eta reduce”的真正例外:您必須向雙方顯式添加參數才能將等級 1 類型的值轉換為等級 2 類型的值。

但是為什么會有這樣的限制呢? 為什么計算機不能自動統一等級 1 類型和等級 2 類型(忘記類型推斷,所有類型都可以通過符號給出)?

我不確定 HLint 是否知道RankNTypes ,也許不知道。

事實上,在擴展的情況下,eta 減少通常是不可能的。 GHC 不能只是統一a->a(forall bb -> b) -> (forall cc -> c) ,否則它會完全搞亂它對 Rank1-code 1 的類型推斷能力。 OTOH,將(forall bb -> b)a參數統一起來不是問題; 結果被確認為(forall bb -> b)(forall cc -> c)匹配。


1考慮map id [(+1), (*2)] 如果允許id具有您正在處理的類型,編譯器最終可能會為多態Num函數生成不同的實例選擇,這當然是不可能的。 還是應該? 我不確定,仔細想想……

無論如何,我很確定它證明了使用 RankNTypes,完全類型推斷是不可能的,因此至少要在 Rank1 子集中獲得它,GHC 通常必須默認將此作為不太可能的多態性選擇。

暫無
暫無

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

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