From GHC user guide it seems like most Pat
can be PBangPat
, but there are a few exceptions. e.g. top-level bangs in a module (like !main
) aren't allowed and x : !xs
fails to parsex : (!xs) parses
thanks @chi. What is the formal specification about where the bangs can be added? I've looked into some chapters of the user guide and the Report but found nothing.

- 893
- 4
- 18
-
2Good question, though in doubt it's probably best not to use BangPatterns at all but good old `seq`. – leftaroundabout Aug 03 '15 at 14:52
1 Answers
There is no accepted formal specification for BangPatterns since they are not a part of any Haskell Report. The closest thing we have to a specification is the User's Guide along with the haskell-prime proposal it links to.
Both of those sources explicitly mention that a bang pattern is not allowed at the top level of a module.
As for x : !xs
, the User's Guide has this to say about the syntax of bang patterns:
We add a single new production to the syntax of patterns:
pat ::= !pat
It should be read in conjunction with the Haskell 2010 Report:
pat ::= lpat qconop pat | lpat lpat ::= apat | - (integer | float) | gcon apat_1 ... apat_k apat ::= var [ @ apat] | ... | ( pat ) | ...
According to these rules x : !xs
actually should parse (since !xs
is a pat
, the whole thing is lpat qconop pat
). So either the User's Guide (and the haskell-prime proposal) is wrong or GHC is wrong on this point.
I believe that in practice the syntax accepted by GHC is "anything that looks like a valid expression" including interpreting (!x)
as a section of the operator !
. For example (! Just x)
is accepted as a pattern but (! ! x)
is not.

- 14,951
- 3
- 39
- 49
-
2Actually [the relevant section of the User's Guide](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/bang-patterns.html#bang-patterns-sem) is so old that it links to the *Haskell 98* report, and the BNF grammar at that time treated precedence differently. [For patterns in particular](https://www.haskell.org/onlinereport/exps.html#sect3.17.1), adding `pat ::= !pat` means to add it at the *lowest precedence*. – Ørjan Johansen Aug 04 '15 at 03:08
-
Although disturbingly, by this reading `(! ! x)` *should* work but doesn't. – Ørjan Johansen Aug 04 '15 at 03:14
-
@ØrjanJohansen, oh good point. I didn't try following the links to the Report since I already had the 2010 Report open in another tab. That does make the description closer to reality, though as you say still not quite the same. – Reid Barton Aug 04 '15 at 15:11
-
See also https://ghc.haskell.org/trac/ghc/ticket/1087 and https://ghc.haskell.org/trac/ghc/ticket/10732. – thomie Dec 13 '15 at 23:03