1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
.. _block-arguments:
More liberal syntax for function arguments
------------------------------------------
.. extension:: BlockArguments
:shortdesc: Allow ``do`` blocks and other constructs as function arguments.
:since: 8.6.1
Allow ``do`` expressions, lambda expressions, etc. to be directly used as
a function argument.
In Haskell 2010, certain kinds of expressions can be used without parentheses
as an argument to an operator, but not as an argument to a function.
They include ``do``, lambda, ``if``, ``case``, and ``let``
expressions. Some GHC extensions also define language constructs of this type:
``mdo`` (:ref:`recursive-do-notation`), ``\case`` (:ref:`lambda-case`), and
``proc`` (:ref:`arrow-notation`).
The :extension:`BlockArguments` extension allows these constructs to be directly
used as a function argument. For example::
when (x > 0) do
print x
exitFailure
will be parsed as::
when (x > 0) (do
print x
exitFailure)
and
::
withForeignPtr fptr \ptr -> c_memcpy buf ptr size
will be parsed as::
withForeignPtr fptr (\ptr -> c_memcpy buf ptr size)
Changes to the grammar
~~~~~~~~~~~~~~~~~~~~~~
The Haskell report `defines
<https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003>`_
the ``lexp`` nonterminal thus (``*`` indicates a rule of interest)
.. code-block:: none
lexp → \ apat1 … apatn -> exp (lambda abstraction, n ≥ 1) *
| let decls in exp (let expression) *
| if exp [;] then exp [;] else exp (conditional) *
| case exp of { alts } (case expression) *
| do { stmts } (do expression) *
| fexp
fexp → [fexp] aexp (function application)
aexp → qvar (variable)
| gcon (general constructor)
| literal
| ( exp ) (parenthesized expression)
| qcon { fbind1 … fbindn } (labeled construction)
| aexp { fbind1 … fbindn } (labelled update)
| …
The :extension:`BlockArguments` extension moves these production rules under
``aexp``
.. code-block:: none
lexp → fexp
fexp → [fexp] aexp (function application)
aexp → qvar (variable)
| gcon (general constructor)
| literal
| ( exp ) (parenthesized expression)
| qcon { fbind1 … fbindn } (labeled construction)
| aexp { fbind1 … fbindn } (labelled update)
| \ apat1 … apatn -> exp (lambda abstraction, n ≥ 1) *
| let decls in exp (let expression) *
| if exp [;] then exp [;] else exp (conditional) *
| case exp of { alts } (case expression) *
| do { stmts } (do expression) *
| …
Now the ``lexp`` nonterminal is redundant and can be dropped from the grammar.
Note that this change relies on an existing meta-rule to resolve ambiguities:
The grammar is ambiguous regarding the extent of lambda abstractions, let
expressions, and conditionals. The ambiguity is resolved by the meta-rule
that each of these constructs extends as far to the right as possible.
For example, ``f \a -> a b`` will be parsed as ``f (\a -> a b)``, not as ``f
(\a -> a) b``.
|