'do' 块内的守卫 - haskell

tom*_*lak 6 syntax haskell guard-clause do-notation

我想写一个简单的游戏“猜数字” -n尝试。我想添加一些条件和命中。是否可以在block内使用守卫do

这是我的代码:

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)
Run Code Online (Sandbox Code Playgroud)

已经出错

error: parse error on input ‘|’
Run Code Online (Sandbox Code Playgroud)

它可以用一些空白来修复,还是不可能做到?

Wil*_*sem 11

do表达[Haskell的报告]仅由选自exppat <- exp,和let …语句,则编译器将这些desugar。因此,如果没有一些语言扩展,就不能在do块中编写守卫。此外,无论如何启用它可能不是一个好主意。例如,如果您想使用两个相邻的“保护块”怎么办?然后两者将“合并”,因此第一个块的守卫将已经消除(几乎)所有情况。

您可以let在此处使用另一个子句:

game :: IO ()
game 0 = return ()
game n = do
    putStrLn "guess number: 0-99"
    number <- getLine
    let y = read number
    let x = 20
    let action | 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!!"
    action
Run Code Online (Sandbox Code Playgroud)

请注意,otherwise原始问题中的 永远不会被触发,因为一个值小于、大于或等于另一个值。


Jos*_*ica 6

那里有很多问题。

首先,你不能说game =一些game n =什么,所以删除这game = return ()行。(您可能一直在尝试编写类型签名,但这不是一个。)

其次,您不能在任意位置使用保护语法。与您所写内容最接近的有效内容是多路 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)
Run Code Online (Sandbox Code Playgroud)

第三,Ordtypeclass 应该用于具有总顺序的类型,因此除非您使用 NaN 之类的非法内容,否则您将始终拥有y>x, y<x, or 之一y==x,因此otherwise永远不会输入。

第四,与<, ==, and比较>是单调和缓慢的,因为它必须不断重复比较。而不是这样做,做这样的事情:

case y `compare` x of
  GT -> _
  LT -> _
  EQ -> _
Run Code Online (Sandbox Code Playgroud)