这是我正在处理的代码的简化版本。
main :: IO ()
main = do
args <- getArgs
if null args
then putStr "> " ; userInput <- getLine
else userInput <- readFile $ head args
let conclusion = userInput
如果没有 do 符号,这将无法工作,当我使用它时,变量不会传递到下面的结论,以及我试图用它来创建一种提示,只会让它发疯。
有什么我忘记添加的东西吗?
最佳答案
这里有一些问题。首先,您需要在 then
和 else
之后包含 do
:
if null args
then do putStr "> " ; userInput <- getLine
else do userInput <- readFile $ head args
do 表示法中的 if
与其他地方的 if
相同;你必须在 then
和 else
之后放置一个 expression,而不是语句,并且你需要 do
来转换一堆语句变成一个表达式。不过,这仍然不是很有效; do
block 中的最后一个语句必须是一个表达式,但这里有一个绑定(bind)。毕竟,每个语句都必须有一个结果值,但绑定(bind)没有。
第二个问题是,正如您所观察到的,这引入了一个新的作用域,因此您无法访问从外部绑定(bind)的变量。如果您考虑一下,这是有道理的;毕竟,您可以将变量绑定(bind)在一侧而不是另一侧。解决方案是将绑定(bind)移到if
:
main :: IO ()
main = do
args <- getArgs
userInput <- if null args
then do putStr "> " ; getLine
else readFile $ head args
let conclusion = userInput
因此,我们绑定(bind)到 userInput
的操作仍然根据 null args
的结果进行计算,但我们将变量绑定(bind)在条件之外。
请注意,这次我没有将do
添加到else
分支;这不是必需的,因为那里只有一个表达式。 (它仍然有效,但在不需要时使用 do
是不合常理的。)
除非您在 let conclusion = userInput
行之后添加一些内容,否则此代码仍然无法运行(因为,正如我所说,do
block 必须以表达式结尾) ,但大概您已经有了代码。
作为附加说明,您应该避免使用像head
和tail
这样的函数; head
是一个偏函数(不是为每个参数都定义的——head []
会产生错误),这些通常被认为是不合常理的。您应该改用模式匹配,如下所示:
userInput <- case args of
[] -> do putStr "> " ; getLine
fileName:_ -> readFile fileName
这就像定义函数时使用的模式匹配,但针对的是单个值而不是任意数量的参数。
关于variables - 使用 Haskell 从 if 语句获取输入并传递变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9216940/