Going over the "Learn yourself..." book I encountered a BMI calculator app. The app, so far, takes a list of pairs of Double and returns a list of Double:
calcBMI :: [(Double, Double)] -> [Dobule]
calcBMI xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height ^ 2
Trying to apply another function to each element of the returned list I tried map declareBMI head calcBMI [(w, h) | w <- [60..70], h <- [1.65]]
but got an error (where declareBMI
was defined):
declareBMI :: Double -> String
declareBMI bmi
| bmi <= 18.5 = "Skinny"
| bmi <= 25 = "Norm"
| bmi <=30 = "Overweight"
| otherwise = "OBESE!"
After viewing the definition of map
(i.e. map f x:xs = f x : map f xs
) I figured out the problem: I'm trying to call head
on the remainder of a lazy list, meaning the interpreter tries to first run calcBMI
and only then head
-ing the result... and this will of course fail because calcBMI
requires a list of pairs.
So, my question is
- is there a way to force an eager evaluation of the
calcBMI
function so I can runhead
on the resultant list? - Is there a better way then forcing eager evaluation to allow me to
head
each element of the resultant list?