Home > other >  Haskell - Parse Error on Input `|" in GHC
Haskell - Parse Error on Input `|" in GHC

Time:12-24

I've just started programming in Haskell and to get used to the syntax and general style of the language I've decided to try and solve some basic problems on Project Euler.

However, when I tried to compile my code for Problem 1 in GHC, I received an error:

main = do

    sum :: Int -> Int
    sum n
        | n == 0         = 0
        | n `mod` 3 == 0 = n   sum (n - 1)
        | n `mod` 5 == 0 = n   sum (n - 1)
        | otherwise      = sum (n - 1)

    print sum 1000

The error message in question:

Problem1.hs:5:9: error: parse error on input `|'
  |
5 |         | n == 0 = 0
  |         ^

Other users having this or a similar problem here usually had something syntactically simple wrong with their code, such as having typed == instead of =, or had an indentation error, but I don't know why my code doesn't compile properly. I don't believe it is related to indentation; I am using VSCode and my tab size is set to 4 spaces, but I have also tried indenting manually by using space, both of which produced the same error.

CodePudding user response:

As @Caramiriel rightfully corrected me, functions cannot be defined in a do-block. I solved this by simply pulling sum out of main, but this left 2 problems in the code:

  1. The function name sum is ambiguous, as it could refer both to the automatically imported function Prelude.sum, or the one I created. To solve this, I simply changed my function name to mySum.
  2. print mySum 1000 does not compile, as this is equivalent to print (mySum) 1000, where both mySum and 1000 are inputs for print. To fix this, I simply added parentheses: print (mySum 1000)

On a less important note, I misread the original question on Project Euler, and it should be print (mySum 999) instead. This leaves me with the following (working!) code:

mySum :: Int -> Int
mySum n
    | n == 0         = 0
    | n `mod` 3 == 0 = n   mySum (n - 1)
    | n `mod` 5 == 0 = n   mySum (n - 1)
    | otherwise      = mySum (n - 1)

main = do
    print (mySum 999)

CodePudding user response:

Actually, functions can be defined in a do block, but you must use a let statement, so the following would work fine:

main = do
    let sum :: Int -> Int
        sum n
            | n == 0         = 0
            | n `mod` 3 == 0 = n   sum (n - 1)
            | n `mod` 5 == 0 = n   sum (n - 1)
            | otherwise      = sum (n - 1)
    print $ sum 1000

As a matter of style, though, it's unusual to define functions within a do block unless they have to be defined there (because they make reference to a variable defined within the do-block, for example), or if they're obviously utility or convenience functions that wouldn't make sense to use outside the do block.

  • Related