Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error compiling - could not deduce Ord

Tags:

types

haskell

nRaizes :: Floating a => a -> a -> a -> a
  nRaizes a b c = let r = b^2 - 4 * a * c
                  in if r < 0
                     then 0
                     else if r == 0
                     then 1
                     else 2

So I got this code, where I'm checking for the number of roots of an equation. But when I try to compile it, it gives me this.

 Could not deduce (Ord a) arising from a use of ‘<’
    from the context (Floating a)
      bound by the type signature for
                 nRaizes :: Floating a => a -> a -> a -> a
      at Ficha1.hs:29:14-43
    Possible fix:
      add (Ord a) to the context of
        the type signature for nRaizes :: Floating a => a -> a -> a -> a
    In the expression: r < 0
    In the expression: if r < 0 then 0 else if r == 0 then 1 else 2
    In the expression:
      let r = b ^ 2 - 4 * a * c
      in if r < 0 then 0 else if r == 0 then 1 else 2

Ficha1.hs:33:32:
    Could not deduce (Eq a) arising from a use of ‘==’
    from the context (Floating a)
      bound by the type signature for
                 nRaizes :: Floating a => a -> a -> a -> a
      at Ficha1.hs:29:14-43
    Possible fix:
      add (Eq a) to the context of
        the type signature for nRaizes :: Floating a => a -> a -> a -> a
    In the expression: r == 0
    In the expression: if r == 0 then 1 else 2
    In the expression: if r < 0 then 0 else if r == 0 then 1 else 2

Yes, I'm a begginer. I seriously cannot even understand what is wrong. It's a floating number, why can't it compare it? I just know it has something to do with the signature, because if I remove it it works

like image 751
Pedro Fernandes Avatar asked Sep 14 '25 10:09

Pedro Fernandes


1 Answers

It's a floating number, why can't it compare it?

No, it is not per se a floating point number. Floating strictly speaking means that you can perform trigometric and hyperbolic functions on it. Whether that means it is a floating point number, is a different aspect (although it is a bit related).

That being said, it thus does not imply that you can compare two elements. This is however not a problem: we can add the typeclass Ord a to it:

nRaizes :: (Floating a, Ord a) => a -> a -> a -> a
nRaizes a b c = let r = b^2 - 4 * a * c
                  in if r < 0
                     then 0
                     else
                         if r == 0
                         then 1
                         else 2

But we defined our function too strict. Why do we need trigometric and hyperbolic functions here? Why not define the function over *all possible number representation with Ord? We can thus generalize the function to:

nRaizes :: (Num a, Ord a) => a -> a -> a -> a
nRaizes a b c = let r = b^2 - 4 * a * c
                  in if r < 0
                     then 0
                     else
                         if r == 0
                         then 1
                         else 2

Furthermore, although most people like Christmas. Most programmers do not like Christmas-trees as function definitions. Perhaps a more elegant way to do this is with guards instead of if-then-elses:

nRaizes :: (Num a, Ord a) => a -> a -> a -> a
nRaizes a b c | r < 0 = 0
              | r == 0 = 1
              | otherwise = 2
    where r = b*b - 4*a*c

Finally we produce three possible outputs: 0, 1, and 2. But nothing says that the type of output should be the same as the type of a, b and c. So we can split the type of input and output into:

nRaizes :: (Num a, Ord a, Num b) => a -> a -> a -> b
nRaizes a b c | r < 0 = 0
              | r == 0 = 1
              | otherwise = 2
    where r = b*b - 4*a*c
like image 133
Willem Van Onsem Avatar answered Sep 17 '25 03:09

Willem Van Onsem