我有以下 2 級功能:
polyOn :: (f a -> f b -> c) -> (forall k . k -> f k) -> a -> b -> c
polyOn bifunc func x y =
bifunc (func x) (func y)
我想翻轉它
flippedPolyOn :: (forall k . k -> f k) -> (f a -> f b -> c) -> a -> b -> c
flippedPolyOn =
flip polyOn
但 ghc 抱怨:
? Couldn't match type ‘k0 -> f k0’ with ‘forall k. k -> f k’
Expected type: (f a -> f b -> c) -> (k0 -> f k0) -> a -> b -> c
Actual type: (f a -> f b -> c)
-> (forall k. k -> f k) -> a -> b -> c
? In the first argument of ‘flip’, namely ‘polyOn’
In the expression: flip polyOn
In an equation for ‘flippedPolyOn’: flippedPolyOn = flip polyOn
? Relevant bindings include
flippedPolyOn :: (forall k. k -> f k) -> (f a -> f b -> c) -> a -> b -> c
(bound at XXXXXX:75:1)
|
76 | flip polyOn
| ^^^^^^
所以它看起來像 ghc 在某些時候將 專門化為(它稱之為)forall k. k -> f k的特定值。kk0
為什么 ghc 會這樣做?這種專業化可以避免嗎?
uj5u.com熱心網友回復:
GHC < 9
問題是 GHC < 9.x 不支持不可預測的多型性。本質上,您要做的是實體化
flip :: (a0->b0->c0) -> b0->a0->c0
通過這種方式:
a0 ~ (f a -> f b -> c)
b0 ~ (forall k . k -> f k)
c0 ~ a -> b -> c
型別推斷與a0和沒有問題c0,但不允許b0以這種方式進行選擇。事實上,如果不支持不可預測的多型性,像這樣的型別變數b0只能用單型別(沒有foralls的型別)實體化。
我們需要行內flip使這項作業
flippedPolyOn x y = polyOn y x
GHC >= 9
默認情況下,在 GHC 9 中,我們仍然會收到型別錯誤,但有更好的錯誤訊息,指出不可預測性問題:
Cannot instantiate unification variable `b0'
with a type involving polytypes: forall k. k -> f k
我們可以通過打開不可預測的型別來按原樣進行代碼型別檢查:
{-# LANGUAGE RankNTypes, ImpredicativeTypes #-}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/347706.html
