Iavor Diatchki | 4 Dec 20:39

Nested guards?

Hi,
Lately I have been using pattern guards more than usual and I find
that occasionally I need to nest them (i.e., I have alternatives with
a common prefix).  This seems to happen when I need to do some
preliminary checking, followed by some decision making.  Here is an
example:

server text
   | Just xs <- parse text
   ,   | "field1" `elem` xs   = ... do one thing ...
       | "field2" `elem` xs   = ... do something else ...

server  _ = ... invalid request ...

As far as I can see this should be a fairly simple change to the
pattern bindings extension.   Would anyone else find this a useful
feature, and if so what syntax should we use?

-Iavor
Roberto Zunino | 4 Dec 21:23

Re: Nested guards?

Iavor Diatchki wrote:
> server text
>    | Just xs <- parse text
>    ,   | "field1" `elem` xs   = ... do one thing ...
>        | "field2" `elem` xs   = ... do something else ...
> 
> server  _ = ... invalid request ...

What about:

server text
   | Just xs <- parse text = let
     x | "field1" `elem` xs   = error "... do one thing ..."
       | "field2" `elem` xs   = error "... do something else ..."
     in x
server  _ = error "... invalid request ..."

Regards,
Zun.
Neil Mitchell | 4 Dec 21:46

Re: [Haskell] Nested guards?

Hi

> server text
>    | Just xs <- parse text = let
>      x | "field1" `elem` xs   = error "... do one thing ..."
>        | "field2" `elem` xs   = error "... do something else ..."
>      in x
> server  _ = error "... invalid request ..."

This now has the wrong semantics - before if parse text returned Just
[] the error invalid request branch was invoked, now its a pattern
match failure.

I haven't used pattern guards that much (but will once Haskell'
standardises them, or they get implemented in Hugs!), but their syntax
seems quite natural. This extension seems to make it harder to
understand them, and gives some nasty , | parsing issues for a human
at least - quite possibly for a compiler too. Perhaps if you gave a
little grammar for extended pattern guards (compared to the original)
it would be easier to see how naturally they fit in.

Thanks

Neil
Roberto Zunino | 4 Dec 22:55

Re: [Haskell] Nested guards?

Neil Mitchell wrote:
>> server text
>>    | Just xs <- parse text = let
>>      x | "field1" `elem` xs   = error "... do one thing ..."
>>        | "field2" `elem` xs   = error "... do something else ..."
>>      in x
>> server  _ = error "... invalid request ..."
> 
> This now has the wrong semantics - before if parse text returned Just
> [] the error invalid request branch was invoked, now its a pattern
> match failure.

I missed that, thanks.

The MonadPlus way is not as elegant, but not too ugly I think:

server text =
  do   Just xs <- return $ parse text
       do   guard $ "field1" `elem` xs
            return "... do one thing ..."
         `mplus` do
            guard $ "field2" `elem` xs
            return "... do something else ..."
    `mplus`
       return "... invalid request ..."

Zun.
Nicolas Frisby | 5 Dec 04:26

Re: Re: [Haskell] Nested guards?

It seems there is previous background here that I am unaware of. I'll
chime in anyway.

What you describe as the "wrong semantics" seems to me to be the more
appropriate. I am inferring that your expected behavior is explained
such that the first server match ought to fail (and fall through to
the second server match) because the pattern in the let fails. This
seems odd to me. If the parse test expression yields a Just
constructor, then hasn't the first server match succeeded and we ought
now commit to the let expression?

I apologize if this should be obvious to anyone familiar with the extension.

On Dec 4, 2007 2:46 PM, Neil Mitchell <ndmitchell <at> gmail.com> wrote:
> Hi
>
> > server text
> >    | Just xs <- parse text = let
> >      x | "field1" `elem` xs   = error "... do one thing ..."
> >        | "field2" `elem` xs   = error "... do something else ..."
> >      in x
> > server  _ = error "... invalid request ..."
>
> This now has the wrong semantics - before if parse text returned Just
> [] the error invalid request branch was invoked, now its a pattern
> match failure.
>
> I haven't used pattern guards that much (but will once Haskell'
> standardises them, or they get implemented in Hugs!), but their syntax
> seems quite natural. This extension seems to make it harder to
(Continue reading)

Iavor Diatchki | 5 Dec 04:45

Re: Re: [Haskell] Nested guards?

Hello everyone,
Just to clarify, the intended semantics of my example was that it
should behave as if we were to duplicate the common prefix:

server text
  | Just xs <- parse text, "field1" `elem` xs   = ... do one thing ...
  | Just xs <- parse text, "field2" `elem` xs   = ... do something else ...

server  _ = ... invalid request ...

The difference is that the nested version is shorter, and probably way
easier for the compiler to produce reasonable code.    As I said in my
first post, I am not sure what would be a nice notation for nesting
the guards:  the notation that I used in the example was just the
first thing that came to mind, we might be able to do better.

-Iavor

On Dec 4, 2007 7:26 PM, Nicolas Frisby <nicolas.frisby <at> gmail.com> wrote:
> It seems there is previous background here that I am unaware of. I'll
> chime in anyway.
>
> What you describe as the "wrong semantics" seems to me to be the more
> appropriate. I am inferring that your expected behavior is explained
> such that the first server match ought to fail (and fall through to
> the second server match) because the pattern in the let fails. This
> seems odd to me. If the parse test expression yields a Just
> constructor, then hasn't the first server match succeeded and we ought
> now commit to the let expression?
>
(Continue reading)

Taral | 5 Dec 00:02

Re: Nested guards?

On 12/4/07, Roberto Zunino <zunino <at> di.unipi.it> wrote:
> server text
>    | Just xs <- parse text = let
>      x | "field1" `elem` xs   = error "... do one thing ..."
>        | "field2" `elem` xs   = error "... do something else ..."
>      in x
> server  _ = error "... invalid request ..."

Not the same fallthrough properties. You'd have to clone the "server
_" clause into the x clause.

--

-- 
Taral <taralx <at> gmail.com>
"Please let me know if there's any further trouble I can give you."
    -- Unknown
Per Gundberg | 5 Dec 00:16
Favicon

Re: Nested guards?

Have you looked at the proposed view patterns? It seems like it would
cover the case you gave here. I don't know if there's work being done in
this area though.

http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns

//Gundberg

> Hi,
> Lately I have been using pattern guards more than usual and I find
> that occasionally I need to nest them (i.e., I have alternatives with
> a common prefix).  This seems to happen when I need to do some
> preliminary checking, followed by some decision making.  Here is an
> example:
>
> server text
>    | Just xs <- parse text
>    ,   | "field1" `elem` xs   = ... do one thing ...
>        | "field2" `elem` xs   = ... do something else ...
>
> server  _ = ... invalid request ...
>
> As far as I can see this should be a fairly simple change to the
> pattern bindings extension.   Would anyone else find this a useful
> feature, and if so what syntax should we use?
>
> -Iavor
> _______________________________________________
> Haskell mailing list
> Haskell <at> haskell.org
(Continue reading)

Wolfgang Jeltsch | 5 Dec 23:12

Re: Nested guards?

Am Mittwoch, 5. Dezember 2007 00:16 schrieb Per Gundberg:
> Have you looked at the proposed view patterns? It seems like it would
> cover the case you gave here. I don't know if there's work being done in
> this area though.
>
> http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns
>
> //Gundberg

I cannot resist citing Henning Thielemann (actually translating from German).  
The following text is from is very good squib about how to become a scripting 
language hater within five days [1].  Please take it with a grain of humor.  
I don’t want to offend anyone.

Here’s the text:

> The root idea of functional programming simplifies many things.  No need to
> distinguish between constants and variables, no “call by reference”, no
> assignments, no predefined loop structures—everything is manageable and the
> effects of functions are controllable.   
>
> It is clear that this situation must not stay this way.  Bit by bit,
> disciples of Perl and Python discover Haskell and demand that Haskell will
> be plastered with syntactic sugar until the simplicity of the functional
> approach isn’t visible anymore.  Sadly, they seem to be successful with this
> as syntax extensions like parallel list comprehensions show.  
>
> Many Haskell newcomers don’t seem to bother studying the concept of
> functions and the wide variety of applications of higher order functions.
> They rather avoid everything systematic and construct their programs mainly
(Continue reading)

Johannes Waldmann | 6 Dec 01:03
Favicon

Re: Nested guards?

Wolfgang Jeltsch wrote:

> I cannot resist citing Henning Thielemann [...]

Amen to that.
Simon Peyton-Jones | 6 Dec 10:03

RE: [Haskell] Nested guards?

[redirecting to Haskell Cafe]

| > It is clear that this situation must not stay this way.  Bit by bit,
| > disciples of Perl and Python discover Haskell and demand that Haskell will
| > be plastered with syntactic sugar until the simplicity of the functional
| > approach isn’t visible anymore.  Sadly, they seem to be successful with this
| > as syntax extensions like parallel list comprehensions show.

I think it is helpful to distinguish "superficial" complexity from "deep" complexity.   All of Haskell's
syntactic sugar is just that: it can be translated into a small purely-functional language using
straightforward translation schemes.  Even something relatively complicated like the "order by/group
by" extension that Phil and I proposed at this year's Haskell workshop, has an easy translation that takes
a dozen or two lines to give in full detail.

In contrast, something like higher order functions, or mutable state, is deep complexity. Both have a
pervasive effect on the language semantics and on its implementation.  (The effect of mutable state is
much, much worse, but they are both deep.)


Concerning Haskell, I'm quite relaxed about superficial complexity, as you'll have seen from what
happens in GHC.  Section 3.6 of the History of Haskell paper addresses this point specifically [1].  You may
disagree with the choice made by the Haskell committee at the time, and with subsequent developments, but
it was quite a conscious choice, and one not without its advantages.

Simon

[1] http://research.microsoft.com/%7Esimonpj/papers/history-of-haskell/history.pdf

_______________________________________________
(Continue reading)

Wolfgang Jeltsch | 6 Dec 12:20

Re: [Haskell] Nested guards?

Am Donnerstag, 6. Dezember 2007 10:03 schrieb Simon Peyton Jones:
> [redirecting to Haskell Cafe]
>
> | > It is clear that this situation must not stay this way.  Bit by bit,
> | > disciples of Perl and Python discover Haskell and demand that Haskell
> | > will be plastered with syntactic sugar until the simplicity of the
> | > functional approach isn’t visible anymore.  Sadly, they seem to be
> | > successful with this as syntax extensions like parallel list
> | > comprehensions show.
>
> I think it is helpful to distinguish "superficial" complexity from "deep"
> complexity.   All of Haskell's syntactic sugar is just that: it can be
> translated into a small purely-functional language using straightforward
> translation schemes.  Even something relatively complicated like the "order
> by/group by" extension that Phil and I proposed at this year's Haskell
> workshop, has an easy translation that takes a dozen or two lines to give
> in full detail.
>
> In contrast, something like higher order functions, or mutable state, is
> deep complexity. Both have a pervasive effect on the language semantics and
> on its implementation.  (The effect of mutable state is much, much worse,
> but they are both deep.)

The point is that higher order functions, type classes, etc. enable you 
to “extend the language yourself” to a large degree by just creating 
libraries.  Such powerful concepts give you the ability to create domain 
specific languages by just writing Haskell code.  So they serve the approach 
of having few concepts in the language which allow you to do many things.

On the other hand, syntactic sugar often deals with very special cases.  
(Continue reading)

Aaron Denney | 6 Dec 22:47
X-Face

Re: [Haskell] Nested guards?

On 2007-12-06, Wolfgang Jeltsch <g9ks157k <at> acme.softbase.org> wrote:
> list comprehensions deal with specific operations (map, filter, etc.)
> of a specific type ([]).

Ah, so we should bring back monad comprehensions?

--

-- 
Aaron Denney
-><-
Ben Franksen | 6 Dec 23:40

Re: [Haskell] Nested guards?

Aaron Denney wrote:
> On 2007-12-06, Wolfgang Jeltsch <g9ks157k <at> acme.softbase.org> wrote:
>> list comprehensions deal with specific operations (map, filter, etc.)
>> of a specific type ([]).
> 
> Ah, so we should bring back monad comprehensions?

I don't miss monad comprehension much, but I'd like to have a way to use
comprehension for other sequence types, notably ByteString, array types and
Data.Sequence (other than converting to lists and back).

Cheers
Ben
Stefan O'Rear | 7 Dec 02:25

Re: Re: [Haskell] Nested guards?

On Thu, Dec 06, 2007 at 11:40:58PM +0100, Ben Franksen wrote:
> Aaron Denney wrote:
> > On 2007-12-06, Wolfgang Jeltsch <g9ks157k <at> acme.softbase.org> wrote:
> >> list comprehensions deal with specific operations (map, filter, etc.)
> >> of a specific type ([]).
> > 
> > Ah, so we should bring back monad comprehensions?
> 
> I don't miss monad comprehension much, but I'd like to have a way to use
> comprehension for other sequence types, notably ByteString, array types and
> Data.Sequence (other than converting to lists and back).

If we had monad comprehensions and some kind of restricted monads (see
my post 'Constructor classes considered harmful', but note that I didn't
then and still don't have a tolerable replacement), we'd get bytestring
/ sequence comprehensions for free.

Stefan
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wolfgang Jeltsch | 7 Dec 00:19

Re: Re: [Haskell] Nested guards?

Am Donnerstag, 6. Dezember 2007 22:47 schrieb Aaron Denney:
> On 2007-12-06, Wolfgang Jeltsch <g9ks157k <at> acme.softbase.org> wrote:
> > list comprehensions deal with specific operations (map, filter, etc.)
> > of a specific type ([]).
>
> Ah, so we should bring back monad comprehensions?

No, we already have do expressions.

Best wishes,
Wolfgang
Simon Peyton-Jones | 7 Dec 10:29

RE: [Haskell] Nested guards?

| And I think that the solution is not to make the language larger and larger
| everytime someone wants a feature but to give people the tools to provide
| features without language changes.

Of course that would be even better!  (Provided of course the resulting programs were comprehensible.) 
Haskell is already pretty good in this respect, thanks to type classes, higher order functions, and
laziness; that's why it's so good at embedded domain-specific languages.  Template Haskell is another
attempt to go further. Geoff Mainland's quasi-quoting idea is another.

If you have other ideas for such general tools, then it'd be great to hear about them.  They are much easier to
wish for than to design.

But where such general tools are inadequate, well-designed syntactic sugar can have a powerfully
beneficial effect, I think.  But it's a topic on which reasonable people can differ, and your judgement may
well differ from mine.

Simon
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Henning Thielemann | 7 Dec 14:11

group-by (Was: Nested guards?)


On Fri, 7 Dec 2007, Simon Peyton-Jones wrote:

> | And I think that the solution is not to make the language larger and larger
> | everytime someone wants a feature but to give people the tools to provide
> | features without language changes.
>
> Of course that would be even better!  (Provided of course the resulting
> programs were comprehensible.)  Haskell is already pretty good in this
> respect, thanks to type classes, higher order functions, and laziness;
> that's why it's so good at embedded domain-specific languages.

When I learned about GROUP BY and HAVING in SQL with its rules about what
is allowed in GROUP BY and SELECT I considered GROUP BY a terrible hack,
that was just introduced because the SQL people didn't want to allow types
different from TABLE, namely lists of tables. I try to convince my data
base colleagues that GROUP BY can nicely be handled in relational algebra
by allowing sets of sets and that this is a fine combinatorial approach. I
think we simply need a function like
  buckets :: (a -> key) -> [a] -> [(key, [a])]
      (where (a -> key) is a simple selector)
 or
  buckets :: (a -> (key, rest)) -> [a] -> [(key, [rest])]
      (where  (a -> (key, rest)) is a bijection)
 or
  buckets :: Ord key => ... ah no :-)
  buckets :: Indexable key => (a -> (key, rest)) -> [a] -> Map key [rest]
  buckets f = Map.fromListWith (++) . map (\ a -> let (k,r) = f a in (k, [r]))

Btw. since I often need fromListWith with Maps of list types, I wonder
(Continue reading)

Anthony Clayden | 11 Dec 06:18

Re: group-by (Was: Nested guards?)

Henning Thielemann <lemming <at> henning-thielemann.de> writes:

> 
> 
> On Fri, 7 Dec 2007, Simon Peyton-Jones wrote:
> 
> > | And I think that the solution is not to make the language larger and 
larger
> > | everytime someone wants a feature but to give people the tools to provide
> > | features without language changes.
> >
> > Of course that would be even better!  (Provided of course the resulting
> > programs were comprehensible.)  Haskell is already pretty good in this
> > respect, thanks to type classes, higher order functions, and laziness;
> > that's why it's so good at embedded domain-specific languages.
> 
> When I learned about GROUP BY and HAVING in SQL with its rules about what
> is allowed in GROUP BY and SELECT I considered GROUP BY a terrible hack,
> that was just introduced because the SQL people didn't want to allow types
> different from TABLE, namely lists of tables. I try to convince my data
> base colleagues that GROUP BY can nicely be handled in relational algebra
> by allowing sets of sets and that this is a fine combinatorial approach. I
> [snip]

I agree with Henning that HAVING is a 'terrible hack', but then SQL altogether 
is a terrible hack. I would expect the Haskell approach to be based on the 
much sounder theoretical principles of Relational Algebra, and I applaud that 
Wadler+SPJ's 'Comprehensive Comprehensions' restricts itself to a subset of 
SQL that corresponds to Relational Algebra. In that context, GROUP BY is 
reasonably well-defined as a mapping from a table to a table. (The hack in SQL 
(Continue reading)

Henning Thielemann | 11 Dec 08:03

Re: Re: group-by (Was: Nested guards?)


On Tue, 11 Dec 2007, Anthony Clayden wrote:

> I agree with Henning that HAVING is a 'terrible hack', but then SQL
> altogether is a terrible hack.

Somehow, yes.

> As that paper points out, HAVING is unnecessary - it's just a filter on
> the result set of group-by.

Yep.

> It's crucial that in Relational Algebra everything is a table. (See Codd's 12
> rules). The result of GROUP BY we might want to pass to another GROUP BY, or
> JOIN to another table, etc -- or does Henning propose a hierarchy of sets of
> sets ...

Yes, why not? Works fine in Haskell. Ok, Haskell programs do not construct
different query processing strategies and compare them at run-time, so the
comparison between Haskell compilers and databases is not quite fair.

> of tables, presumably with a hierarchy of HAVINGHAVING's?

map (map (map (filter p)))   and so on :-)
Christian Maeder | 5 Dec 11:40
Favicon

Re: Nested guards?

Iavor Diatchki wrote:
> Hi,
> Lately I have been using pattern guards more than usual and I find
> that occasionally I need to nest them (i.e., I have alternatives with
> a common prefix).  This seems to happen when I need to do some
> preliminary checking, followed by some decision making.  Here is an
> example:
> 
> server text
>    | Just xs <- parse text
>    ,   | "field1" `elem` xs   = ... do one thing ...
>        | "field2" `elem` xs   = ... do something else ...
> 
> server  _ = ... invalid request ...

Not having used pattern guards so far, can't you write?

server text = case parse text of
  Just xs
    | "field1" `elem` xs  -> ... do one thing ...
    | "field2" `elem` xs  -> ... do something else ...
  _ -> ... invalid request ...

Christian
Simon Peyton-Jones | 5 Dec 16:44

RE: Nested guards?

Indeed this makes sense.  See Section 3 of
        http://research.microsoft.com/~simonpj/Papers/pat.htm

It's really the syntactic/notational problem that has put me off every doing something like this.  I just
couldn't come up with a compelling syntax.  (The syntax GHC uses has the great merit that it's identical to
that for list comprehensions.)

Simon

| -----Original Message-----
| From: haskell-bounces <at> haskell.org [mailto:haskell-bounces <at> haskell.org] On Behalf Of Iavor Diatchki
| Sent: 04 December 2007 19:42
| To: Haskell users
| Subject: [Haskell] Nested guards?
|
| Hi,
| Lately I have been using pattern guards more than usual and I find
| that occasionally I need to nest them (i.e., I have alternatives with
| a common prefix).  This seems to happen when I need to do some
| preliminary checking, followed by some decision making.  Here is an
| example:
|
| server text
|    | Just xs <- parse text
|    ,   | "field1" `elem` xs   = ... do one thing ...
|        | "field2" `elem` xs   = ... do something else ...
|
| server  _ = ... invalid request ...
|
| As far as I can see this should be a fairly simple change to the
(Continue reading)

Roel van Dijk | 6 Dec 10:00

Re: Nested guards?

Note that Clean also supports nested guards. See section 3.3 of the
Clean language report:

http://clean.cs.ru.nl/download/Clean20/doc/CleanRep2.0.pdf

Unfortunately the html version of the report appears to be broken.

The report gives an example of nested guards and explains the
semantics with "if then else" expressions.
Simon Peyton-Jones | 6 Dec 10:06

RE: Nested guards?

| Note that Clean also supports nested guards. See section 3.3 of the
| Clean language report:
|
| http://clean.cs.ru.nl/download/Clean20/doc/CleanRep2.0.pdf

Interesting, I didn't know that.

But (a) Clean guards don't bind, and pattern guards that bind was where this thread started.   And (b) the
Clean manual says: "To ensure that at least one of the alternatives of a nested guard will be successful, a
nested guarded alternative must always have a 'default case' as last alternative".  That's a pity.  The
main point about guards is that failure means "go on to the next equation", a semantics that they could have
chosen I guess.

Simon
Bas van Dijk | 6 Dec 14:08
Gravatar

Re: Nested guards?

On Dec 6, 2007 9:06 AM, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:
> b) the Clean manual says: "To ensure that at least one of the alternatives of a nested guard will be
successful, a nested guarded alternative > must always have a 'default case' as last alternative". 
That's a pity.  The main point about guards is that failure means "go on to the next
> equation", a semantics that they could have chosen I guess.

I brought this up some time ago on haskell-prime (
http://thread.gmane.org/gmane.comp.lang.haskell.prime/1561 ). One of
the Clean guys mentioned that "the compiler can handle nested-guards
with fall-throughs just fine" and that "The reason that a nested guard
must have a default case is syntactical, otherwise there could be the
dangling-else ambiguity".

Bas

Gmane