下面描述的所有實驗都是用GHC 8.0.1完成的。消失約束的情況:較高等級類型的奇異點
此問題是RankNTypes with type aliases confusion的後續行動。這個問題有歸結爲類型的像這樣的功能...
{-# LANGUAGE RankNTypes #-}
sleight1 :: a -> (Num a => [a]) -> a
sleight1 x (y:_) = x + y
...這是由類型檢查被拒絕......
ThinAir.hs:4:13: error:
* No instance for (Num a) arising from a pattern
Possible fix:
add (Num a) to the context of
the type signature for:
sleight1 :: a -> (Num a => [a]) -> a
* In the pattern: y : _
In an equation for `sleight1': sleight1 x (y : _) = x + y
...因爲higher-排名限制Num a
cannot be moved outside of the type of the second argument(如果我們改爲a -> a -> (Num a => [a])
,將是可能的)。既如此,我們最終要更高秩約束添加到已經量化了整個事情的變量,那就是:
sleight1 :: forall a. a -> (Num a => [a]) -> a
有了這個概括做,我們會盡量簡化例子一點。讓我們來代替(+)
的東西,不需要Num
,並從該結果的脫開問題的參數的類型:
sleight2 :: a -> (Num b => b) -> a
sleight2 x y = const x y
這不就像工作之前(保存在錯誤略有變化消息):
ThinAir.hs:7:24: error:
* No instance for (Num b) arising from a use of `y'
Possible fix:
add (Num b) to the context of
the type signature for:
sleight2 :: a -> (Num b => b) -> a
* In the second argument of `const', namely `y'
In the expression: const x y
In an equation for `sleight2': sleight2 x y = const x y
Failed, modules loaded: none.
使用const
這裏,然而,也許是不必要的,所以我們可能會嘗試寫自己的實現:
sleight3 :: a -> (Num b => b) -> a
sleight3 x y = x
令人驚訝的是,這實際上有效!
Prelude> :r
[1 of 1] Compiling Main (ThinAir.hs, interpreted)
Ok, modules loaded: Main.
*Main> :t sleight3
sleight3 :: a -> (Num b => b) -> a
*Main> sleight3 1 2
1
更奇怪的是,似乎有沒有實際Num
上的第二個參數約束:
*Main> sleight3 1 "wat"
1
我不太清楚如何作出這樣的理解。也許我們可以這樣說,就像我們可以在的範圍內一樣,只要我們從不評價它,只要它不用於統一右側的任何地方,那麼一個不可滿足的約束就可以堅持在一種類型中。然而,這感覺就像是一個非常弱的類比,特別是因爲我們通常認爲非嚴格性是一種涉及價值而不是類型的概念。此外,這讓我們從掌握世界String
與Num b => b
如何統一 - 假設這種事實際上發生了,我並不十分確定。那麼,什麼是一個準確的描述當約束似乎以這種方式消失的時候呢?
我覺得有些自然,例如,在類型'f :: A - >(x - > B) - > C' in'_positive_(或covariant)的位置中''x'。粗略地說,'f'很有希望提供_'x'而不是從外部請求它。這擴展到'y :: C a => a'。而且,每種類型都使用'y',GHC必須提供一個字典以獲得'a'類型的值 - 所以如果沒有這樣的字典,它會抱怨。 – chi
這似乎很奇怪,我同意。可能只有GHC製造商知道'forall'背後發生了什麼樣的魔術:) – Shersh
@chi從正面和負面的角度來看問題的確很明顯。有趣的是,如果將約束的直觀視圖作爲某種受限量化(例如,「Num a => a'代表'Num'中某種類型'a''),並且開始看到它們,那麼事情在這裏纔有意義因爲實質上,這些功能來自詞典。 – duplode