6.2.20. Lexical negation — Glasgow Haskell Compiler 9.4.0.20220501 User's Guide

# 6.2.20. Lexical negation

`LexicalNegation`

  Since: | 9.0.1

  Detect if the minus sign stands for negation during lexical analysis by checking for the surrounding whitespace.

In Haskell 2010, the minus sign stands for negation when it has no left-hand side. Consider `x = - 5` and `y = 2 - 5`. In `x`, there’s no expression between the `=` and `-`, so the minus stands for negation, whereas in `y`, there’s `2` to the left of the minus, therefore it stands for subtraction.

This leads to certain syntactic anomalies:

- `(% x)` is an operator section for any operator `(%)` except for `(-)`. `(- x)` is negated `x` rather than the right operator section of subtraction. Consequently, it is impossible to write such a section, and users are advised to write `(subtract x)` instead.
- Negative numbers must be parenthesized when they appear in function argument position. `f (-5)` is correct, whereas `f -5` is parsed as `(-) f 5`.

The latter issue is partly mitigated by `NegativeLiterals`. When it is enabled, `-5` is parsed as negative 5 regardless of context, so `f -5` works as expected. However, it only applies to literals, so `f -x` or `f -(a*2)` are still parsed as subtraction.

With `LexicalNegation`, both anomalies are resolved:

- `(% x)` is an operator section for any operator `(%)`, no exceptions, as long as there’s whitespace between `%` and `x`.
- In `f -x`, the `-x` is parsed as the negation of `x` for any syntactically atomic expression `x` (variable, literal, or parenthesized expression).
- The prefix `-` binds tighter than any infix operator. `-a % b` is parsed as `(-a) % b` regardless of the fixity of `%`.

This means that `(- x)` is the right operator section of subtraction, whereas `(-x)` is the negation of `x`. Note that these expressions will often have different types (`(- x)` might have type `Int -> Int` while `(-x)` will have type `Int`), and so users mistaking one for the other will likely get a compile error.

Under `LexicalNegation`, negated literals are desugared without `negate`. That is, `-123` stands for `fromInteger (-123)` rather than `negate (fromInteger 123)`. This makes `LexicalNegation` a valid replacement for `NegativeLiterals`.