我正在尝试编写一个能够执行2种不同游戏模式的功能,这些游戏模式定义为tictactoe :: IO ()
和main :: IO ()
。我输入'|'时出现解析错误。我不明白我做错了什么。有人可以向我解释一下吗?
tictac :: IO()
tictac = do
putStrLn "Would you like to play against the computer or
another player? Enter: 2 Player or Computer"
choice <- getLine
|choice == "Computer" = main
|choice == "2 Player" = tictactoe
|otherwise = putStrLn "That's not a choice!"
答案 0 :(得分:5)
有一组有限的地方你可以使用警卫 - 它们最常用于功能定义。在这种情况下,您可能正在寻找case
语句:
choice <- getLine
case choice of
"Computer" -> main
"2 Player" -> tictactoe
_ -> putStrLn "That's not a choice!"
_
模式匹配任何东西,其中&#34; mops up&#34;剩下的模式。
它在这里的用法类似于otherwise
,虽然otherwise
实际上只是true
的语法糖,因为守卫中的表达式是boolean
。
它与守卫不完全相同,因为守卫评估布尔表达式而case
进行模式匹配,但它有效。更准确的双重守卫是if
表达式,但case
语法更好,当您可以使用它时。有关更多示例,请查看Wiki上的control structures页面。
正如评论中指出的那样,也可以在case
表达式中使用警卫 - 您可以在the specification和this question/answer中看到这一点。它确实需要至少一个模式匹配,这在这里很难看 - 你可以使用"hack" described here做类似的事情:
case () of
_ | choice == "Computer" -> main
| choice == "2 Player" -> tictactoe
| otherwise -> putStrLn "That's not a choice!"
但是这样做没有任何好处。
答案 1 :(得分:1)
有几种方法可以测试这样的值,但与您编写的内容最相似的方法是使用自GHC 7.6(2012年9月)以来可用的名为MultiWayIf
的扩展名。添加编译指示:
{-# LANGUAGE MultiWayIf #-}
在源文件的顶部(或在GHCi中使用:set -XMultiWayIf
),您可以编写以下内容:
choice <- getLine
-- Simply add the ‘if’ keyword here.
if
| choice == "Computer" -> main
| choice == "2 Player" -> tictactoe
| otherwise -> putStrLn "That's not a choice!"
通常情况下,保护语法| condition
仅适用于两个地方: definitions (其中一个保护在名称和参数之后,在=
符号之前)和case
(在模式之后,在->
符号之前):
doubleIfEven :: Int -> Int
-- Definition
doubleIfEven x
| even x = x * 2
--------
| otherwise = x
-----------
doubleIfJustEven :: Maybe Int -> Maybe Int
doubleIfJustEven mx
-- Match
= case mx of
Just x
| even x -> Just (x * 2)
--------
| otherwise -> Just x
-----------
Nothing -> Nothing
以下是替代方案:
case
表达式,在这种情况下,您只测试字符串的(结构)相等性:
case choice of
"Computer" -> main
"2 Player" -> tictactoe
_ -> putStrLn "That's not a choice!"
where
子句或let
绑定中的本地定义:
tictac :: IO ()
tictac = do
putStrLn "Would you like to play against the computer or\
\ another player? Enter: 2 Player or Computer"
choice <- getLine
check choice
where
check choice
| choice == "Computer" = main
| choice == "2 Player" = tictactoe
| otherwise = putStrLn "That's not a choice!"
----
tictac :: IO ()
tictac = do
putStrLn "Would you like to play against the computer or\
\ another player? Enter: 2 Player or Computer"
let
check choice
| choice == "Computer" = main
| choice == "2 Player" = tictactoe
| otherwise = putStrLn "That's not a choice!"
choice <- getLine
check choice
嵌套if
表达式:
if choice == "Computer" then main
else if choice == "2 Player" then tictactoe
else putStrLn "That's not a choice!"
case
带有虚拟图案和守卫(一个古老的成语):
case () of
_ | choice == "Computer" -> main
| choice == "2 Player" -> tictactoe
| otherwise -> putStrLn "That's not a choice!"
#1最常用于匹配;如果您需要保护并且想要避免MultiWayIf
支持旧编译器,或者只是想将逻辑分解为单独的定义以便于阅读,则使用#2; #3和#4不是很常见或惯用,但它们并没有“错误”。