8.10. Bang patterns

GHC supports an extension of pattern matching called bang patterns. Bang patterns are under consideration for Haskell Prime. The Haskell prime feature description contains more discussion and examples than the material below.

Bang patterns are enabled by the flag -XBangPatterns.

8.10.1. Informal description of bang patterns

The main idea is to add a single new production to the syntax of patterns:

  pat ::= !pat

Matching an expression e against a pattern !p is done by first evaluating e (to WHNF) and then matching the result against p. Example:

f1 !x = True

This definition makes f1 is strict in x, whereas without the bang it would be lazy. Bang patterns can be nested of course:

f2 (!x, y) = [x,y]

Here, f2 is strict in x but not in y. A bang only really has an effect if it precedes a variable or wild-card pattern:

f3 !(x,y) = [x,y]
f4 (x,y)  = [x,y]

Here, f3 and f4 are identical; putting a bang before a pattern that forces evaluation anyway does nothing.

Bang patterns work in case expressions too, of course:

g5 x = let y = f x in body
g6 x = case f x of { y -> body }
g7 x = case f x of { !y -> body }

The functions g5 and g6 mean exactly the same thing. But g7 evaluates (f x), binds y to the result, and then evaluates body.

Bang patterns work in let and where definitions too. For example:

let ![x,y] = e in b

is a strict pattern: operationally, it evaluates e, matches it against the pattern [x,y], and then evaluates b The "!" should not be regarded as part of the pattern; after all, in a function argument ![x,y] means the same as [x,y]. Rather, the "!" is part of the syntax of let bindings.

8.10.2. Syntax and semantics

We add a single new production to the syntax of patterns:

  pat ::= !pat

There is one problem with syntactic ambiguity. Consider:

f !x = 3

Is this a definition of the infix function "(!)", or of the "f" with a bang pattern? GHC resolves this ambiguity in favour of the latter. If you want to define (!) with bang-patterns enabled, you have to do so using prefix notation:

(!) f x = 3

The semantics of Haskell pattern matching is described in Section 3.17.2 of the Haskell Report. To this description add one extra item 10, saying:

  • Matching the pattern !pat against a value v behaves as follows:

    • if v is bottom, the match diverges

    • otherwise, pat is matched against v

Similarly, in Figure 4 of Section 3.17.3, add a new case (t):

case v of { !pat -> e; _ -> e' }
   = v `seq` case v of { pat -> e; _ -> e' }

That leaves let expressions, whose translation is given in Section 3.12 of the Haskell Report. In the translation box, first apply the following transformation: for each pattern pi that is of form !qi = ei, transform it to (xi,!qi) = ((),ei), and and replace e0 by (xi `seq` e0). Then, when none of the left-hand-side patterns have a bang at the top, apply the rules in the existing box.

The effect of the let rule is to force complete matching of the pattern qi before evaluation of the body is begun. The bang is retained in the translated form in case qi is a variable, thus:

  let !y = f x in b

The let-binding can be recursive. However, it is much more common for the let-binding to be non-recursive, in which case the following law holds: (let !p = rhs in body) is equivalent to (case rhs of !p -> body)

A pattern with a bang at the outermost level is not allowed at the top level of a module.