我有以下haskell代码:
fac n = product [1..n]
taylor3s w0 f f' f'' t h = w1 : taylor3s w1 f f' f'' (t+h) h
where hp i = h^i / fac i
w1 = w0 + (hp 1) * f t w0 + (hp 2) * f' t w0 + (hp 3) * f'' t w0
taylor_results = take 4 $ taylor3s 1 f f' f'' 1 0.25
where f t x = t^4 - 4*x/t
f' t x = 4*t^3 - 4*(f t x)/t + 4*x/t^2
f'' t x = 12*t^2 - 4*(f' t x)/t + 8*(f t x)/t^2 - 8*x/t^3
taylor_results应该是taylor3s的用例。但是,数字类型推断存在问题。当我尝试编译时,这是我得到的错误:
practice.hs:93:26:
Ambiguous type variable `a' in the constraints:
`Integral a'
arising from a use of `taylor3s' at practice.hs:93:26-51
`Fractional a' arising from a use of `f' at practice.hs:93:37
Possible cause: the monomorphism restriction applied to the following:
taylor_results :: [a] (bound at practice.hs:93:0)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
有人可以帮我理解问题是什么吗?
答案 0 :(得分:8)
由于您的混合操作仅适用于仅在小数上可用的积分和运算(特别是您使用^
,其中第二个操作数必须是整数 - 如果您打算使用**
为了使两个操作数具有相同的浮点类型,haskell推断所有参数和taylor3s
的结果都具有类型Fractional a, Integral a => a
。这不是类型错误,因为理论上这种类型可能存在,但它很可能不是你想要的,因为在实践中这种类型不存在。
无论如何你得到类型错误的原因是推断类型的taylor_results
因此也是Fractional a, Integral a => a
,这是多态的,因此违反了monomorphism restriction。
如果你明确地将taylor_results
声明为taylor_results :: Fractional a, Integral a => a
或禁用单态限制,整个事情就会编译,但是不可能使用(没有定义实际实例化Integral和Fractional的类型,是废话)。
请注意,如果您解决此问题(例如将 ^
替换为**
),taylor_results
的类型仍将是多态的(它将被推断为{{1}这实际上是合理的,所以你仍然会遇到单态限制。因此,您仍然需要关闭限制,明确声明taylor_results :: (Floating a, Enum a) => [a]
的类型是多态的,或者显式声明taylor_results
的类型是实例化Floating和Enum的特定类型(例如Double)。请注意,除非您执行后者,否则每次使用时都会重新计算taylor_results
(这就是存在单态限制的原因)。
请注意,如果您解决此问题(例如,将taylor_results
替换为^
),则**
的最常规类型将为taylor_results
,但您获得的类型(除非你禁用单态限制)将是(Floating a, Enum a) => [a]
。如果你不想要双打,你要么必须明确声明taylor_results属于另一种类型(实例化Floating和Enum)或者是多态的。请注意,如果您声明它是多态的,则每次使用时都会重新计算[Double]
(这就是存在单态限制的原因)。
答案 1 :(得分:0)
似乎Haskell推断taylor3s
作为Integral
类型的返回,但事实上子函数f
等被推断为处理Fractional
类型违反了推断。
也许通过明确地告诉Haskell taylor3s
返回类型可能会有所帮助。