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:
- The function name
sum
is ambiguous, as it could refer both to the automatically imported functionPrelude.sum
, or the one I created. To solve this, I simply changed my function name tomySum
. print mySum 1000
does not compile, as this is equivalent toprint (mySum) 1000
, where bothmySum
and1000
are inputs forprint
. 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.