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

_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime

Reply via email to