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 practice.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 oftaylor3shave the typeFractional 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_resultsis consequently alsoFractional a, Integral a => awhich is polymorphic and thus violates the monomorphism restriction.If you would explicitly declare
taylor_resultsastaylor_results :: Fractional a, Integral a => aor 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 oftaylor_resultswill still be polymorphic (it will be inferred astaylor_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 oftaylor_resultsto be polymorphic or explicitly declare the type oftaylor_resultsto be a specific type that instantiates Floating and Enum (e.g. Double). Note that unless you do the latter,taylor_resultswill 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 oftaylor_resultswill 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_resultswill be recalculated each time you use it (which is why the monomorphism restriction exists).