Language semantics

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Language semantics

Andrew Coppin
I have a tricky little question...

Suppose I write a function like this:

  foo pattern1
    | gard1 = ...
    | gard2 = ...
  foo pattern2
    | gard3 = ...
    | gard4 = ...

According to one tutorial I read, if pattern1 matches, pattern2 will
never be tried, even if both guard1 and guard2 fail.

And according to another tutorial I read, if pattern1 matches but all
guards fail, pattern2 *will* be tried.

Can somebody comfirm which one is actually correct?

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Stefan O'Rear
On Wed, Jun 27, 2007 at 09:46:41PM +0100, Andrew Coppin wrote:

> I have a tricky little question...
>
> Suppose I write a function like this:
>
>  foo pattern1
>    | gard1 = ...
>    | gard2 = ...
>  foo pattern2
>    | gard3 = ...
>    | gard4 = ...
>
> According to one tutorial I read, if pattern1 matches, pattern2 will
> never be tried, even if both guard1 and guard2 fail.
>
> And according to another tutorial I read, if pattern1 matches but all
> guards fail, pattern2 *will* be tried.
>
> Can somebody comfirm which one is actually correct?

According to http://haskell.org/onlinereport/exps.html#sect3.17.2

Top level patterns in case expressions and the set of top level patterns
in function or pattern bindings may have zero or more associated guards.
A guard is a boolean expression that is evaluated only after   all of
the arguments have been successfully matched, and it must be true for
the overall pattern match to succeed. The environment of the guard is
the same as the right-hand-side of the case-expression
alternative, function definition, or pattern binding to which it is
attached.

So, if guard1 and guard2 both fail, then pattern1 doesn't match (and
pattern matching continues).  As such, your "corner case" cannot
actually exist.

Stefan
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Jonathan Cast
In reply to this post by Andrew Coppin
On Wednesday 27 June 2007, Andrew Coppin wrote:

> I have a tricky little question...
>
> Suppose I write a function like this:
>
>   foo pattern1
>
>     | gard1 = ...
>     | gard2 = ...
>
>   foo pattern2
>
>     | gard3 = ...
>     | gard4 = ...
>
> According to one tutorial I read, if pattern1 matches, pattern2 will
> never be tried, even if both guard1 and guard2 fail.
>
> And according to another tutorial I read, if pattern1 matches but all
> guards fail, pattern2 *will* be tried.
>
> Can somebody comfirm which one is actually correct?

You could just try it, you know . . .

Anyway, the second tutorial is correct: if all guards on pattern1 fail,
pattern2 will be tried next.  See Section 3.17.3 in the Haskell Report [1].

Btw., which was the first tutorial?

Sincerely,
Jonathan Cast
http://sourceforge.net/projects/fid-core
http://sourceforge.net/projects/fid-emacs

[1] http://haskell.org/onlinereport/exps.html#case-semantics
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Andrew Coppin
In reply to this post by Stefan O'Rear
Stefan O'Rear wrote:

> On Wed, Jun 27, 2007 at 09:46:41PM +0100, Andrew Coppin wrote:
>  
>> I have a tricky little question...
>>
>> Suppose I write a function like this:
>>
>>  foo pattern1
>>    | gard1 = ...
>>    | gard2 = ...
>>  foo pattern2
>>    | gard3 = ...
>>    | gard4 = ...
>>
>> According to one tutorial I read, if pattern1 matches, pattern2 will
>> never be tried, even if both guard1 and guard2 fail.
>>
>> And according to another tutorial I read, if pattern1 matches but all
>> guards fail, pattern2 *will* be tried.
>>
>> Can somebody comfirm which one is actually correct?
>>    
>
> According to http://haskell.org/onlinereport/exps.html#sect3.17.2
>
> Top level patterns in case expressions and the set of top level patterns
> in function or pattern bindings may have zero or more associated guards.
> A guard is a boolean expression that is evaluated only after   all of
> the arguments have been successfully matched, and it must be true for
> the overall pattern match to succeed. The environment of the guard is
> the same as the right-hand-side of the case-expression
> alternative, function definition, or pattern binding to which it is
> attached.
>
> So, if guard1 and guard2 both fail, then pattern1 doesn't match (and
> pattern matching continues).  As such, your "corner case" cannot
> actually exist.
>  

Wow, wait a sec - case expressions are allowed to have guards too??

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Stefan O'Rear
On Wed, Jun 27, 2007 at 10:28:05PM +0100, Andrew Coppin wrote:

> Stefan O'Rear wrote:
> >On Wed, Jun 27, 2007 at 09:46:41PM +0100, Andrew Coppin wrote:
> >  
> >>I have a tricky little question...
> >>
> >>Suppose I write a function like this:
> >>
> >> foo pattern1
> >>   | gard1 = ...
> >>   | gard2 = ...
> >> foo pattern2
> >>   | gard3 = ...
> >>   | gard4 = ...
> >>
> >>According to one tutorial I read, if pattern1 matches, pattern2 will
> >>never be tried, even if both guard1 and guard2 fail.
> >>
> >>And according to another tutorial I read, if pattern1 matches but all
> >>guards fail, pattern2 *will* be tried.
> >>
> >>Can somebody comfirm which one is actually correct?
> >>    
> >
> >According to http://haskell.org/onlinereport/exps.html#sect3.17.2
> >
> >Top level patterns in case expressions and the set of top level patterns
> >in function or pattern bindings may have zero or more associated guards.
> >A guard is a boolean expression that is evaluated only after   all of
> >the arguments have been successfully matched, and it must be true for
> >the overall pattern match to succeed. The environment of the guard is
> >the same as the right-hand-side of the case-expression
> >alternative, function definition, or pattern binding to which it is
> >attached.
> >
> >So, if guard1 and guard2 both fail, then pattern1 doesn't match (and
> >pattern matching continues).  As such, your "corner case" cannot
> >actually exist.
> >  
>
> Wow, wait a sec - case expressions are allowed to have guards too??

stefan@stefans:~$ ghci
Loading package base ... linking ... done.
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |    GHC Interactive, version 6.7.20070612, for Haskell 98.
/ /_\\/ __  / /___| |    http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|    Type :? for help.

Prelude> case () of { () | True -> "x" }
"x"
Prelude>

Stefan
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Jonathan Cast
In reply to this post by Andrew Coppin
On Wednesday 27 June 2007, Andrew Coppin wrote:

> Stefan O'Rear wrote:
> > On Wed, Jun 27, 2007 at 09:46:41PM +0100, Andrew Coppin wrote:
> >> I have a tricky little question...
> >>
> >> Suppose I write a function like this:
> >>
> >>  foo pattern1
> >>
> >>    | gard1 = ...
> >>    | gard2 = ...
> >>
> >>  foo pattern2
> >>
> >>    | gard3 = ...
> >>    | gard4 = ...
> >>
> >> According to one tutorial I read, if pattern1 matches, pattern2 will
> >> never be tried, even if both guard1 and guard2 fail.
> >>
> >> And according to another tutorial I read, if pattern1 matches but all
> >> guards fail, pattern2 *will* be tried.
> >>
> >> Can somebody comfirm which one is actually correct?
> >
> > According to http://haskell.org/onlinereport/exps.html#sect3.17.2
> >
> > Top level patterns in case expressions and the set of top level patterns
> > in function or pattern bindings may have zero or more associated guards.
> > A guard is a boolean expression that is evaluated only after   all of
> > the arguments have been successfully matched, and it must be true for
> > the overall pattern match to succeed. The environment of the guard is
> > the same as the right-hand-side of the case-expression
> > alternative, function definition, or pattern binding to which it is
> > attached.
> >
> > So, if guard1 and guard2 both fail, then pattern1 doesn't match (and
> > pattern matching continues).  As such, your "corner case" cannot
> > actually exist.
>
> Wow, wait a sec - case expressions are allowed to have guards too??

Yes.  I guess I assumed you knew that, sorry.

The only syntactic (or semantic) difference between function equations and
case expressions (aside from the fact that case expressions require you to
tuple up the values you're pattern-matching on) is the fact that case
expressions use -> where function bindings use =.  Other than that, the two
forms are exactly equivalent.

Sincerely,
Jonathan Cast
http://sourceforge.net/projects/fid-core
http://sourceforge.net/projects/fid-emacs
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Dan Mead
Andrew: Try using catchalls in your guards


pattern1
| guard1 =
| guard2 =
| otherwise =

This makes it much easier to use pattern guards.
"otherwise" is a reserved word used for this stuff in ghc.


-Dan


On 6/27/07, Jon Cast <[hidden email]> wrote:
On Wednesday 27 June 2007, Andrew Coppin wrote:

> Stefan O'Rear wrote:
> > On Wed, Jun 27, 2007 at 09:46:41PM +0100, Andrew Coppin wrote:
> >> I have a tricky little question...
> >>
> >> Suppose I write a function like this:
> >>
> >>  foo pattern1
> >>
> >>    | gard1 = ...
> >>    | gard2 = ...
> >>
> >>  foo pattern2
> >>
> >>    | gard3 = ...
> >>    | gard4 = ...
> >>
> >> According to one tutorial I read, if pattern1 matches, pattern2 will
> >> never be tried, even if both guard1 and guard2 fail.
> >>
> >> And according to another tutorial I read, if pattern1 matches but all
> >> guards fail, pattern2 *will* be tried.
> >>
> >> Can somebody comfirm which one is actually correct?
> >
> > According to http://haskell.org/onlinereport/exps.html#sect3.17.2
> >
> > Top level patterns in case expressions and the set of top level patterns
> > in function or pattern bindings may have zero or more associated guards.
> > A guard is a boolean expression that is evaluated only after   all of
> > the arguments have been successfully matched, and it must be true for
> > the overall pattern match to succeed. The environment of the guard is
> > the same as the right-hand-side of the case-expression
> > alternative, function definition, or pattern binding to which it is
> > attached.
> >
> > So, if guard1 and guard2 both fail, then pattern1 doesn't match (and
> > pattern matching continues).  As such, your "corner case" cannot
> > actually exist.
>
> Wow, wait a sec - case expressions are allowed to have guards too??

Yes.  I guess I assumed you knew that, sorry.

The only syntactic (or semantic) difference between function equations and
case expressions (aside from the fact that case expressions require you to
tuple up the values you're pattern-matching on) is the fact that case
expressions use -> where function bindings use =.  Other than that, the two
forms are exactly equivalent.

Sincerely,
Jonathan Cast
http://sourceforge.net/projects/fid-core
http://sourceforge.net/projects/fid-emacs
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Jonathan Cast
On Wednesday 27 June 2007, you wrote:

> Andrew: Try using catchalls in your guards
>
>
> pattern1
>
> | guard1 =
> | guard2 =
> | otherwise =
>
> This makes it much easier to use pattern guards.
> "otherwise" is a reserved word used for this stuff in ghc.

Since we're quoting the standard and all, my inner pedant can't help but
quibble: otherwise is not a keyword, it's a synonym for True defined in the
Standard Prelude (and, in particular, goes away if you say import Prelude
()):

$ cat > Foo.hs
import Prelude

main = print otherwise
$ ghc Foo.hs -o foo
$ ./foo
True
$ cat > Foo.hs
import Prelude (print)

main = print otherwise
$ ghc Foo.hs -o foo

Foo.hs:3:13: Not in scope: `otherwise'


Sincerely,
Jonathan Cast
Computer Programmer
http://sourceforge.net/projects/fid-core
http://sourceforge.net/projects/fid-emacs
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Language semantics

Bulat Ziganshin-2
In reply to this post by Andrew Coppin
Hello Andrew,

Thursday, June 28, 2007, 1:28:05 AM, you wrote:

> Wow, wait a sec - case expressions are allowed to have guards too??

btw, it's used to implement boolean switches:

case () of
 _ | a>0       -> 1
   | a<0       -> -1
   | otherwise -> 0

--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Andrew Coppin
In reply to this post by Jonathan Cast
Jon Cast wrote:
> Anyway, the second tutorial is correct: if all guards on pattern1 fail,
> pattern2 will be tried next.  See Section 3.17.3 in the Haskell Report [1].
>
> Btw., which was the first tutorial?
>  

Unfortunately, I cannot remember.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Andrew Coppin
In reply to this post by Jonathan Cast
Jon Cast wrote:

> On Wednesday 27 June 2007, Andrew Coppin wrote:
>  
>> Wow, wait a sec - case expressions are allowed to have guards too??
>>    
>
> Yes.  I guess I assumed you knew that, sorry.
>
> The only syntactic (or semantic) difference between function equations and
> case expressions (aside from the fact that case expressions require you to
> tuple up the values you're pattern-matching on) is the fact that case
> expressions use -> where function bindings use =.  Other than that, the two
> forms are exactly equivalent.
>  

I knew they were nearly identical. I didn't realise that they *were*
identical!

Hmm, I tried to find out 1 thing and actually found out 2 things! :-D

I wonder what the layout for that is... something like this?

  case foo of
    patter1
      | guard1 -> ...
      | guard2 -> ...
    pattern2
      | guard3 -> ...
      | guard4 -> ...

Well, I'll have to go try it...

I always thought of guards as being a nice shorthand for if-expressions
- but if they can affect the order of pattern matching, clearly they are
more drastically different than I realised. (Generally, I never ever use
'em!)

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Andrew Coppin
In reply to this post by Dan Mead
Dan Mead wrote:

> Andrew: Try using catchalls in your guards
>
>
> pattern1
> | guard1 =
> | guard2 =
> | otherwise =
>
> This makes it much easier to use pattern guards.
> "otherwise" is a reserved word used for this stuff in ghc.

Yeah, it's good practice to include an explicit otherwise clause - but
in this specific instance, I'm trying to do tricky stuff where one rule
falls through to another if some condition doesn't hold - but that
condition is only expressible as a function.

Well, let me show you the code - somebody will probably recognise this
stuff...

convert1 :: Expression -> Expression
convert1 S = S
convert1 K = K
convert1 I = I
convert1 (Var v) = Var v
convert1 (x :@: y) = (convert1 x) :@: (convert1 y)
convert1 (Lam n e)
  | n `not_in` e = K :@: (convert1 e)
convert1 (Lam n (Var v))
  | n == v = I
  | otherwise = K :@: (convert1 (Var v))
convert1 (Lam n (x :@: y))
  | y `is_var` n && n `not_in` x = convert1 x
  | otherwise                    = S :@: (convert1 (Lam n x)) :@:
(convert1 (Lam n y))
convert1 (Lam n (Lam m e))
  | n `not_in` e = K :@: (convert1 (Lam m e))
  | otherwise    = convert1 (Lam n (convert1 (Lam m e)))

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Stefan O'Rear
On Fri, Jun 29, 2007 at 07:18:00PM +0100, Andrew Coppin wrote:

> Dan Mead wrote:
> >Andrew: Try using catchalls in your guards
> >
> >
> >pattern1
> >| guard1 =
> >| guard2 =
> >| otherwise =
> >
> >This makes it much easier to use pattern guards.
> >"otherwise" is a reserved word used for this stuff in ghc.
>
> Yeah, it's good practice to include an explicit otherwise clause - but
> in this specific instance, I'm trying to do tricky stuff where one rule
> falls through to another if some condition doesn't hold - but that
> condition is only expressible as a function.
>
> Well, let me show you the code - somebody will probably recognise this
> stuff...
>
> convert1 :: Expression -> Expression
> convert1 S = S
> convert1 K = K
> convert1 I = I
> convert1 (Var v) = Var v
> convert1 (x :@: y) = (convert1 x) :@: (convert1 y)
> convert1 (Lam n e)
>  | n `not_in` e = K :@: (convert1 e)
> convert1 (Lam n (Var v))
>  | n == v = I
>  | otherwise = K :@: (convert1 (Var v))
> convert1 (Lam n (x :@: y))
>  | y `is_var` n && n `not_in` x = convert1 x
>  | otherwise                    = S :@: (convert1 (Lam n x)) :@:
> (convert1 (Lam n y))
> convert1 (Lam n (Lam m e))
>  | n `not_in` e = K :@: (convert1 (Lam m e))
>  | otherwise    = convert1 (Lam n (convert1 (Lam m e)))

This is *much* easier expressed as a bottom-up traversal.

compile = transform optimize . transform eliminate

eliminate (Lam v e) = transform (abstract v) e
eliminate x = x

abstract v (Var v') | v == v'   = I
abstract v (a :@ b) = S :@ a :@ b
abstract v x = x

optimize (S :@ (K :@ x) :@ (K :@ y)) = K :@ (x :@ y)
optimize (S :@ (K :@ x) :@ I) = x
optimize x = x

(Here using Uniplate, mostly because it is the freshest in my mind of
all of them).

Stefan
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Andrew Coppin
Stefan O'Rear wrote:

> On Fri, Jun 29, 2007 at 07:18:00PM +0100, Andrew Coppin wrote:
>  
>> Well, let me show you the code - somebody will probably recognise this
>> stuff...
>>
>> convert1 :: Expression -> Expression
>> convert1 S = S
>> convert1 K = K
>> convert1 I = I
>> convert1 (Var v) = Var v
>> convert1 (x :@: y) = (convert1 x) :@: (convert1 y)
>> convert1 (Lam n e)
>>  | n `not_in` e = K :@: (convert1 e)
>> convert1 (Lam n (Var v))
>>  | n == v = I
>>  | otherwise = K :@: (convert1 (Var v))
>> convert1 (Lam n (x :@: y))
>>  | y `is_var` n && n `not_in` x = convert1 x
>>  | otherwise                    = S :@: (convert1 (Lam n x)) :@:
>> (convert1 (Lam n y))
>> convert1 (Lam n (Lam m e))
>>  | n `not_in` e = K :@: (convert1 (Lam m e))
>>  | otherwise    = convert1 (Lam n (convert1 (Lam m e)))
>>    
>
> This is *much* easier expressed as a bottom-up traversal.
>
> compile = transform optimize . transform eliminate
>
> eliminate (Lam v e) = transform (abstract v) e
> eliminate x = x
>
> abstract v (Var v') | v == v'   = I
> abstract v (a :@ b) = S :@ a :@ b
> abstract v x = x
>
> optimize (S :@ (K :@ x) :@ (K :@ y)) = K :@ (x :@ y)
> optimize (S :@ (K :@ x) :@ I) = x
> optimize x = x
>  

Woah... Let me sit down and grok that for an hour or two. o_o

(Hey, maybe this is why I don't develop cutting edge software for a living?)

> (Here using Uniplate, mostly because it is the freshest in my mind of
> all of them).
>  

What's Uniplate?

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Mark T.B. Carroll-2
Andrew Coppin <[hidden email]> writes:
(snip)
> Woah... Let me sit down and grok that for an hour or two. o_o

The Haskell learning curve - including the wonderful range of useful
generic stuff you can do with it - extends way higher than for many
other languages, I think, though you can write lots of useful code when
you're just partway up. I'm still learning things, and knowing I have
much more yet to learn, and normally I can learn most of my way around a
new programming language within a couple of weeks.

(snip)
> What's Uniplate?

http://www-users.cs.york.ac.uk/~ndm/uniplate/ may help to answer that
question. I haven't even finished understanding SYB, yet, though; I'm
still mystified by how to use Data.Generics.Twins.gzipWithQ. So, I'm
not at a stage where I can usefully contrast Uniplate with the
Data.Generics stuff.

-- Mark

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

David House
In reply to this post by Andrew Coppin
Andrew Coppin writes:
 > I wonder what the layout for that is... something like this?
 >
 >   case foo of
 >     patter1
 >       | guard1 -> ...
 >       | guard2 -> ...
 >     pattern2
 >       | guard3 -> ...
 >       | guard4 -> ...

Something like that should work. If the patterns are more indented than the
'case', and the guards are more indented than the patterns, then the layout rule
should work fine. As always, once you get used to the way layout works,
everything is pretty intuitive.

 > Well, I'll have to go try it...

Always a nice solution to these kinds of problems!

 > I always thought of guards as being a nice shorthand for if-expressions
 > - but if they can affect the order of pattern matching, clearly they are
 > more drastically different than I realised. (Generally, I never ever use
 > 'em!)

A useful rule to remember with guards is that "once you cross the equals sign,
you can't go back". So if one of your patterns matches and a guard on that
pattern is true, that right-hand side will be evaluated and there is no way to
fall back to another guard or pattern.

--
-David House, [hidden email]
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Jonathan Cast
In reply to this post by Andrew Coppin
On Friday 29 June 2007, Andrew Coppin wrote:

> Jon Cast wrote:
> > On Wednesday 27 June 2007, Andrew Coppin wrote:
> >> Wow, wait a sec - case expressions are allowed to have guards too??
> >
> > Yes.  I guess I assumed you knew that, sorry.
> >
> > The only syntactic (or semantic) difference between function equations
> > and case expressions (aside from the fact that case expressions require
> > you to tuple up the values you're pattern-matching on) is the fact that
> > case expressions use -> where function bindings use =.  Other than that,
> > the two forms are exactly equivalent.
>
> I knew they were nearly identical. I didn't realise that they *were*
> identical!
>
> Hmm, I tried to find out 1 thing and actually found out 2 things! :-D
>
> I wonder what the layout for that is... something like this?
>
>   case foo of
>     patter1
>
>       | guard1 -> ...
>       | guard2 -> ...
>
>     pattern2
>
>       | guard3 -> ...
>       | guard4 -> ...

Just so.

Jonathan Cast
http://sourceforge.net/projects/fid-core
http://sourceforge.net/projects/fid-emacs
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Neil Mitchell
In reply to this post by Mark T.B. Carroll-2
Hi

> > What's Uniplate?
>
> http://www-users.cs.york.ac.uk/~ndm/uniplate/ may help to answer that
> question. I haven't even finished understanding SYB, yet, though; I'm
> still mystified by how to use Data.Generics.Twins.gzipWithQ. So, I'm
> not at a stage where I can usefully contrast Uniplate with the
> Data.Generics stuff.

Uniplate should be easier to understand than SYB. The draft paper on
that web page compares Uniplate to SYB (and Compos). It also has
plenty of examples of how to use Uniplate to do tasks. The manual on
that page has suggested exercises to check that you can understand and
extend Uniplate code.

Uniplate produces more concise code, has traversal operations that are
not present in the SYB library, runs faster and works in Hugs. SYB is
capable of many more generic operations than Uniplate, such as
gzipWithQ and much much more.

Thanks

Neil
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Andrew Coppin
In reply to this post by Stefan O'Rear
Stefan O'Rear wrote:

> This is *much* easier expressed as a bottom-up traversal.
>
> compile = transform optimize . transform eliminate
>
> eliminate (Lam v e) = transform (abstract v) e
> eliminate x = x
>
> abstract v (Var v') | v == v'   = I
> abstract v (a :@ b) = S :@ a :@ b
> abstract v x = x
>
> optimize (S :@ (K :@ x) :@ (K :@ y)) = K :@ (x :@ y)
> optimize (S :@ (K :@ x) :@ I) = x
> optimize x = x
>
> (Here using Uniplate, mostly because it is the freshest in my mind of
> all of them).
>  

Um... shouldn't that read

  abstract v (a :@ b) = S :@ (transform (abstract v) a) :@: (transform
(abstract v) b)

?

Or am I missing something?

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Language semantics

Stefan O'Rear
On Sun, Jul 01, 2007 at 05:06:10PM +0100, Andrew Coppin wrote:

> Stefan O'Rear wrote:
> >This is *much* easier expressed as a bottom-up traversal.
> >
> >compile = transform optimize . transform eliminate
> >
> >eliminate (Lam v e) = transform (abstract v) e
> >eliminate x = x
> >
> >abstract v (Var v') | v == v'   = I
> >abstract v (a :@ b) = S :@ a :@ b
> >abstract v x = x
> >
> >optimize (S :@ (K :@ x) :@ (K :@ y)) = K :@ (x :@ y)
> >optimize (S :@ (K :@ x) :@ I) = x
> >optimize x = x
> >
> >(Here using Uniplate, mostly because it is the freshest in my mind of
> >all of them).
> >  
>
> Um... shouldn't that read
>
>  abstract v (a :@ b) = S :@ (transform (abstract v) a) :@: (transform
> (abstract v) b)

No, because the whole point of transform is that it handles recursion
for you.  (However, there is a bug!  abstracting an unrecognized form
(that is, a primitive combinator) should add a K.)

Stefan
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
12