2

I am stuck behind a very simple exercise I just have to do x + y ^ sqrt z with let, but I tried:

let f x y z = x + y ^ sqrt z

but it doesn't work and complains about a type miss match when f is used and with :t (f) I get:

(f) :: (Integral b, Floating b, Num a) => a -> a -> b -> a

Can somebody explain or give an article which explains the (Integral b, Floating b, Num a) part. What I know is Num a => a "1" -> a "2" -> a "3" for f x y = x + y

x has the type of a1 and y has the type of a2 and the solution is a3 all of typeclass Num which is used for (*), (+), (^), ... .

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • 5
    That `(Integral b, Floating b, Num a)` bit is a _typeclass constraint_. Have a look at https://en.wikibooks.org/wiki/Haskell/Classes_and_types#Type_constraints and http://learnyouahaskell.com/types-and-typeclasses for some info. Another thing — there are [several different exponentiation operators](https://stackoverflow.com/a/6400628/7345298) in Haskell, and I think you want `**` rather than `^`. – bradrn Sep 24 '19 at 10:42
  • 3
    The problem is that the `^` operator expects an integer as its second input (i.e. you can write `2 ^ 3` but you can't write `2 ^ 3.0`). However, the `sqrt` function returns a floating point number. If you want to raise a number to a floating point power then you have to use the `**` operator. For example, can write `2 ** 3.0`. Hence, your function would be `let f x y z = x + y ** sqrt z`. – Aadit M Shah Sep 24 '19 at 10:58
  • 1
    Most numbers are not both `Integral` and `Floating`. – Willem Van Onsem Sep 24 '19 at 11:05

1 Answers1

3

The (^) :: (Num a, Integral b) => a -> b -> a takes as second parameter an Integral type. An integral type is something like an Int, Integer, etc.

But your sqrt :: Floating f => f -> f takes a Floating value and returns a Floating value. This thus means that the type of z needs to be a type that is both a member of the Integral and Floating typeclass. Although strictly speaking, it is possible to implement such types, the two typeclasses contradict each other in terms on what sort of types can be members.

You probably should use (**) :: Floating f => f -> f -> f here to raise a number to a floating power. We can thus define f as:

f x y z = x + y ** sqrt z

Then f has type:

f :: Floating a => a -> a -> a -> a

It thus takes three as where a is a type that is a member of the Floating typeclass, and returns an a.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555