[Haskell] Views in Haskell
Claus Reinke
claus.reinke at talk21.com
Tue Jan 23 10:07:08 EST 2007
> http://hackage.haskell.org/trac/haskell-prime/wiki/ViewPatterns
>
>I'm thinking of implementing it in GHC, so I'd be interested in feedback of the form
> - how desirable is it to have a feature of this general form?
> - can this particular proposal be improved?
IMHO, getting a handle on the ADT vs pattern matching issues is overdue, so thanks
for raising this again. a few first comments:
1 I am a bit concerned about the use of non-linear patterns in your examples.
There are good arguments for non-linear patterns, and Haskellers have made good
arguments against non-linear patterns. But you seem to suggest allowing non-linear
patterns in some cases (related to view patterns), but not in others (general patterns).
That is likely to be confusing.
2 view patterns nicely separate expressions in patterns from pattern variables. But I
didn't realize at first that view patterns can be used nested inside other patterns.
Yet this variable binding during nested matching is the essential contribution, and
the only reason why the extra syntactic sugar is justified. Perhaps this point could
be repeated and emphasized in "The proposal more formally", for people like me?-)
3 what you call first class abstractions are not entirely orthogonal to view patterns.
taking Tullsen's and my own proposal as examples:
- the way patterns and alternatives are handled needs to fit together. that doesn't
seem to be a problem since your and our proposals agree on using what I call
a monadic data parsing framework (using a MonadPlus such as Maybe to handle
pattern match failure and alternatives)
- all three proposals have discussed how to handle patterns as well. For Tullsen,
that is central to his proposal, for me, it was only one of the more advanced
examples because I wanted to focus on match alternatives first.
Tullsen first builds his pattern combinators, then outlines a point-free style that
avoids the need for pattern variables althogether but does not seem to scale well,
then suggests syntactic sugar for translating patterns with variables into applications
of his combinators. So that last part is closely related to, if different from, your
proposal.
In my example, I build up patterns from de-constructors (which use tests and
selectors), so that a cons pattern takes a head pattern and a tail pattern as
parameters and applies them to the head and tail if it is applied to a non-empty
list. To handle variables, I use an old trick from the early functional logic
languages, namely that logic variables can be passed unbound, then bound to
values later, just what we need for pattern variables. Since Haskell doesn't
have logic variables, I have to simulate them, which is the only awkward bit
of the example:
http://www.haskell.org/pipermail/haskell-prime/2006-November/001915.html
as long as Haskell doesn't support logic variables, some syntactic sugar for
variables in nested patterns, such as Tullsen's or your's, is probably inevitable.
4 whether to use view patterns inside ordinary patterns, or whether to build up
patterns from abstract de-constructors (just as expressions are built from
abstract constructors) may seem only a question of style. but if your aim is
to encourage people to transition from exporting concrete data types to
exporting abstract types only, the latter approach seems more consistent
to me. In my example, a cons de-constructor would be as simple as
-- the cons view of array lists is a higher-order pattern that takes
-- patterns for the head and tail components, and applies them after
-- checking whether the list parameter is a non-empty list
consAP h t l = do { Match $ guard $ not (isNilA l); h (headA l); t (tailA l) }
but that relies on the scoping of (simulated) logic variables, and it does
not translate directly to your view patterns, as the h and t pattern parameters
would have their own scope for their pattern variables. It would be instructive
to have something equivalent to pattern constructors/abstract deconstructors
for view patterns, if only to see whether view patterns can support a fully
abstract style of nested matches easily. I am not entirely sure they do, but
here is a first attempt:
-- abstract list deconstructors / list pattern constructors
-- (consP takes h/t sub-patterns as parameters)
consP h t l = do { guard $ not (null l); hr <- h (head l); tr <- t (tail l); return (hr,tr) }
nilP l = do { guard $ null l; return () }
-- wildcard and variable patterns
wildP l = return ()
varP = return
-- extract the head of the tail of the parameter list, if that list has two elements
f (consP wildP (consP varP nilP) -> (_,(x,_))) = x
It seems a bit awkward to have to specify the structure of the parameter twice,
once to build up the pattern, then again to match sub-expressions to variables.
but would this work in principle at least?
5 possible extension 1 smells of superfluous complexity. There is almost no gain
compared to using tuples, but there's a lot to pay in added types and rules.
6 possible extension 2 seems a non-starter if we want compositional abstract
patterns, and I certainly do want them. Imagine the example in (4) with
explicit Maybe.
Being able to have compositional abstract patterns would be the make-or-break
criterion for me. Without them, new syntactic sugar wouldn't be justified, with
them, their precise form is a matter of convenience.
Claus
More information about the Haskell-prime
mailing list