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 a
s 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