[Haskell] Views in Haskell
Malcolm.Wallace at cs.york.ac.uk
Wed Jan 24 09:58:37 EST 2007
Simon Peyton-Jones <simonpj at microsoft.com> wrote:
> I have finally written up a proposal for adding
> "view patterns" to Haskell.
I have taken the liberty of correcting a couple of mistakes in your
example code (on the wiki).
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? For example,
f ((name,rest) <- regexp "[a-z]*") = ...
does not seem so bad, especially when compared with the equivalent
f v | Just (name,rest) <- regexp "[a-z]*" v = ...
The form (pat <- expr) would seem to lend itself more naturally to the
idea that the 'expr' is applied to an (anonymous) value, yielding a
pattern. In contrast, the (expr -> pat) form looks too much like a
lambda abstraction, whose form is confusingly opposite: (\pat -> expr).
I concur with Claus that one of the major differences between this
proposal and pattern guards is the ability to nest view patterns, just
like all other existing patterns can be nested. This is perhaps its
most interesting feature. Using the '<-' arrow does not seem to obscure
this feature too much:
parsePacket ((n, (val,bs) <- bits n) <- bits 3) = ...
parsePacket (bits 3 -> (n, (bits n -> val bs))) = ...
Possible extension 1: multi-argument view patterns. This looks nasty.
The pain of introducing lots of extra types, (which will not appear
literally in user code in any case, but that are arbitrarily bounded in
number), does not balance against the minor saving of a couple of
brackets. Tuples already exist for that purpose. Indeed, the user may
wish their particular view to package up the multiple return values in a
different data structure, for further pattern deconstruction, e.g.
last_two :: [Int] -> (Int,Int)
last_two ((x:y:_) <- snoc) = (x,y)
Why treat tuples as more special than other ways of packaging multiple
Possible extension 2: no implicit Maybe. Making the Maybe constructors
explicit would even more clearly show how view patterns relate to
pattern guards. Indeed, it would be wonderful not to need to wrap the
result of the view in a Maybe! Rather than writing a special 'snoc'
function with type [a] -> Maybe (a,[a]), I could just use the normal
existing 'reverse' function:
last_two (Just (x:y:_) <- snoc) = (x,y)
last_two ((x:y:_) <- reverse) = (x,y)
Now the semantics of view patterns would be even simpler! In
(pat <- expr), after applying the expression to a value, if the inner
pattern matches, then the whole pattern matches. That's it. No
complications, no implicit monads. Nice.
More information about the Haskell