Search code examples
haskellwhitespaceguardpattern-guards

Haskell Says My Guard Has A Parse Error


So I've been playing with Haskell the past couple of days, and I decided I'd make a basic definition of the Fibonacci sequence. So I wrote this code:

main = do
    fib :: (Integral a) => Int -> Int
    fib x
        | x == 0 = 0
        | x == 1 = 1
        | x >= 2 = fib (x - 2) + fib (x - 1)
    do { print (fib 5) }

And I get an error message saying:

4:17: parse error on input `|'

I suspected tab errors, so I tried every whitespace fix I could find, but I just can't find what's wrong!

EDIT: So I did what people suggested, and I have this code now:

fib :: (Integral a) => Int -> Int
main = do
    fib x
        | x == 0 = 0
        | x == 1 = 1
        | x >= 2 = fib (x - 2) + fib (x - 1)
    print (fib 5)

And I'm getting the same error.


Solution

  • You can also define fib locally to main outside of the do block. Do bear in mind that do is syntactic sugar for the use of various monadic binding functions, and so the syntax accepted within it is not quite the same as that accepted outside it. And, in fact, your main doesn't even require the do block because you just call print rather than chaining any IO actions together.

    main = let
             fib x | x == 0 = 0
                   | x == 1 = 1
                   | x >= 2 = fib (x - 2) + fib (x + 1)
           in
             print (fib 5)
    

    Or you could use where:

    main = print (fib 5)
           where
             fib x | x == 0 = 0
                   | x == 1 = 1
                   | x >= 2 = fib (x - 2) + fib (x + 1)
    

    They're the same, the question is just where the local binding actually goes. let..in gives you a new block where the new bindings are in scope, while where makes its bindings available in the scope of the function it's attached to.

    If, as seems eventually likely, you do want a do block as well so you can do multiple IO actions, you can just put that in place of the call to print, like so:

    main = let
             fib x | x == 0 = 0
                   | x == 1 = 1
                   | x >= 2 = fib (x - 2) + fib (x + 1)
           in
             do print (fib 5)
                print (fib 6)