Why do I get parse input error in this Haskell code?

Viewed 84

The input to the code is numbers written in words "one" "two" etc. the output is the sum of a all numbers inputed when "sum" or "end" is entered. "end" also exits the program.

This is the code that I've written.

main = addfunc 0


addfunc :: Int -> IO ()
addfunc l = do
 {
  input <- getLine;
  let n = myStrToI input
  ; if n == -2 
    then do {
          putStrLn("The final sum is: " ++ show (l));
          return ();            
          }
    else if n == -1 
     then 
           putStrLn("The current sum is: " ++ show(l));
           addfunc l;     <--Error Here       
    else  addfunc (n+l)
 }

myStrToI :: [Char] -> Int
myStrToI l
  | l == "zero" = 0
  | l == "one" = 1
  | l == "two" = 2
  | l == "three" = 3
  | l == "four" = 4
  | l == "five" = 5
  | l == "six" = 6
  | l == "seven" = 7
  | l == "eight" = 8
  | l == "nine" = 9
  | l == "sum" = -1
  | l == "end" = -2

The error I get is

"error: parse error on input 'addfunc'

17. addfunc l;"

I've tried changing the amount of spaces or removing the ';' in the line above, but I still get an error at that place. Is this error because the indentation of if else blocks? I'm beginner to Haskell and don't really understand where the error is.

1 Answers

If you use { } (which you probably shouldn't), then did disables all indentation sensitivity inside. So your code parses just the same as

addfunc :: Int -> IO ()
addfunc l = do
 {
  input <- getLine;
  let n = myStrToI input;
  if n == -2
  then do {putStrLn("The final sum is: " ++ show (l)); return ()}
  else if n == -1 
  then putStrLn("The current sum is: " ++ show(l));
  addfunc l
  else addfunc (n+l)
 }

So what does the compiler make of that? Well, let's also move the semicolons around a bit:

addfunc :: Int -> IO ()
addfunc l = do
 { input <- getLine
 ; let n = myStrToI input
 ; if n == -2
   then do {putStrLn("The final sum is: " ++ show (l)); return ()}
   else if n == -1 
   then putStrLn("The current sum is: " ++ show(l))
 ; addfunc l
   else addfunc (n+l)
 }

Whoops. The if n == -1 is never finished, instead you skip to the next line in the outermost do block, and there's then a lone else there.

What you actually need is another do for that if branch. Preferrably use indentation without braces:

addfunc :: Int -> IO ()
addfunc l = do
  input <- getLine
  let n = myStrToI input
  if n == -2 
   then do
     putStrLn("The final sum is: " ++ show (l))
     return ()
   else if n == -1 
   then do
     putStrLn $ "The current sum is: " ++ show l
     addfunc l
   else
     addfunc (n+l)
 

Actually I'd prefer using a case construct instead of those ifs:

  ...
  let n = myStrToI input
  case n of
   -2 -> do
     putStrLn("The final sum is: " ++ show (l))
     return ()
   -1 -> do
     putStrLn $ "The current sum is: " ++ show l
     addfunc l
   _ ->
     addfunc (n+l)
Related