restacker
restacker

Reputation: 11

why is haskell interpreter giving me this parse error?

Doing exercises in Richard Bird's book "Introduction to Functional Programming Using Haskell," second edition. In the last line in the following code, I get the error:

"Parse error in pattern (n `times` Succ m)

Note that the same pattern (with m and n interchanged) was accepted in the definition of times. Why am I getting this error?

    data Nat = Zero | Succ Nat
    deriving (Eq, Ord, Show)

    plus :: Nat -> Nat -> Nat
    m `plus` Zero = m
    m `plus` Succ n = Succ (m `plus` n)

    m `times` Zero = Zero
    m `times` Succ n = (m `times` n) `plus` m

    divide :: Nat -> Nat -> Nat
    Zero `divide` m = Zero
    (n `times` Succ m) `divide` n = Succ m

Upvotes: 1

Views: 298

Answers (1)

Daniel Fischer
Daniel Fischer

Reputation: 183918

You get a parse error on

(n `times` Succ m) `divide` n = Succ m

because the arguments of the defined function must be patterns, that is

  • a wildcard _
  • a variable identifier foo
  • a constructor application (a value constructor applied to as many patterns as its arity demands)
  • a labelled pattern F{field1 = value1, ..., fieldN = valueN} (if the constructor F is defined using named field syntax)
  • a literal 1, "foo"
  • a negative literal -1
  • a tuple patter, (1,2)
  • a list pattern [1,2]
  • a parenthesised pattern (pat), wher pat is a pattern
  • a lazy pattern, ~pat, where pat is a pattern

and the first argument here is not a pattern but a function application of a non-constructor function.

A pattern allows to deconstruct a value, but an ordinary function application doesn't. For your problem, if you have

12 `divide` 4

-- and all that is available when the function is called is the value, not how it was obtained -- your attempted function definition would require that the compiler factors the value to check whether it can be written in the given form.

Another problem in that line is that you use the identifier n twice, but any variable identifier can only appear once in a pattern-match.

Note that the same pattern (with m and n interchanged) was accepted in the definition of times.

In the definition

m `times` Succ n = (m `times` n) `plus` m

the function times is defined for some kinds of arguments. The entire left hand side is not a pattern, there we have the two patterns m - a variable pattern that matches every argument and binds it to the name m - and Succ n (that contains the nested variable pattern n).

The left hand side of the definition consists of the defined name (times) and two patterns for the arguments.

In the definition of divide, the same structure is expected, the name to be defined, and two patterns for the arguments.

(n `times` Succ m) `divide` n = Succ m

So when the parser encounters the opening parenthesis, it expects a parenthesised pattern. But it finds

     n          `times`            Succ m
pattern infix-function-application pattern

The top node of the expression tree of that is times, which is not a constructor. Hence the part between the parentheses cannot be parsed as a pattern.

Upvotes: 3

Related Questions