Reputation: 40386
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?
Upvotes: 5
Views: 513
Reputation: 370415
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).
Upvotes: 8
Reputation: 527298
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.
Upvotes: 0