Bang patterns, ~ patterns, and lazy let

I just looked at the bang pattern proposal in more detail. To summarise: * Pattern-matching is presently strict against constructors, lazy against variables. * ~p matches p lazily; matching always succeeds, binding the variables in p to _|_ if matching p fails. * !p matches p strictly; matching always loops if the value matched is _|_, even if p is a variable or ~ pattern. Note that !~p is not the same as p (matching it can never fail, p itself is not matched strictly), but ~!p is the same as ~p. So far, so good--everything has a clean semantics and is easy to understand. Now for the warts: * Patterns on the left hand side of a let or where are implicitly preceded by ~, making matching in these contexts lazy by default. * ! on the left hand side of a let or where *has a different meaning to ! in a pattern* -- it means that the ~ that would have been implicitly inserted by the previous rule, is not inserted after all! This is not the same as banging the pattern with the implicit ~, because as I remarked above, !~p is not the same as p. This really, really smacks of committee design, doesn't it? Come on, it's a dog's breakfast! I've made clear before that I consider the FIRST rule above (that matching in let and where has an implicit ~) to be a wart already, but giving ! a second meaning to control whether or not the first wart is really applied is growing warts on warts! The one good thing to be said for this design is that it doesn't break existing code. But really--the design is unreasonably complex, and would just store up trouble for the future. Imagine trying to make a further extension to pattern matching next time Haskell is revised, without breaking code that relies on the warts on warts above! I would urge that either we stick with the present design, or, if bang patterns are added (which a lot speaks for), that the language be simplified at the same time so that patterns are matched in the same way everywhere, and BOTH warts above are excised. Some existing code would break, but in return the language would become simpler and more expressive. John

On Tue, Feb 07, 2006 at 09:02:36AM +0100, John Hughes wrote:
I would urge that either we stick with the present design, or, if bang patterns are added (which a lot speaks for), that the language be simplified at the same time so that patterns are matched in the same way everywhere, and BOTH warts above are excised. Some existing code would break, but in return the language would become simpler and more expressive.
Would top-level bindings of constructor patterns and !x be evaluated when the module was loaded (or at compile time)?

John Hughes wrote:
* ! on the left hand side of a let or where *has a different meaning to ! in a pattern* -- it means that the ~ that would have been implicitly inserted by the previous rule, is not inserted after all!
I wish it were that simple, but I don't think it is. let { !x = const undefined y ; !y = const 'a' x } in y desugars in the current proposal to let { x = const undefined y ; y = const 'a' x } in x `seq` y `seq` y which is _|_, but absent implicit ~, let { x = const undefined y ; y = const 'a' x } in y had better (and does) mean 'a'. It's also not that case that !x has the same meaning in both proposals, e.g. let { !x = y ; !y = const 'a' x } in x means 'a' in the current proposal but _|_ in yours. My experience is that "top-level" strictness information has a very different nature from "nested" strictness information, and it's not generally possible to find a single interpretation that covers both. The reason is that strictness is a relationship between a value and its continuation (i.e. context). Nested strictness annotations connect data to a datatype context; top-level strictness annotations in this case connect data to either a case context or a let context. Each of the three situations has to be considered separately.
This is not the same as banging the pattern with the implicit ~, because as I remarked above, !~p is not the same as p.
Actually if ! patterns were handled consistently in let they would come out as ~!p = ~p, so the ! would have no effect. The current proposal effectively borrows the ! notation, which would otherwise be useless, for a different purpose in this case. -- Ben
participants (3)
-
Ben Rudiak-Gould
-
John Hughes
-
Ross Paterson