Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I get: Could not deduce (Fractional a) arising from a use of ‘/’?

Tags:

haskell

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?

like image 892
Flowryn Avatar asked Dec 17 '22 15:12

Flowryn


1 Answers

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
like image 75
Willem Van Onsem Avatar answered Mar 07 '23 16:03

Willem Van Onsem