2

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    |

3 Answers 3

7

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"
Sign up to request clarification or add additional context in comments.

1 Comment

Prefer readLn to getLine+read: it Does The Right Thing with exceptions when the input can't be parsed. In this particular case it doesn't matter, but it's a good habit to get into.
5

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.

Comments

4

To remove the first warning, replace tabs with spaces.

To fix the error, add num to <=3

if num >=1 && num <=3

You will also need to add a putStrLn here:

else putStrLn "Wrong health range indicated"

Also, you can't use getLine as in getLine <= 7. Shouldn't that be num instead? Do you really want to read another number from the user?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.