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?
What's the difference between Integer and Int ? Integer can represent arbitrarily large integers, up to using all of the storage on your machine. Int can only represent integers in a finite range.
Num is a typeclass — a group of types — which includes all types which are regarded as numbers. The (Num a) => part of the signature restricts a to number types – or, in Haskell terminology, instances of Num .
The workhorse for converting from integral types is fromIntegral , which will convert from any Integral type into any Num eric type (which includes Int , Integer , Rational , and Double ): fromIntegral :: (Num b, Integral a) => a -> b.
Type Classes are a language mechanism in Haskell designed to support general overloading in a principled way. They address each of the concerns raised above. They provide concise types to describe overloaded functions, so there is no expo- nential blow-up in the number of versions of an overloaded function.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With