summaryrefslogtreecommitdiff
path: root/docs/users_guide/exts/lexical_negation.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/users_guide/exts/lexical_negation.rst')
-rw-r--r--docs/users_guide/exts/lexical_negation.rst57
1 files changed, 57 insertions, 0 deletions
diff --git a/docs/users_guide/exts/lexical_negation.rst b/docs/users_guide/exts/lexical_negation.rst
new file mode 100644
index 0000000000..1060d950e4
--- /dev/null
+++ b/docs/users_guide/exts/lexical_negation.rst
@@ -0,0 +1,57 @@
+.. _lexical-negation:
+
+Lexical negation
+----------------
+
+.. extension:: LexicalNegation
+ :shortdesc: Use whitespace to determine whether the minus sign stands for
+ negation or subtraction.
+
+ :since: 8.12.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 :extension:`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 :extension:`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 :extension:`LexicalNegation`, negated literals are desugared without
+``negate``. That is, ``-123`` stands for ``fromInteger (-123)`` rather than
+``negate (fromInteger 123)``. This makes :extension:`LexicalNegation` a valid
+replacement for :extension:`NegativeLiterals`.