Haskell数字类型的问题

min*_*vor 5 haskell type-inference

我有以下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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我理解问题是什么吗?

sep*_*p2k 8

由于您只是在仅在小数上可用的积分和运算上可用的混合操作(特别是您使用^第二个操作数必须是整数的 - **如果您打算使两个操作数具有相同的浮点类型,则使用),haskell推断所有参数和结果taylor3s都有类型Fractional a, Integral a => a.这不是类型错误,因为理论上这种类型可能存在,但它很可能不是你想要的,因为在实践中这种类型不存在.

无论如何,你得到类型错误的原因是推断类型taylor_results因此也是Fractional a, Integral a => a多态的,因此违反了单态限制.

如果你想明确声明taylor_results作为taylor_results :: Fractional a, Integral a => a或禁用单态的限制,整个事情会编译,但无法使用(没有定义,实际上实例积分和分数,这将是废话型).

请注意,如果你解决这个问题(例如通过更换^**)的类型taylor_results仍然是多态(它会被推断为taylor_results :: (Floating a, Enum a) => [a],这实际上是合理的),所以你还是会碰到单态的限制.因此,您仍然需要关闭限制,显式声明类型为taylor_results多态或显式声明类型为taylor_results实例化Floating和Enum的特定类型(例如Double).请注意,除非您执行后者,taylor_results否则每次使用时都会重新计算(这就是存在单态限制的原因).

请注意,如果你解决这个问题(例如通过更换^**)的最普遍的类型taylor_results将是(Floating a, Enum a) => [a],但是你得到的类型(除非您禁用单态的限制)将[Double].如果你不想要双打,你要么必须明确声明taylor_results属于另一种类型(实例化Floating和Enum)或者是多态的.请注意,如果您声明它是多态的,taylor_results则每次使用它时都会重新计算(这就是存在单态限制的原因).