6.2.17. 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)doprintxexitFailure
will be parsed as:
when(x>0)(doprintxexitFailure)
and
withForeignPtrfptr\ptr->c_memcpybufptrsize
will be parsed as:
withForeignPtrfptr(\ptr->c_memcpybufptrsize)
6.2.17.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->ab
will be parsed as f(\a->ab)
, not as f(\a->a)b
.