On Wed, 2007-01-24 at 14:58 +0000, Malcolm Wallace wrote:
To add to the bikeshed discussion of syntax, did you consider and reject the obvious use of '<-' rather than '->', which would more closely match the pattern guard syntax?
Using the '<-' arrow does not seem to obscure this feature too much: parsePacket ((n, (val,bs) <- bits n) <- bits 3) = ... vs parsePacket (bits 3 -> (n, (bits n -> val bs))) = ...
The main drawback to this is that we don't get the left to right binders and uses. That is we use 'n' as a variable binder when we extract the 3 bits and then use that later to decide how many bits to extract. With the '<-' form the flow is all back and forth rather than left to right. In Erlang they have these bit/byte patterns: parseIpPacket << version: 4, ihl: 4, tos: 8, ... , optionsAndPadding: tos*5-32, data >> = ... See: "Applications, Implementation and Performance. Evaluation of Bit Stream Programming in Erlang", http://user.it.uu.se/~kostis/Papers/padl07.pdf The point is that it's common for things matched earlier to get used later. Simon's original suggestion allows the left-to-right match & usage that makes this kind of pattern neat. On the other hand I do see the problem with the use of '->' in views and in lambda abstractions. My first thought after seeing the erlang bit/bytestring patterns was something like a mix of pattern guards but with some monad syntax: parseIpPacket packet | do version <- bits 4 ihl <- bits 4 tos <- bits 8 ... optionsAndPadding <- bits (tos*5-32) data <- remainder(?!) = ... The idea is that it looks much like a monad, monadic fail makes the pattern match fail (just like pattern gaurds) and the variables bound in the LHS are available for subsequent patterns (just like pattern gaurds) and also bound in the RHS. However it really is a monad and so can carry some state along (in this case the current bit offset and/or the tail of the bitstring). I guess that means the RHS has to be in the monad. What's different from an ordinary do is that failure in the monad somehow becomes pattern match failure. Don't ask me exactly how that works! :-) It's just what I felt was a reasonably Haskelly translation of the Erlang example. It's not nested patterns of course. I'm not convinced that deeply nested (->) or (<-) style view patterns would make the Erlang bit matching examples look very nice. Afterall it only works for lists in Haskell because of infix patterns and data constructors. Nobody would like writing: foo (Cons x1 (Cons x2 (Cons x3 Nil))) vs foo (x1:x2:x3:[]) Duncan