以下是我正在处理的代码的简化版本。
main :: IO ()
main = do
args <- getArgs
if null args
then putStr "> " ; userInput <- getLine
else userInput <- readFile $ head args
let conclusion = userInput
如果不使用符号,这将无法工作,当我使用它时,变量将不会传递给下面的结论,而我正在尝试使用putStr来创建一种提示,只是让它发疯。
有什么东西我忘记在某处添加吗?
答案 0 :(得分:8)
这里有一些问题。首先,您需要在do
和then
之后添加else
:
if null args
then do putStr "> " ; userInput <- getLine
else do userInput <- readFile $ head args
注释中的 if
与其他地方的if
相同;你必须在then
和else
后面放一个表达式,而不是语句,你需要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
块必须以表达式结尾),但可能你已经有了代码。
作为补充说明,您应该避免使用head
和tail
等功能; head
是部分函数(未针对每个参数定义 - head []
将产生错误),并且这些通常被认为是单一的。您应该使用模式匹配,如下所示:
userInput <- case args of
[] -> do putStr "> " ; getLine
fileName:_ -> readFile fileName
这就像定义函数时使用的模式匹配一样,但是对于单个值而不是任意数量的参数。
答案 1 :(得分:3)
您在then
和else
块中执行的任何变量绑定都不会在外部作用域中可见,因此您需要绑定if
子句本身的结果。 / p>
main :: IO ()
main = do
args <- getArgs
userInput <- if null args
then do
putStr "> "
getLine
else readFile $ head args