[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