Search code examples
haskellsyntaxdo-notationguard-clause

Guard inside 'do' block - haskell


I want to write a simple game "guess number" - with n attempts. I want to add some conditions and hits. Is it possible to use guards inside do block ?

Here is my code:

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)

already got error

error: parse error on input ‘|’

Is it fixable with some white space, or just impossible to do?


Solution

  • A do expression [Haskell-report] only consists out of exp, pat <- exp, and let … statements, and the compiler will desugar these. Hence without some language extensions, you can not write guards in a do block. Furthermore it is likely not a good idea to enable that anyway. What if you for example would want to use two "guard blocks" next to each other? Then the two would "merge" and thus the guards of the first block would already eleminate (nearly) all cases.

    You can use another let clause here:

    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

    Note that the otherwise in the original question will never get triggered, since a value is less than, greater than, or equal to another value.