Could not deduce (Floating a) arising from a use of `pi'

Viewed 104

circleArea is function to calculate the area of a circle given the radius r:

circleArea r = r^2 * pi

However, adding the type signature circleArea :: Num a => a -> a causes this error:

* Could not deduce (Floating a) arising from a use of `pi'
  from the context: Num a
    bound by the type signature for:
               circleArea :: forall a. Num a => a -> a
  Possible fix:
    add (Floating a) to the context of
      the type signature for:
        circleArea :: forall a. Num a => a -> a
* In the second argument of `(*)', namely `pi'
  In the expression: r * r * pi
  In an equation for `circleArea': circleArea r = r * r * pi

Using circleArea :: Floating a => a -> a, as suggested, resolves the issue.

I'm running this on repl.it.

Why isn't Num a valid typeclass here? pi has a type of Floating a -> a, isn't pi a Num as well?

1 Answers

The reason this happens is because pi has type pi :: Floating a => a. When you multiply two items, then the two operands as well as the result all have the same type, since (*) has type (*) :: Num a => a -> a -> a.

This thus means that r^2 should have the same type as pi and thus as r^2 * pi. Since pi can take any type as long as it is a Floating type, this thus means that r^2 should be Floating as well, and since (^) has type (^) :: (Num a, Integral b) => a -> b -> a, it thus means that r has the same type as r^2, and therefore r also has to be a Floating type. This thus means that both r and r^2 * pi have as type Floating.

This also makes sense. It would be rather odd that we could have an Int as result, since we multiply with something that is clearly not integral.

Related