# Changes between Version 3 and Version 4 of BangPatterns

Ignore:
Timestamp:
Feb 6, 2006 11:03:52 AM (10 years ago)
Comment:

--

Unmodified
Removed
Modified
• ## BangPatterns

 v3 the module initialisation is performed. But it's not clear why it would be necessary or useful.  Conservative conclusion: no top-level bang-patterns. But it's not clear why it would be necessary or useful.  '''Conservative conclusion''': no top-level bang-patterns. == Recursive let and where bindings == But (a) it must be unusual, and (b) I have found it very hard to come up with a plausible translation (that deals with all the tricky points). Conservative conclusion: bang-pattern bindings must be non-recursive. === Tricky point: syntax === points below). '''Conservative conclusion''': bang-pattern bindings must be non-recursive. == Tricky point: syntax == What does this mean? }}} === Tricky point: nested bangs === Another point that came up in implementation is this.  In GHC, at least, ''patterns'' are initially parsed as ''expressions'', because Haskell's syntax doesn't let you tell the two apart until quite late in the day. In expressions, the form {{{(! x)}}} is a right section, and parses fine. But the form {{{(!x, !y)}}} is simply illegal.  Solution: in the syntax of expressions, allow sections without the wrapping parens in explicit lists and tuples.  Actually this would make sense generally: what could {{{(+ 3, + 4)}}} mean apart from a tuple of two sections? == Tricky point: nested bangs == Consider this: not evaluated; but `y` '''is''' evaluated. This means that you can't give the obvious alternative translation that uses just let-bindings and {{{seq}}.  For example, we could attempt to translate the example to: {{{ let t = x = case t of (x, Just !y) -> x y = case t of (x, Just !y) -> y in t `seq` }}} This won't work, because using `seq` on `t` won't force `y`. You could build an intermediate tuple, thus: {{{ let t = case of (x, Just !y) -> (x,y) x = fst t y = snd t in t `seq` }}} But that seems a waste when the patttern is itself just a tuple; and it needs adjustment when there is only one bound variable. Bottom line: for non-recursive bindings, the straightforward translation to a `case` is, well, straightforward.   Recursive bindings could probably be handled, but it's more complicated. == Tricky point: pattern-matching semantics == A bang is part of a ''pattern''; matching a bang forces evaluation. So the exact placement of bangs in equations matters. For example, there is a difference between these two functions: {{{ f1 x  True  = True f1 !x False = False f2 !x True  = True f2  x False = False }}} Since pattern matching goes top-to-bottom, left-to-right, {{{(f1 bottom True)}}} is {{{True}}}, whereas {{{(f2 bottom True)}}} is {{{bottom}}}. == Tricky point: polymorphism == But if this is Haskell source, then `f` won't be polymorphic. One could say that the translation isn't required to preserve the static semantics, but GHC, at least, translates into System F, and being able to do so is a good sanity check.  If we were to do that, then we would need {{{ :: Maybe (forall a. Num a => a -> a) }}} so that the case expression works out in System F: {{{ case of { Just (f :: forall a. Num a -> a -> a) -> (f Int dNumInt (1::Int), f Integer dNumInteger (2::Integer) } }}} The trouble is that `` probably has a type more like {{{ :: forall a. Num a => Maybe (a -> a) }}} ...and now the dictionary lambda may get in the way of forcing the pattern. This is a swamp.  '''Conservative conclusion''': no generalisation (at all) for bang-pattern bindings. == Changes to the Report == The changes to the Report would be these The changes to the Report would be these.  (Incomplete.) * Section 3.17, add pat ::= !pat to the syntax of patterns.