Home > Back-end >  Why do I get parse input error in this Haskell code?
Why do I get parse input error in this Haskell code?

Time:09-17

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.

CodePudding user response:

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