6.2.18. More liberal syntax for function arguments¶
-
BlockArguments
¶ 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
(The recursive do-notation), \case
(Lambda-case), and
proc
(Arrow notation).
The 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)
6.2.18.1. Changes to the grammar¶
The Haskell report defines
the lexp
nonterminal thus (*
indicates a rule of interest)
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 BlockArguments
extension moves these production rules under
aexp
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
.