Question

I'm still very much trying to get into haskell, but I've noticed something that annoyed me quite a bit.

In the book "Learn You a Haskell for Great Good!" there's this part that shows the use of guards in pattern matching, in the case of the book it was a small function that calculates the bmi of a person, it went a little something like this (parts changed slightly to not infringe copyright or whatever):

bmiCalc :: (RealFloat a) => a -> a -> String
bmiCalc weight height
    | bmi <= 18.5 = "skinny"
    | bmi <= 25.0 = "normal"
    | bmi <= 30.0 = "fat"
    | otherwise   = "obese"
    where bmi = weight / height ^ 2

That's all fine and dandy the code works as advertised, but I thought, what if it also showed what the bmi it calculated was along with the text?

So I re-wrote the code to this:

bmiCalc :: (RealFloat a) => a -> a -> String
bmiCalc weight height
    | bmi <= 18.5 = "skinny, " ++ show bmi
    | bmi <= 25.0 = "normal, " ++ show bmi
    | bmi <= 30.0 = "fat, "    ++ show bmi
    | otherwise   = "obese, "  ++ show bmi
    where bmi = weight / height ^ 2

Expecting "show" to work like .toString does in java and c#
Boy was I wrong.

ghci gave me this big nasty error message:

Could not deduce (Show a) arising from a use of `show'
from the context (RealFloat a)
  bound by the type signature for
             bmiCalc :: RealFloat a => a -> a -> String
  at file.hs:1:16-48
Possible fix:
  add (Show a) to the context of
    the type signature for bmiCalc :: RealFloat a => a -> a -> String
In the second argument of `(++)', namely `show bmi'
In the expression: "skinny, " ++ show bmi
In an equation for `bmiCalc':
    bmiCalc weight height
      | bmi <= 18.5 = "skinny, " ++ show bmi
      | bmi <= 25.0 = "normal, " ++ show bmi
      | bmi <= 30.0 = "fat, " ++ show bmi
      | otherwise = "obese, " ++ show bmi
      where
          bmi = weight / height ^ 2
Failed, modules loaded: none.

why is that? why doesn't it allow me to append what appears to return a string, to a string? I mean as far as I've understood "skinny, " ++ show bmi is a string... which is exactly what the type signature says I have to return

so what did I do wrong here?

Was it helpful?

Solution

Change the type signature to:

bmiCalc :: (RealFloat a, Show a) => a -> a -> String

Because you want to use the member function show, from the Show typeclass; but you haven't specified that in the function constraint, and ghci has no way to infer that to be correct.

OTHER TIPS

RealFloat isn't a showable type. You'll have to add a show constraint.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top