Написание циклов для интерактивного ввода-вывода: проблемы с нотацией и версткой - PullRequest
12 голосов
/ 17 апреля 2011

Я только начал Haskell, и это меня полностью смущает. Я делал Java и Python, и это имело для меня больше смысла.

В настоящее время я пытаюсь получить пользовательский ввод, проверить, если он действителен, если нет: вывести ошибку и получить ввод снова; если действительный: выведите из него логическое значение.

Точнее, я хочу ввод да / нет, где 'y' выдаст True, 'n' выдаст False, а любой другой ввод выведет сообщение в командную строку и попросит ввести y / n еще раз.

например:.

Continue? y/n:
> assd
Invalid input.
Continue? y/n:
> y
(something happens)
Continue? y/n:
> n
(Close program)

Запись в формате знакомств, такая функция:

boolean inputBool() {
    while(True) {
       str = input("Continue? y/n: ");
       if (str == "y") {
           return True;
       } else if (str == "n") {
           return False;
       } else {
           print("Invalid input");
       }
}

--main program--

while(inputBool()) {
    doSomething();
}

Так как я только начал основывать haskell (сегодня на самом деле), я не очень понимаю, что я могу или не могу сделать. Я думал о чем-то похожем на:

yesno :: Bool
yesno = do
        putStr "Continue? y/n: " 
        str <- readLn
        if (str == "y") then True else (
            if (str == "n") then False else (
                do
                putStrLn "Invalid input."
                yesno
            )    
        )

Что не работает по многим причинам. Моя главная проблема в том, что я не знаю, что делает это «делать». Я только что прочитал, что он используется при необходимости операций ввода-вывода и каким-то образом выполняет следующие выражения. Что не имеет смысла для меня после прочтения того, что в haskell все оценивается как ценность. Что «делать» оценивать? Кроме того, какой отступ ожидается? Это кажется случайным. Я знаю, что функция должна вычислять до моего логического значения, что не представляется возможным при использовании этой операции "do". Но тогда как мне напечатать что-нибудь на консоль и сделать это частью выражения, которое оценивается как True или False?

Спасибо за любую помощь.

(Кстати, есть ли в интернете активные форумы на Haskell? Я не смог найти ни одного = /)

1 Ответ

22 голосов
/ 17 апреля 2011

Поскольку ваша функция должна выполнять IO, она должна возвращать значение в монаде IO, поэтому ее тип должен быть yesno :: IO Bool, а значения True и False должны быть подняты в монаду на return. Вам также нужно getLine вместо readLn, поскольку вам нужна необработанная строка, а не анализируемое значение (что может привести к ошибке разбора). Наконец, вам нужно hFlush stdout перед вызовом getLine, в противном случае приглашение все еще будет находиться в буфере в ожидании новой строки (а для этого необходимо импортировать System.IO).

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

import System.IO

yesno :: String -> IO Bool
yesno prompt = do
          putStr $ prompt ++ " y/n: "
          hFlush stdout
          str <- getLine
          case str of
            "y" -> return True
            "n" -> return False
            _   -> do
              putStrLn "Invalid input."
              yesno prompt

Затем вы можете вызвать вашу функцию из цикла взаимодействия:

main :: IO ()
main = do
         fun <- yesno "Is Haskell fun?"
         if fun
          then putStrLn "rock on"
          else putStrLn "read more tutorials"
         continue <- yesno "Continue?"
         if continue then main else return ()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...