Here are some more thoughts about qualifier lists as guards (this time
starting with the less important ones).

Heribert.


1. I agree that my "simplify" example was not so good. In fact, one
   could do without nested qualifiers/guards easily because the first
   two qualifiers

     "s  <- Just (simplify e )" and "s' <- Just (simplify e')"

   have failure-free patterns, so that they could be replaced by
   definitions of s and s' in a "where" clause. So hopefully the
   following example with some test before the recursive calls is a bit
   more convincing:

     simplify (Plus e e') | someTest e e',
                            s  <- simplify e ,
                            s' <- simplify e'  | (Val 0) <- s  = s'
                                               | (Val 0) <- s' = s
                                               | otherwise     = (Plus s s')
     simplify e                                                = e

2. A list of qualifiers happens to work nicely in the "clunky" example,
   because the test "ok1 && ok2" is a conjunction and in a way the
   members of a list of qualifiers are also connected cunjunctively.
   (What can we learn from this observation???)

3. From Alex' example (version 5a) one could have learned that we do not
   need guards at all, because all sorts of guards (today's Haskell
   guards, Peyton-Jones-style guards, and nested guards) can be replaced
   by the Maybe monad in a *straightforward* way:

     clunky env var1 var2 = fromJust (do val1 <- lookup env var1,
                                         val2 <- lookup env var2
                                         Just val1 + val2
                                      ++
                                      Just (var1 + var2) )

     simplify e = fromJust (do (Plus e e') <- e
                               guard (someTest e e')
                               s  <- Just (simplify e ),
                               s' <- Just (simplify e'),
                               (do (Val 0) <- Just s ; Just s
                                ++
                                do (Val 0) <- Just s'; Just s'
                                ++
                                Just (Plus s s'))
                            ++
                            Just e)

   According to this, one might consider abolishing guards in function
   definitions entirely. Guards (and even multiple equations for
   defining a function!) could be seen as a relic from the times when
   there was no syntactic support for monads in Haskell.

   I don't advertise such a solution, e.g., because it is not backward
   compatible. I just pointed it out because Maybe has been used as an
   argument against the need for nested guards.

4. Another argument against nested guards has been that they are
   "against the spirit of independent guarded equations". This is true,
   but isn't it also against this spirit that one may write

     f pats | guard1 = expr1
            ...
            | guardn = exprn

   instead of

     f pats | guard1 = expr1
     ...
     f pats | guardn = exprn

   ?

   With traditional guards, matching consists of two major parts:
   pattern matching + boolean tests. Factoring out common subexpressions
   is possible only at the border of these two parts. With Simon's
   proposal boolean tests and matching may be more freely mixed, but
   factoring out is still only allowed after some prefix of matching
   operations but not later.

   This gave me the impression that the proposal might have been more
   orthogonal in this respect and has lead to the suggestions in my
   previous mail.

5. The more I think about it, the more I am in favour of Simon's
   qualifier lists (i.e., without nesting), but with semantics according
   to the Maybe monad. It has several advantages (the last one being the
   most important one in my eyes):

   - The syntax is not a problem:

       clunky env var1 var1 | val1 <- lookup env var1,
                              val2 <- lookup env var2
                            = val1 + val2
       ...other equations for clunky...

   - It is as backward compatible as Simon's proposal.

   - It does not need the explananation of a new semantics for "<-" with
     a non-monadic expression on the RHS.

   - It does allow nesting for those who want it, because they can use
     "++" on the RHS of "<-". (Note that this is even more flexible than
     the "nested qualifiers" approach.)

   - What are the possible results of pattern matching? It may fail or
     succeed, and in the latter case some data is available. This is
     exactly what Maybe has been introduced for.

6. I admit that my considerations in this message are not mainly driven
   by the desire to solve some concrete programming need (and certainly
   not in an ad-hoc way), but more by the desire to keep the language
   orthogonal (although you might even question this).



Reply via email to