下面的程序類型檢查:爲什麼函數類型需要被「包裝」才能滿足類型檢查器?
{-# LANGUAGE RankNTypes #-}
import Numeric.AD (grad)
newtype Fun = Fun (forall a. Num a => [a] -> a)
test1 [u, v] = (v - (u * u * u))
test2 [u, v] = ((u * u) + (v * v) - 1)
main = print $ fmap (\(Fun f) -> grad f [1,1]) [Fun test1, Fun test2]
但這個方案失敗:
main = print $ fmap (\f -> grad f [1,1]) [test1, test2]
隨着錯誤類型:
Grad.hs:13:33: error:
• Couldn't match type ‘Integer’
with ‘Numeric.AD.Internal.Reverse.Reverse s Integer’
Expected type: [Numeric.AD.Internal.Reverse.Reverse s Integer]
-> Numeric.AD.Internal.Reverse.Reverse s Integer
Actual type: [Integer] -> Integer
• In the first argument of ‘grad’, namely ‘f’
In the expression: grad f [1, 1]
In the first argument of ‘fmap’, namely ‘(\ f -> grad f [1, 1])’
直觀,後者計劃看起來是正確的。畢竟, 以下,表面上看似乎等價程序做的工作:
main = print $ [grad test1 [1,1], grad test2 [1,1]]
它看起來像在GHC的類型系統的限制。我想知道 是什麼原因導致失敗,爲什麼存在此限制,以及除包裝函數(上面的每個Fun
)之外的任何可能的 解決方法。
(注:這是不是由單態的限制造成的;編譯 與NoMonomorphismRestriction
沒有幫助)
難道這是可怕的單態嗎? –
這不是單態限制。 – frasertweedale
這實際上是類型系統中的一個限制。失敗的程序需要對意想不到的類型進行正確的類型檢查('[test1,test2] :: [forall a。...]'是不可預測的),這是[docs](https://downloads.haskell。 org /〜ghc/latest/docs/html/users_guide/glasgow_exts.html#impredicative-polymorphism)聲稱,GHC只有「非常片狀的支持」。最好的解決方法是'newtype'包裝。或者,打開ImpredicativeTypes併爲程序的每個子項添加類型註釋,直到它被敲入。 – user2407038