'do' 块内的守卫 - haskell
Guard inside 'do' block - haskell
我想写一个简单的游戏 "guess number" - n
次尝试。我想添加一些条件和命中率。是否可以在 do
块内使用 guards?
这是我的代码:
game = return()
game n = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x =20
| y>x = putStrLn "your number is greater than x"
| y<x = putStrLn "your number is less than x"
| y==x putStrLn "U win!!"
| otherwise = game (n-1)
已经出现错误
error: parse error on input ‘|’
它可以用一些 白色 space 修复,还是根本不可能修复?
那里有很多问题。
首先,你不能说 game =
和 game n =
,所以删除 game = return ()
行。 (您可能一直在尝试编写类型签名,但那不是。)
其次,您不能在任意位置使用保护语法。最接近您所写内容的有效内容是 multi-way if-expressions,它可以让您这样写:
{-# LANGUAGE MultiWayIf #-}
game n = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x =20
if
| y>x -> putStrLn "your number is greater than x"
| y<x -> putStrLn "your number is less than x"
| y==x-> putStrLn "U win!!"
| otherwise -> game (n-1)
第三,Ord
类型类应该用于具有总顺序的类型,因此除非您使用像 NaN 这样的非法事物,否则您将始终拥有 y>x
、y<x
或 y==x
,因此永远不会输入 otherwise
。
第四,与<
、==
、>
比较,比较单调,比较慢,因为要不断重复比较。不要那样做,而是做这样的事情:
case y `compare` x of
GT -> _
LT -> _
EQ -> _
A do
expression [Haskell-report] 仅由 exp
、pat <- exp
和 let …
语句组成,编译器将对这些语句进行脱糖。因此,如果没有一些语言扩展,你不能在 do
块中编写守卫。此外,无论如何启用它可能不是一个好主意。例如,如果您想要使用两个并排的“保护块”怎么办?然后两者将“合并”,因此第一个街区的警卫已经(几乎)消除了所有情况。
您可以在此处使用另一个 let
子句:
game :: IO ()
game 0 = return ()
game n = do
putStrLn "guess number: 0-99"
number <- getLine
let y = read number
let x = 20
<b>let action</b> | y > x = putStrLn "your number is greater than x" >> game (n-1)
| y < x = putStrLn "your number is less than x" >> game (n-1)
| otherwise = putStrLn "U win!!"
<b>action</b>
请注意,原始问题中的 otherwise
永远不会被触发,因为一个值小于、大于或等于另一个值。
您也可以只使用 case
或 LambdaCase
。
{-# LANGUAGE LambdaCase #-}
game :: Int -> IO ()
game n = case n of
0 -> putStrLn "used all attempts"
n ->
putStrLn "guess a number: 0 - 99" >>
(`compare` 20) . read <$> getLine >>=
\case
EQ -> putStrLn "U win"
GT -> putStrLn "your number is greater than x" >>
game (n - 1)
LT -> putStrLn "your number is less than x" >>
game (n - 1)
其他答案非常有用。阅读那些让我看到你也可以调用一个函数来解决这个问题,例如
game = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x = 20
action y x
where
action y x
| y>x = putStrLn "your number is greater than x" >> game
| y<x = putStrLn "your number is less than x" >> game
| otherwise = putStrLn "U win!!"
我想写一个简单的游戏 "guess number" - n
次尝试。我想添加一些条件和命中率。是否可以在 do
块内使用 guards?
这是我的代码:
game = return()
game n = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x =20
| y>x = putStrLn "your number is greater than x"
| y<x = putStrLn "your number is less than x"
| y==x putStrLn "U win!!"
| otherwise = game (n-1)
已经出现错误
error: parse error on input ‘|’
它可以用一些 白色 space 修复,还是根本不可能修复?
那里有很多问题。
首先,你不能说 game =
和 game n =
,所以删除 game = return ()
行。 (您可能一直在尝试编写类型签名,但那不是。)
其次,您不能在任意位置使用保护语法。最接近您所写内容的有效内容是 multi-way if-expressions,它可以让您这样写:
{-# LANGUAGE MultiWayIf #-}
game n = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x =20
if
| y>x -> putStrLn "your number is greater than x"
| y<x -> putStrLn "your number is less than x"
| y==x-> putStrLn "U win!!"
| otherwise -> game (n-1)
第三,Ord
类型类应该用于具有总顺序的类型,因此除非您使用像 NaN 这样的非法事物,否则您将始终拥有 y>x
、y<x
或 y==x
,因此永远不会输入 otherwise
。
第四,与<
、==
、>
比较,比较单调,比较慢,因为要不断重复比较。不要那样做,而是做这样的事情:
case y `compare` x of
GT -> _
LT -> _
EQ -> _
A do
expression [Haskell-report] 仅由 exp
、pat <- exp
和 let …
语句组成,编译器将对这些语句进行脱糖。因此,如果没有一些语言扩展,你不能在 do
块中编写守卫。此外,无论如何启用它可能不是一个好主意。例如,如果您想要使用两个并排的“保护块”怎么办?然后两者将“合并”,因此第一个街区的警卫已经(几乎)消除了所有情况。
您可以在此处使用另一个 let
子句:
game :: IO ()
game 0 = return ()
game n = do
putStrLn "guess number: 0-99"
number <- getLine
let y = read number
let x = 20
<b>let action</b> | y > x = putStrLn "your number is greater than x" >> game (n-1)
| y < x = putStrLn "your number is less than x" >> game (n-1)
| otherwise = putStrLn "U win!!"
<b>action</b>
请注意,原始问题中的 otherwise
永远不会被触发,因为一个值小于、大于或等于另一个值。
您也可以只使用 case
或 LambdaCase
。
{-# LANGUAGE LambdaCase #-}
game :: Int -> IO ()
game n = case n of
0 -> putStrLn "used all attempts"
n ->
putStrLn "guess a number: 0 - 99" >>
(`compare` 20) . read <$> getLine >>=
\case
EQ -> putStrLn "U win"
GT -> putStrLn "your number is greater than x" >>
game (n - 1)
LT -> putStrLn "your number is less than x" >>
game (n - 1)
其他答案非常有用。阅读那些让我看到你也可以调用一个函数来解决这个问题,例如
game = do putStrLn "guess number: 0-99"
number<-getLine
let y = read number
let x = 20
action y x
where
action y x
| y>x = putStrLn "your number is greater than x" >> game
| y<x = putStrLn "your number is less than x" >> game
| otherwise = putStrLn "U win!!"