我刚开始使用Wikibook学习Haskell,到目前为止,我做的还不错,因为我已经在Visual Basic和Java方面学习了非常基础的HS课程,但是Haskell的某些奇特功能使我在合并更多内容时感到困惑比一个。其中一本Wikibook遇到了一个练习问题,即根据作为用户输入的特定名称编写三个不同的字符串。当使用if-then-else语句时,这很好,但是当我尝试使用防护时,我在第6行遇到了解析错误。
main = do
putStrLn "What is your name?"
n <- getLine
|(n == "Simon") || (n == "John") || (n == "Phil")
= putStrLn "Help me make this stuff"
|n == "Koen" = putStrLn "How is this a parse error"
|otherwise "Line 11 looks fine to me"
Which reads " error: parse error on input ‘|’"
Is this a problem with the guard | or the operator ||? the error lists it is on 6:9 if that helps.
编辑:由于有人回答了我的第一个问题,因此我对一个非常相似的主题还有另一个问题。 Wikibooks Haskell教程已将此列为练习的另一种解决方案,使用where语句代替if-then-else:
main = do
putStrLn "Hello, what is your name?"
name <- getLine
putStrLn (message name)
where
greatlanguage = "I think Haskell is a great programming language."
message "Simon" = greatlanguage
message "John" = greatlanguage
message "Phil" = greatlanguage
message "Koen" = "I think debugging Haskell is fun."
message _ = "Sorry, I don't know you."
是否可以使用||?运算符如何以某种方式将3个Simon,John和Phil行压缩为单行?
答案 0 :(得分:2)
只能将保护插入函数定义(以func a b | condition = ...
的形式)和case
块(以case x of pattern | condition -> ...
的形式)中;您不能将它们插入do
内,以阻止您尝试的方式。您将需要在此处使用if ... then ... else
。
答案 1 :(得分:2)
有很多方法可以解决这个问题。我建议您考虑将这段代码从do
块移到它自己的函数中。
for n :: String -> IO ()
foo n | n == "Simon" ||
n == "John" ||
n == "Phil" = putStrLn "Help me make this stuff"
| n == "Koen" = putStrLn "How is this a parse error"
|otherwise = putStrLn "Line 11 looks fine to me"
然后在您的do
块中调用它,
main = do
putStrLn "What is your name?"
n <- getLine
foo n
另外,将辅助功能设置为“纯”可能更明智,
for n :: String -> String
foo n | n == "Simon" ||
n == "John" ||
n == "Phil" = "Help me make this stuff"
| n == "Koen" = "How is this a parse error"
|otherwise = "Line 11 looks fine to me"
并通过
进行调用main = do
putStrLn "What is your name?"
n <- getLine
putStrLn (foo n)
如果您愿意,也可以简化第一个后卫,
foo n | n `elem` ["Simon", "John", "Phil"] = "Help me make this stuff"
| n == "Koen" = "How is this a parse error"
|otherwise = "Line 11 looks fine to me"
如果您真的想将其内联到do
块中,则可以通过案例构建来适应其中一种解决方案,例如
main = do
putStrLn "What is your name?"
n <- getLine
putStrLn $ case n of
_ | n `elem` ["Simon", "John", "Phil"] -> "Help me make this stuff"
_ | n == "Koen" -> "How is this a parse error"
_ -> "Line 11 looks fine to me"
答案 2 :(得分:2)
为补充其他答案,我将添加两个选择(不一定是更好的选择)。
main = do
putStrLn "What is your name?"
n <- getLine
case () of
_ | n == "Simon" || n == "John" || n == "Phil"
-> putStrLn "Help me make this stuff"
| n == "Koen"
-> putStrLn "How is this a parse error"
| otherwise
-> putStrLn "Line 11 looks fine to me"
这需要打开MultiWayIf
扩展名。
{-# LANGUAGE MultiWayIf #-} -- at the top of the file
main = do
putStrLn "What is your name?"
n <- getLine
if | n == "Simon" || n == "John" || n == "Phil"
-> putStrLn "Help me make this stuff"
| n == "Koen"
-> putStrLn "How is this a parse error"
| otherwise
-> putStrLn "Line 11 looks fine to me"
请记住,即使在otherwise
之后,我们仍然需要->
,否则会触发解析错误。