
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⑈