Печать состояния работоспособности путем сравнения числовых значений из пользовательского ввода - PullRequest
1 голос
/ 17 мая 2019

Я пытаюсь получить числовое значение от пользователя (в диапазоне 1-10) и с помощью условных выражений (if number >= 1 && <=3) выводить состояние здоровья (например, putStrLn "your health is poor"), но получаю сообщение об ошибке, которое я не могу пройти

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"

Сообщение об ошибке:

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 ]

8 голосов
/ 17 мая 2019

Одной из ближайших проблем является то, что вы пишете:

if num >=1 && <=3

вместо

if num >=1 && num <= 3

Но даже тогда он не будет работать, поскольку тип num равен String (поскольку вы используете getLine :: IO String, и вы не можете сравнить его с числовыми значениями.

Вам потребуется использовать что-то вроде read, чтобы «прочитать» строку в числовое значение (обратите внимание, что она потерпит крах, если строка не будет представлять числовое значение).

Далее, выражения типа getLine <= 7 также не будут работать по той же причине: getLine :: IO String, поэтому вы не можете сравнить IO String с числовым значением.

Этот код будет работать:

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"

Однако я бы порекомендовал вам взглянуть на case выражения или / и MultiWayIf, так как это может быть лучшим способом написания этого кода:

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"
6 голосов
/ 17 мая 2019

Вы делаете здесь некоторые ошибки, в основном с типами:

Линия:

num <- getLine

означает, что num - это String, но позже вы будете использовать его как число. Возможно, вы захотите использовать readLn :: Read a => IO a, и, вероятно, лучше также указать тип:

num <- <b>readLn :: IO Int</b>

В ваших первых if случаях:

if num >=1 && <=3

Неверно, так как он анализируется как (num >= 1) && (<= 3). Таким образом, правильный оператор не a Bool, а (Num n, Ord n) => n -> Bool, так что функция. Функция не True или False.

Вы должны заменить его на:

if num >=1 && <b>num <=3</b>

Позже вы пишете:

if num >=4 && getLine <=7

но и здесь типы не совпадают: getLine имеет тип IO String, так что это не число, даже не IO Int. Вы, вероятно, хотите повторно использовать num, поэтому:

if num >=4 && <b>num</b> <=7

Наконец, в else записи вы пишете:

else <b>"Wrong health range indicated"</b>

Но тип health равен IO (), а не String, поэтому вы должны использовать putStrLn:

else <b>putStrLn</b> "Wrong health range indicated"

Вы можете выделить putStrLn в:

health :: IO ()
health = do 
    putStrLn "State your health using numbers 1 - 10: "
    num <- <b>readLn :: IO Int</b>
    --putStrLn "Your health is: "
    <b>putStrLn</b> $
        if <b>num <= 0 || num > 10</b> 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"

Вышеприведенное все еще не идеально, так как чтение строки в Int может пойти не так. Так что это может помочь использовать readMaybe здесь, чтобы сделать программу более безопасной.

5 голосов
/ 17 мая 2019

Чтобы убрать первое предупреждение, замените табуляцию пробелами.

Чтобы исправить ошибку, добавьте num к <=3

if num >=1 && num <=3

Вам также необходимо добавить putStrLn здесь:

else putStrLn "Wrong health range indicated"

Кроме того, вы не можете использовать getLine, как в getLine <= 7. Разве это не должно быть num вместо этого? Вы действительно хотите прочитать другой номер от пользователя?

...