使用Haskell从if语句获取输入和传递变量

时间:2012-02-09 18:52:20

标签: variables haskell if-statement io

以下是我正在处理的代码的简化版本。

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

     let conclusion = userInput

如果不使用符号,这将无法工作,当我使用它时,变量将不会传递给下面的结论,而我正在尝试使用putStr来创建一种提示,只是让它发疯。

有什么东西我忘记在某处添加吗?

2 个答案:

答案 0 :(得分:8)

这里有一些问题。首先,您需要在dothen之后添加else

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

if与其他地方的if相同;你必须在thenelse后面放一个表达式,而不是语句,你需要do把一堆语句变成一个表达式。但这仍然不是很有效; do块中的最后一个语句必须是表达式,但是这里有绑定。毕竟,每个语句都必须有一个结果值,但绑定没有。

第二个问题是,正如您所观察到的,这引入了一个新范围,因此您无法访问从外部绑定的变量。如果你考虑一下,这是有道理的;毕竟,你可以在一侧而不是另一侧绑定变量。解决方案是简单地将绑定移到<{1}} 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块必须以表达式结尾),但可能你已经有了代码。

作为补充说明,您应该避免使用headtail等功能; head部分函数(未针对每个参数定义 - head []将产生错误),并且这些通常被认为是单一的。您应该使用模式匹配,如下所示:

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

这就像定义函数时使用的模式匹配一​​样,但是对于单个值而不是任意数量的参数。

答案 1 :(得分:3)

您在thenelse块中执行的任何变量绑定都不会在外部作用域中可见,因此您需要绑定if子句本身的结果。 / p>

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