bessarabov
bessarabov

Reputation: 11871

Why it is impossible to multiply negative numbers in haskell without brackets

Multiplying 5 * -3 in haskell gchi gives me and error. But multiplying 5 * (-3) works ok. Why are the brackets needed?

$ ghci
GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 5 * -3

<interactive>:2:1:
    Precedence parsing error
        cannot mix `*' [infixl 7] and prefix `-' [infixl 6] in the same infix expression
Prelude> 5 * (-3)
-15
Prelude>

Upvotes: 12

Views: 10071

Answers (5)

Gepser Hoil
Gepser Hoil

Reputation: 4236

Since there is still no accepted answer I did a little of research about this interesting question because I found it unanswered on another place too.

Short answer is: the grammar doesn't allow it.

Let me explain that a little bit more datailed, but first let's remember this:

On haskell, operators are functions on infix notation.

Now, let's see the error message:

Precedence parsing error
    cannot mix `*' [infixl 7] and prefix `-' [infixl 6] in the same infix expression

What does that means? Well, we should start defining what infixl 7 and infixl 6 are. On their grammar they have something like this:

infixr 9 .
infixr 8 ^, ^^, **
infixl 7 *, /, `quot`, `rem`, `div`, `mod`
infixl 6 +, -
infixr 5 :
infix 4 ==, /=, <, <=, >=, >
infixr 3 &&
infixr 2 ||
infixl 1 >>, >>=
infixr 1 =<<
infixr 0 $, $!, `seq`

Note: You can see that here, at the standard prelude.

What they mean on the error message is you can't join infixl 7 elements with infixl 6, that's would be the same reason that you can't do something like this:

Prelude> 5 * +3

You will get this error:

parse error on input `+'

Wait, if that is a sintax error, why the error message is different?

Well, it seems that the unary "-" operator is very special in haskell (as other answers said) and is being used on other parts of the grammar, so, in theory this will go to a different branch of the syntax tree and will throw an error somewhere else.

If you want to read more about the unary "-" operator you can go here.

Upvotes: 5

mljrg
mljrg

Reputation: 4620

A rule of thumb is to put negative numbers between parenthesis when they are preceded by a function application or an operator of higher precedence. This has been working for me so far.

Upvotes: 1

&#216;rjan Johansen
&#216;rjan Johansen

Reputation: 18199

The other answers tell you that - is a very special operator in Haskell, with strange syntactic behavior. I don't think that's really answering your question though, because there is absolutely nothing that would have prohibited the language designers from making 5 * -3 work the way you expected, even with the other strangeness.

So the real answer is, they simply didn't allow it.

As to why, my guess is because they were inspired not by the syntax of C-like languages (obvious really if you look at the rest of Haskell's syntax) but by notations based more closely on math convention, and in math you normally do need to parenthesize a -3 in that position. Although it's a bit of a copout because math also normally doesn't use anything in the place of the *.

Upvotes: 0

Don Stewart
Don Stewart

Reputation: 137987

Because of how the unary minus operator is specified in Haskell. It is a bit magic, unfortunately. It's an odd corner of the language specification.

Unary minus is the only unary operator in the language. Support for unary minus syntax is simply to support syntactic sugar for the negate function.

On the one hand, this lets us make - 7 the same as -7. On the other hand, it breaks other things, like section syntax.

And as you see, it makes for confusion when writing mix fixed expressions.

You need to parenthesize the use of negate, as follows:

5 * (-3)

Upvotes: 18

Ferruccio
Ferruccio

Reputation: 100718

The rule is that you cannot use a - operator (Haskell's only unary operator) near a binary operator.

Since you can define new operators in Haskell, the reason for this rule is that otherwise it could introduce a potential parsing ambiguity. Suppose you didn't use any spaces and specified 5*-3.

Would that mean 5 * -3 or 5 *- 3?

Upvotes: 3

Related Questions