I am trying to get a numeric value from the user (ranging 1-10) and using conditional statements (if number >= 1 && <=3) print out health status (e.g. putStrLn "your health is poor") but getting error message that I can't go past
health :: IO ()
health = do
putStrLn "State your health using numbers 1 - 10: "
num <- getLine
--putStrLn "Your health is: "
if num >=1 && <=3
then
do putStrLn "Your health is poor"
else if num >=4 && getLine <=7
then putStrLn "Your health is OK"
else if num >=8 && getLine<=10
then putStrLn "your health is fanstastic"
else "Wrong health range indicated"
Error message:
healthCheck.hs:9:1: warning: [-Wtabs]
Tab character found here, and in five further locations.
Please use spaces instead.
|
9 | --putStrLn "Your health is: " | ^^^^^^^^
healthCheck.hs:10:39: error: parse error on input ‘<=’
|
10 | if num >=1 && <=3 |
One immediate problem is that you write:
if num >=1 && <=3
instead of
if num >=1 && num <= 3
But even then it will not work since the type of num is String (since you use getLine :: IO String, and you cannot compare it with numeric values.
You would need to use something like read to "read" the string into a numeric value (note that it'll crash if the string does not represent a numeric value).
Next, expressions like getLine <= 7 will not work either, for the same reason: getLine :: IO String, so you cannot compare IO String with a numeric value.
This code will work:
health :: IO ()
health = do
putStrLn "State your health using numbers 1 - 10: "
str <- getLine
let num = read str
--putStrLn "Your health is: "
if (num >=1 && num <=3 )
then putStrLn "Your health is poor"
else if num >=4 && num <=7
then putStrLn "Your health is OK"
else if num >=8 && num <=10
then putStrLn "your health is fanstastic"
else putStrLn "Wrong health range indicated"
However I'd recommend you to look at case expressions or/and MultiWayIf as this may be a better way of writing this code:
health :: IO ()
health = do
putStrLn "State your health using numbers 1 - 10: "
str <- getLine
case read str of
num | num >= 1 && num <= 3 -> putStrLn "Your health is poor"
num | num >= 4 && num <= 7 -> putStrLn "Your health is OK"
num | num >= 8 && num <=10 -> putStrLn "your health is fanstastic"
_ -> putStrLn "Wrong health range indicated"
You make some mistakes here, mainly with the types:
The line:
num <- getLine
means that num is a String, but you later use it as a number. You probably want to use readLn :: Read a => IO a, and probably it is better to specify the type as well:
num <- readLn :: IO Int
In your first if cases:
if num >=1 && <=3
Is wrong since it is parsed as (num >= 1) && (<= 3). The right operator is thus not a Bool, but an (Num n, Ord n) => n -> Bool, so a function. A function is not True or False.
You should replace it with:
if num >=1 && num <=3
Later you write:
if num >=4 && getLine <=7
but here again the types do not match: getLine has type IO String, so it is not a number, it is even not an IO Int. You probably want to reuse the num, so:
if num >=4 && num <=7
Finally in the else stament, you write:
else "Wrong health range indicated"
But the type of health is IO (), not String, you thus should use putStrLn:
else putStrLn "Wrong health range indicated"
You can factor the putStrLn out, into:
health :: IO ()
health = do
putStrLn "State your health using numbers 1 - 10: "
num <- readLn :: IO Int
--putStrLn "Your health is: "
putStrLn $
if num <= 0 || num > 10 then "Wrong health range indicated"
else if num <= 3 then "Your health is poor"
else if num <= 7 then "Your health is OK"
else "your health is fanstastic"
The above is still not ideal, since reading a string into an Int can go wrong. So it might help to use readMaybe here to make the program safer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With