
Personally I think ~ patterns are great, and we are now talking about ! patterns, a kind of dual to ~ patterns. So at least I think we should un-couple the two discussions.
I think so too. Removing ~ patterns seems like a fairly poor idea to me. Sure, they're not very much explicitly used (though everyone uses them implicitly in pattern bindings), but when you want them, they can be fairly important. I think perhaps we just need better coverage of ~ in the tutorials. Now that I think about it, I rather like the idea of ! patterns as well. They make ~ patterns seem more natural by contrast. Strictness can on occasion be just as important as laziness, and this notation makes it more convenient to obtain in simple cases. How to get a similarly pretty notation for more structured strictness annotations is a bit of a concern. I wonder whether some of the Control.Parallel.Strategies library should be more strategically located? :)
- Cale
I'd be fairly horrified at the removal of ~ patterns. I've used them to fix very serious space-leaks that would have been awkward to fix in any other way. I suppose if lazy pattern matching were provided by some other mechanism, say via let bindings, then I should always in principle be able to translate away a ~ pattern. But the translation will often be much more awkward. Actually, I think it's a much bigger wart that pattern matching in let and where is lazy, and everywhere else is strict, than that we have an operator ~ on patterns with a clean compositional semantics. Way back in the Haskell 98 process I tried to get that changed--so that patterns would be matched strictly EVERYWHERE unless you wrote ~ --but I lost that argument. John

I also use ~ patterns quite regularly and would be quite put off by their removal. and I know just how hard they are to implement :) I do look forward to using ! patterns too. I often find that making things more strict can often make things worse space-wise if not done quite carefully and the same is true of making things too lazy. being able to finely control this in both directions is a very useful feature. in any case, I thought I'd mention my favorite use of ~ patterns which is not actually their intended use. I use them to enforce preconditions that I don't expect a pattern match to fail. this is mainly used in list comprehensions. if I have a type like data E = EVar Var | EAp E E say I want to change the type on a list of variables, a list comprehension is often the nicest way to do it (imagine this were more complicated such that a list comprehension actually is needed) [ setType t v | EVar v <- vs | t <- ts ] now, I expect vs to be all variables, but imagine a bug makes an EAp float in there, suddenly my list is truncated mysteriously and odd things happen because the types all get offset by one! so I write it like this [ setType t v | ~(EVar v) <- vs | t <- ts ] it both documents my intent, and causes the compiler to enforce it at run time. another use I would use more if ghc got its incomplete pattern matching warning algorithm correct would be to document when I intend a pattern match to be partial f (Foo a) = a f ~(Bar x) = x this means that I expect the argument to never be anything other than a Foo or Bar so it is okay that I don't have more cases. again, it is both for documentation of intent and to suppress the compiler warning. John -- John Meacham - ⑆repetae.net⑆john⑈
participants (2)
-
John Hughes
-
John Meacham