diff options
Diffstat (limited to 'docs/users_guide/exts')
-rw-r--r-- | docs/users_guide/exts/lexical_negation.rst | 57 | ||||
-rw-r--r-- | docs/users_guide/exts/negative_literals.rst | 3 | ||||
-rw-r--r-- | docs/users_guide/exts/syntax.rst | 1 |
3 files changed, 60 insertions, 1 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`. diff --git a/docs/users_guide/exts/negative_literals.rst b/docs/users_guide/exts/negative_literals.rst index 74fcc87a21..237fabf044 100644 --- a/docs/users_guide/exts/negative_literals.rst +++ b/docs/users_guide/exts/negative_literals.rst @@ -27,5 +27,6 @@ as two tokens. One pitfall is that with :extension:`NegativeLiterals`, ``x-1`` will be parsed as ``x`` applied to the argument ``-1``, which is usually not what you want. ``x - 1`` or even ``x- 1`` can be used instead -for subtraction. +for subtraction. To avoid this, consider using :extension:`LexicalNegation` +instead. diff --git a/docs/users_guide/exts/syntax.rst b/docs/users_guide/exts/syntax.rst index 781e65b9d3..bb29b55772 100644 --- a/docs/users_guide/exts/syntax.rst +++ b/docs/users_guide/exts/syntax.rst @@ -25,3 +25,4 @@ Syntax block_arguments typed_holes arrows + lexical_negation |