[Haskell] Views in Haskell

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Wed Jan 24 10:25:00 EST 2007

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",

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)))
foo (x1:x2:x3:[])


More information about the Haskell mailing list