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.