I have the following code in a .hs file
module TypeInference1 where
f :: Num a => a -> a -> a
f x y = x + y + 3
Then if I check the type of f, I obtain the following result, which is ok:
*TypeInference1> :t f
f :: Num a => a -> a -> a
If I pass to f one parameter of type fractional and check its type I obtain:
*TypeInference1> :t f 1.0
f 1.0 :: Fractional a => a -> a
But on the other hand if I change the f by setting a division operation on one of its arguments, as follows:
f x y = x/2 + y + 3
I obtain the following error:
5-typeInference1.hs:4:9: error:
• Could not deduce (Fractional a) arising from a use of ‘/’
from the context: Num a
bound by the type signature for:
f :: forall a. Num a => a -> a -> a
at 5-typeInference1.hs:3:1-25
Possible fix:
add (Fractional a) to the context of
the type signature for:
f :: forall a. Num a => a -> a -> a
• In the first argument of ‘(+)’, namely ‘x / 2’
In the first argument of ‘(+)’, namely ‘x / 2 + y’
In the expression: x / 2 + y + 3
Why does this happen and why the type can not be deduced when I change the function f as above?
Short answer: by specifying Num a => a -> a -> a you claim that f can deal with all as that are members of the Num typeclass, but the (/) can only work with types that are members of the Fractional typeclass.
Fractional is a "sub" typeclass of Num. That means that all types that are a member of Fractional are a member of Num, but this does not hold vice versa.
By specifying as type for f:
f :: Num a => a -> a -> a
You say that f can deal with all types a that are members of the Num typeclass. But that is incorrect if you define f as f x y = x/2 + y + 3, since x/2 means that x should be a type that is a member of Fractional. Indeed (/) has type (/) :: Fractional a => a -> a -> a. You thus should make f more restrictive, such that you can only pass values that are of type a with a a member of the Fractional typeclass:
f :: Fractional a => a -> a -> a
f x y = x/2 + y + 3
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