开发者

problems with Haskell's Number Types

开发者 https://www.devze.com 2022-12-30 14:44 出处:网络
I have the following haskell code: fac n = product [1..n] taylor3s w0 f f\' f\'\' t h = w1 : taylor3s w1 f f\' f\'\' (t+h) h

I have the following haskell code:

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 is supposed to be a use case of taylor3s. However, there is something wrong with the number type inferencing. When I try to compile, this is the error I get:

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 pr开发者_如何学Goactice.hs:93:0)
    Probable fix: give these definition(s) an explicit type signature
                  or use -XNoMonomorphismRestriction

Can someone help me with understanding what the problem is?


Since you're mixing operations that are only available on integrals and operations that are only available on fractionals (specifically you use ^ of which the second operand must be integral - use ** if you intend for both operands to have the same Floating type), haskell infers that all arguments and the result of taylor3s have the type Fractional a, Integral a => a. This is not a type error, since theoretically such a type could exist, but it's most likely not what you want because in practice such a type does not exist.

The reason that you get a type error anyway is that the inferred type of taylor_results is consequently also Fractional a, Integral a => a which is polymorphic and thus violates the monomorphism restriction.

If you would explicitly declare taylor_results as taylor_results :: Fractional a, Integral a => a or disable the monomorphism restriction, the whole thing would compile, but be impossible to use (without defining a type that actually instantiates Integral and Fractional, which would be nonsense).

Note that if you fix this (for example by replacing ^ with **) the type of taylor_results will still be polymorphic (it will be inferred as taylor_results :: (Floating a, Enum a) => [a], which is actually sensible), so you will still run into the monomorphism restriction. So you still need to either turn the restriction off, explicitly declare the type of taylor_results to be polymorphic or explicitly declare the type of taylor_results to be a specific type that instantiates Floating and Enum (e.g. Double). Note that unless you do the latter, taylor_results will be recalculated each time you use it (which is why the monomorphism restriction exists).

Note that if you fix this (for example by replacing ^ with **) the most general type of taylor_results will be (Floating a, Enum a) => [a], however the type you get (unless you disable the monomorphism restriction) will be [Double]. If you don't want doubles, you either have to explicitly declare taylor_results to be of another type (which instantiates Floating and Enum) or to be polymorphic. Note that if you declare it to be polymorphic, taylor_results will be recalculated each time you use it (which is why the monomorphism restriction exists).


It appears that Haskell is inferring the return of taylor3s as being an Integral type, but then the fact that the subfunctions f etc are inferred as dealing with Fractional types violates that inference.

Perhaps by explicitly telling Haskell the taylor3s return type might help.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号