Why parse error? Indentation?

user905686 picture user905686 · Aug 24, 2011 · Viewed 17k times · Source

I wrote this code:

addNums key num = add [] key num
    where add res a:as b:bs
        | a == [] = res
        | otherwise = add res:(a+b) as bs

At line 3 the interpreter says:

parse error (possibly incorrect indentation)

I could not find something wrong, neither with the code nor with the indentation. I put four spaces for each tab.

Annotation:

Even this does not compile:

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs

Line 2:

Parse error in pattern: add

Answer

hammar picture hammar · Aug 24, 2011

The main indendation rule in Haskell is that if you want to continue a definition on another line, it has to be further indented than the the thing you're defining. In this case the guards for your add function are less indented, so that's what the compiler is complaining about.

Disregarding the other errors in your code, the indentation should be something like this:

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs

Also note that the exact amount of indentation does not matter, only the indentation of the continuing lines relative to the thing being defined.

Another syntactic problem with your code is that you seem to have misunderstood the precedence rules of Haskell. In Haskell, function application binds tighter than any operator, so add res a:as b:bs is parsed as (add res a):(as b):bs, while you meant add res (a:as) (b:bs).

The final problems are type errors. The (:) operator has the type a -> [a] -> [a], which means that it takes an element and a list, and produces a list. In your code res:(a+b), you appear to have this reversed, as res is a list and a+b is the element. Since there is no operator in Haskell to append a single element to the end of a list, you'll have to use the list concatenation operator (++) :: [a] -> [a] -> [a] instead: res ++ [a+b].

You're also comparing the element a to the list [] in your guard. This is probably not what you meant, and the pattern (a:as) would not match if the list was empty. The easiest solution to this is to add another pattern instead of your guard.

Putting all of this together, this code should hopefully do what you intended:

addNums key num = add [] key num
    where add res [] _ = res
          add res (a:as) (b:bs) = add (res ++ [a+b]) as bs

P.S. Repeatedly appending to the end of a list is not very efficient. In fact, it's O(n2). You might want to add to the front instead and reverse the list when you're done. This is O(n).


References: