簡體   English   中英

如何將多態函數應用於具體類型?

[英]How to apply polymorphic function to a concrete type?

下面是我在學習 Haskell 時遇到的一個問題的提煉版本:

data A = A
data B = B

data Test = TestA A
          | TestB B

test :: (a -> a) -> (Test -> Test)
test op t =
  case t of
    TestA a -> TestA $ op a
    TestB b -> TestB $ op b

testA = test id (TestA A)
testB = test id (TestB B)

嘗試編譯它會出現以下錯誤:

無法將預期類型“B”與實際類型“a”匹配

'a' 是由 test :: (a -> a) -> Test -> Test 的類型簽名綁定的剛性類型變量

這是怎么回事? 我認為當我傳入一個多態函數時,我應該能夠將它應用於不同具體類型的值。

這里的基本問題是 Haskell 如何從類型簽名中的自由變量推斷量化。 鑒於以下類型簽名...

test :: (a -> a) -> (Test -> Test)

...類型變量a未綁定。 Haskell 自動將未綁定的類型變量轉換為通用量化約束,所以上面的類型實際上是這樣解釋的:

test :: forall a. (a -> a) -> (Test -> Test)

現在你得到的錯誤可能更有意義——類型變量a每次調用test只能與一種類型統一,這是由調用者決定的。 因此, (a -> a)函數可以是String -> StringInt -> Int或任何其他類型,但它永遠不能是同時適用於AB的函數。

但是,很明顯,當您編寫該類型簽名時,您有不同的意圖。 您希望(a -> a)函數成為類似於id的類型簽名:一個真正適用於任何值的函數,而不是某個特定選擇的特定函數a 要指定這一點,您必須使forall顯式,以便編譯器准確地知道該類型變量應如何量化:

test :: (forall a. a -> a) -> (Test -> Test)

但是,上述類型實際上在標准 Haskell 中無效。 由GHC支持,但是,通過使用Rank2TypesRankNTypes擴展,這允許“較高等級”多態性像上述類型簽名。

暫無
暫無

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

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