Получить ввод и передать переменную из оператора if с помощью Haskell - PullRequest
2 голосов
/ 09 февраля 2012

Вот упрощенная версия кода, над которым я работаю.

main :: IO ()
main = do
     args <- getArgs
     if null args
       then putStr "> " ; userInput <- getLine
       else userInput <- readFile $ head args

     let conclusion = userInput

Это не будет работать без записи, переменная не перейдет к выводу нижекогда я его использую, а putStr, который я пытаюсь использовать для создания своего рода приглашения, просто сводит его с ума.

Есть что-то, что я забыл добавить куда-нибудь?

Ответы [ 2 ]

8 голосов
/ 09 февраля 2012

Здесь есть несколько проблем. Во-первых, вам нужно включить do после then и else:

if null args
  then do putStr "> " ; userInput <- getLine
  else do userInput <- readFile $ head args

if в нотации do совпадает с if везде; Вы должны поставить выражение после then и else, а не операторы, и вам нужно do, чтобы превратить группу операторов в выражение. Это все еще не совсем верно, хотя; последний оператор в блоке do должен быть выражением, но здесь у вас есть привязка. В конце концов, каждое утверждение должно иметь значение результата, а привязка - нет.

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

main :: IO ()
main = do
     args <- getArgs
     userInput <- if null args
       then do putStr "> " ; getLine
       else readFile $ head args

     let conclusion = userInput

Итак, действие, результат которого мы связываем с userInput, все еще вычисляется в зависимости от результата null args, но мы связываем переменную вне условного выражения.

Обратите внимание, что на этот раз я не добавил do в ветку else; это не обязательно, так как там только одно выражение. (Это все еще допустимо, но не имеет смысла использовать do, когда в этом нет необходимости.)

Этот код все равно не будет работать, если вы не поместите что-то после строки let conclusion = userInput (поскольку, как я уже сказал, блоки do должны заканчиваться выражением), но, вероятно, у вас уже есть код там.

В качестве дополнительного примечания вам следует избегать использования таких функций, как head и tail; head - это частичная функция (не определенная для каждого аргумента - head [] вызовет ошибку), и они обычно считаются недиоматическими. Вместо этого вы должны использовать сопоставление с шаблоном, например так:

userInput <- case args of
  [] -> do putStr "> " ; getLine
  fileName:_ -> readFile fileName

Это похоже на сопоставление с образцом, используемое при определении функции, но для одного значения, а не для любого количества аргументов.

3 голосов
/ 09 февраля 2012

Любые привязки переменных, которые вы делаете в блоках then и else, не будут видны во внешней области видимости, поэтому вам нужно привязать результат из самого предложения if.

main :: IO ()
main = do
    args <- getArgs
    userInput <- if null args
        then do
            putStr "> "
            getLine
        else readFile $ head args
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...