下面的程序类型检查:为什么函数类型需要被“包装”才能满足类型检查器?
{-# 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