Suggestion for bang patterns documentation

I got confused by the GHC documentation recently, I was wondering how it could be improved. From: http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html
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.
The first sentence is true, but only in settings where the pattern is being evaluated eagerly -- the bang in:
f3 a = let !(x,y) = a in [1,x,y] f4 a = let (x,y) = a in [1,x,y] has an effect.
The first time I read this, I took the first sentence to be a unqualified truth and ended up thinking that !(x,y) was equivalent to (x,y) everywhere. Stuff that comes later actually clarifies this, but I missed it. What about making the distinction clear upfront? Something like:
A bang in an eager pattern match only really has an effect if it precedes a variable or wild-card pattern: f3 !(x,y) = [x,y] f4 (x,y) = [x,y] Because f4 _|_ will force the evaluation of the pattern match anyway, f3 and f4 are identical; the bang does nothing.
It also might be a good idea to immediately follow this with the let/where usage:
A bang can also preceed a let/where binding to make the pattern match strict. For example: let ![x,y] = e in b is a strict pattern... (in the existing docs, let comes a bit later):
Just a thought. Hopefully someone can come up with a better way of wording what I'm getting at. Thanks, -Brian _________________________________________________________________ Windows Live™ Hotmail®…more than just e-mail. http://windowslive.com/howitworks?ocid=TXT_TAGLM_WL_t2_hm_justgotbetter_howi...

good idea. done | -----Original Message----- | From: glasgow-haskell-users-bounces@haskell.org [mailto:glasgow-haskell-users- | bounces@haskell.org] On Behalf Of Brian Bloniarz | Sent: 27 February 2009 03:56 | To: glasgow-haskell-users@haskell.org | Subject: Suggestion for bang patterns documentation | | | I got confused by the GHC documentation recently, I was wondering how | it could be improved. From: | http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html | | > 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. | | The first sentence is true, but only in settings where the pattern is being | evaluated eagerly -- the bang in: | > f3 a = let !(x,y) = a in [1,x,y] | > f4 a = let (x,y) = a in [1,x,y] | has an effect. | | The first time I read this, I took the first sentence to be a unqualified truth | and ended up thinking that !(x,y) was equivalent to (x,y) everywhere. Stuff | that comes later actually clarifies this, but I missed it. | | What about making the distinction clear upfront? Something like: | > A bang in an eager pattern match only really has an effect if it precedes a | variable | > or wild-card pattern: | > f3 !(x,y) = [x,y] | > f4 (x,y) = [x,y] | > Because f4 _|_ will force the evaluation of the pattern match anyway, f3 and f4 | > are identical; the bang does nothing. | | It also might be a good idea to immediately follow this with the let/where usage: | | > A bang can also preceed a let/where binding to make the pattern match strict. For | example: | > let ![x,y] = e in b | > is a strict pattern... | (in the existing docs, let comes a bit later): | | Just a thought. Hopefully someone can come up with a better way of | wording what I'm getting at. | | Thanks, | -Brian | | _________________________________________________________________ | Windows Live(tm) Hotmail(r)...more than just e-mail. | http://windowslive.com/howitworks?ocid=TXT_TAGLM_WL_t2_hm_justgotbetter_howi... | 22009_______________________________________________ | Glasgow-haskell-users mailing list | Glasgow-haskell-users@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Brian Bloniarz wrote:
I got confused by the GHC documentation recently, I was wondering how it could be improved. From: http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html
Seeing the rule pat ::= !pat you'll probably want to avoid patterns like: "!!pat", "! ! pat", or "~ ! ~ pat". Even the current http://www.haskell.org/onlinelibrary/exps.html#sect3.17.1 apat -> ~ apat allows "~ ~x". (Note the space!) So maybe a separate non-terminal "bpat" should be used with: bpat -> [~|!] apat (and bpat used within pat). You may also want to exclude "v@ ~(...)" in favor of "~v@(...)".
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.
Maybe the duality (if it is one) should be added that an irrefutable pattern above would make a difference but not within the let below.
The first sentence is true, but only in settings where the pattern is being evaluated eagerly -- the bang in:
f3 a = let !(x,y) = a in [1,x,y] f4 a = let (x,y) = a in [1,x,y] has an effect.
Cheers Christian

Brian Bloniarz wrote:
I got confused by the GHC documentation recently, I was wondering how it could be improved. From: http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html
<cite> 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) </cite> Shouldn't the bang be removed in the final case pattern? Furthermore with existential types the let binding is not supported: data E = forall a . Show a => E a f :: E -> String f x = case x of E a -> show a f works, but g g :: E -> String g x = let !(E a) = x in show a fails (with or without the bang): My brain just exploded. I can't handle pattern bindings for existentially-quantified constructors. Instead, use a case-expression, or do-notation, to unpack the constructor. In the binding group for !(E a) In a pattern binding: !(E a) = x In the expression: let !(E a) = x in show a In the definition of `g': g x = let !(E a) = x in show a Cheers Christian P.S. It should be mentioned that ~ and ! only make sense for single variant data types (like tuples)

| <cite> | 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) | </cite> | | Shouldn't the bang be removed in the final case pattern? No. If p was a simple variable, then case rhs of x -> body is non-strict in Haskell, but should be strict here. | P.S. It should be mentioned that ~ and ! only make sense for single | variant data types (like tuples) That isn't true. Both are useful for multi-variant types Simon

Simon Peyton-Jones wrote:
| <cite> | 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) | </cite> | | Shouldn't the bang be removed in the final case pattern?
No. If p was a simple variable, then case rhs of x -> body is non-strict in Haskell, but should be strict here.
Thanks for pointing this out. But the case with a simple variable (and no distinction) is special anyway (sort of a monomorphic let binding).
| P.S. It should be mentioned that ~ and ! only make sense for single | variant data types (like tuples)
That isn't true. Both are useful for multi-variant types
Right, a non-empty list should behave like a pair as long as I don't want to know the variant beforehand and thereby forcing evaluation anyway. Cheers Christian
participants (3)
-
Brian Bloniarz
-
Christian Maeder
-
Simon Peyton-Jones