Eben Kadile
Eben Kadile

Reputation: 779

Haskell - messed up parsing of parentheses character?

According to this question Haskell patterns have to have the same number of arguments in each line. Here is my function:

findNextParens :: Int -> String -> Int
findNextParens 1 (')':str) = 1
findnextParens n (c:str)   = 1 + findNextParens n str
findNextParens n ('(':str) = 1 + findNextParens (n + 1) str
findNextParens n (')':str) = 1 + findNextParens (n - 1) str

Given the number of open parantheses and a string, it's supposed to find the index of the parantheses that closes the first one. When I try to load this function I get an error saying I've declared the function on the 1st and 3rd lines of its pattern. I have two arguments per line, so what's the cause of this?

Upvotes: 0

Views: 92

Answers (2)

chi
chi

Reputation: 116174

Let's load the code in GHCi:

> :{
| findNextParens :: Int -> String -> Int
| findNextParens 1 (')':str) = 1
| findnextParens n (c:str)   = 1 + findNextParens n str
| findNextParens n ('(':str) = 1 + findNextParens (n + 1) str
| findNextParens n (')':str) = 1 + findNextParens (n - 1) str
| :}

<interactive>:14:1: error: 
    Multiple declarations of ‘findNextParens’

Multiple declarations? Oh, the third line defines findnextParens instead of findNextParens, so it counts as a declaration of a new function.

Let's fix that typo:

> :{
| findNextParens :: Int -> String -> Int
| findNextParens 1 (')':str) = 1
| findNextParens n (c:str)   = 1 + findNextParens n str
| findNextParens n ('(':str) = 1 + findNextParens (n + 1) str
| findNextParens n (')':str) = 1 + findNextParens (n - 1) str
| :}

<interactive>:21:1: warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In an equation for ‘findNextParens’:
        findNextParens n ('(' : str) = ...

<interactive>:22:1: warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In an equation for ‘findNextParens’:
        findNextParens n (')' : str) = ...

Ah, two redundant (= unreachable) patterns!

Indeed, the line findNextParens n (c:str) = 1 + findNextParens n str catches even those cases where c is a open/closed parentheses, so the next lines are never reached.

Summary: always turn on warnings (-Wall) when compiling your code!

Upvotes: 4

Mark Seemann
Mark Seemann

Reputation: 233487

The second line has a lower-case n, but Haskell is case-sensitive. Change it to:

findNextParens :: Int -> String -> Int
findNextParens 1 (')':str) = 1
findNextParens n (c:str)   = 1 + findNextParens n str
findNextParens n ('(':str) = 1 + findNextParens (n + 1) str
findNextParens n (')':str) = 1 + findNextParens (n - 1) str

Upvotes: 1

Related Questions