Re: writing / status teams - call for volunteers

2006-09-28 Thread Andres Loeh
 Would anyone else like to volunteer to write a section of the report for
 specific proposals below?
 
  In
  ==
  
  #74: add some kind of concurrency: SM, HN, IJ
  #35: add ForeignFunctionInterface: MC, SM
  #49: add multi parameter type classes: MS
  #60: add RankNTypes or Rank2Types: AL
  #57: add polymorphic components: AL
  #26: add ExistentialQuantification (existential components): AL, MS, SJT
  #24: add HierarchicalModules: BH, IJ
  #25: add EmptyDataDeclarations: BH, HN
  #23: fix common pitfall with the do-notation and if-then-else: SM, HN, 
  #42: fix comment syntax grammar: SM
  #56: add Pattern Guards: :(
  #78: Add infix type constructors: BH, AL
  Help w/ libraries (yay!): IJ, BH, SM, RP, DS

I would like to start writing a new section on the syntax of data type
declarations. All the proposals I've put my name on are somewhat related
to this area, most of all existential quantification and infix type
constructors.

Have we already discussed how we produce new text for the report? Is this
supposed to be all on the Wiki, or are we going to modify the TeX sources
of the Haskell-98 report? Is the plan to keep the general style and structure
of the Haskell-98 report, or are we going to rewrite and restructure the
whole report?

Cheers,
  Andres
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


Pattern guards

2006-09-28 Thread Yitzchak Gale

I would like to suggest a correction to ticket #56,
Pattern Guards.

It is easy to show that every expression written
using pattern guards can also be written in
Haskell 98 in a way that is essentially
equivalent in simplicity. (Proof below.)

In my opinion, the Haskell 98 version below is
more clear than the pattern guard version - it
makes the monad explicit. Even if you disagree,
I think it would be very difficult to argue that the
difference is important enough to justify the extreme
measure of adding new syntax to the language.

Therefore, the first two items under Pros are
false, and should be removed. The only remaining
Pro is that the extension is well-specified, which
has no value on its own.

The purpose of Haskell' is to remove warts from
Haskell, not add new ones. Pattern guards are
a serious wart - they further overload syntax that
is arguably already overused, as pointed out
in the referenced paper by Martin Erwig and
Simon Peyton Jones [EPJ].

I hope that there is still time to retract the evil decree
of definitely in Proposal Status for this ticket.

Regards,
Yitz

Proof: We first assume that the following declarations
are available, presumably from a library:


data Exit e a = Continue a | Exit {runExit :: e}
instance Monad (Exit e) where
  return = Continue
  Continue x = f = f x
  Exit e = _ = Exit e


(Note that this is essentially the same as the Monad
instance for Either defined in Control.Monad.Error,
except without the restriction that e be an instance
of Error.)


maybeExit :: Maybe e - Exit e ()
maybeExit = maybe (return ()) Exit


Now given any function binding using pattern guards:

funlhs
| qual11, qual12, ..., qual1n = exp1
| qual21, qual22, ..., qual2n = exp2
...

we translate the function binding into Haskell 98 as:

funlhs = runExit $ do
 maybeExit $ do {qual11'; qual12'; ...; qual1n'; return (exp1)}
 maybeExit $ do {qual21'; qual22'; ...; qual2n'; return (exp2)}
 ...

where

 qualij' - pat - return (e) if qualij is pat - e
 qualij' - guard (qualij) if qualij is a boolean expression
 qualij' - qualij if qualij is a let expression

For a conventional guard:

| p = exp

we can simplify the translation to:

 when (p) $ Exit (exp)

Simplifications are also possible for other special cases.

This concludes the proof. Here are some examples, taken
from [EPJ]:


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


translates to:


clunky env var1 var2 = runExit $ do
  maybeExit $ do
val1 - lookup env var1
val2 - lookup env var2
return (val1 + val2)
 ...other equations for clunky



filtSeq :: (a-Bool) - Seq a - Seq a
filtSeq p xs
 | Just (y,ys) - lview xs, p y = lcons y (filtSeq p ys)
 | Just (y,ys) - lview xs  = filtSeq p ys
 | otherwise= nil


translates to:


filtSeq :: (a-Bool) - Seq a - Seq a
filtSeq p xs = runExit $ do
  maybeExit $ do
(y,ys) - lview xs
guard $ p y
return $ lcons y $ filtSeq p ys
  maybeExit $ do
(y,ys) - lview xs
return $ filtSeq p ys
  Exit nil


Note that in this case, the Maybe monad alone is
sufficient. That eliminates both the double lookup and
the double pattern match, as discussed in [EPJ]:


filtSeq :: (a-Bool) - Seq a - Seq a
filtSeq p xs = fromMaybe nil $ do
  (y,ys) - lview xs
  return $ if (p y)
then lcons y (filtSeq p ys)
else filtSeq p ys

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


Re: Pattern guards

2006-09-28 Thread Ross Paterson
On Thu, Sep 28, 2006 at 04:40:30PM +0300, Yitzchak Gale wrote:
 Now given any function binding using pattern guards:
 
 funlhs
 | qual11, qual12, ..., qual1n = exp1
 | qual21, qual22, ..., qual2n = exp2
 ...
 
 we translate the function binding into Haskell 98 as:
 
 funlhs = runExit $ do
  maybeExit $ do {qual11'; qual12'; ...; qual1n'; return (exp1)}
  maybeExit $ do {qual21'; qual22'; ...; qual2n'; return (exp2)}
  ...

Or even

funlhs = fromJust $
 do {qual11'; qual12'; ...; qual1n'; return (exp1)}
 `mplus`
 do {qual21'; qual22'; ...; qual2n'; return (exp2)}

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


Re: Pattern guards

2006-09-28 Thread Conor McBride

Hi

Yitzchak Gale wrote:

I would like to suggest a correction to ticket #56,
Pattern Guards.

It is easy to show that every expression written
using pattern guards can also be written in
Haskell 98 in a way that is essentially
equivalent in simplicity. (Proof below.)


Whether or not your conclusion is correct, your candidate proof is 
incomplete.



funlhs
| qual11, qual12, ..., qual1n = exp1
| qual21, qual22, ..., qual2n = exp2
...

we translate the function binding into Haskell 98 as:

funlhs = runExit $ do
 maybeExit $ do {qual11'; qual12'; ...; qual1n'; return (exp1)}
 maybeExit $ do {qual21'; qual22'; ...; qual2n'; return (exp2)}
 ...


This translation does not appear to address programs with multiple 
left-hand sides, exploiting fall-through from match (hence guard) 
failure, eg


 varVal :: String - [(String, String)] - String
 varVal x locals | Just y - lookup x locals = y
 varVal X xys = 42
 varVal _ _ = error var not found

Haskell 98 provides no means to inspect the value of an intermediate 
computation (something other than an argument or component thereof) 
without committing to one right-hand side. I think that's rather 
unfortunate, because it loses the visual tabulation of the possibilities 
and priorities.


I'm not a big fan of pattern guards, though, because they only give you 
one shot at matching the intermediate result. Some means to do 'case e' 
on the left would be nice. Maybe


 gcd x y | compare x y -
   LT = gcd x (y - x)
   GT = gcd (x - y) y
 gcd x _ = x

or some such. I wish I could think of a better example without too much 
context, but such a thing escapes me for the moment. In general, I think 
it's good to collocate on the left as much as possible of a function's 
scrutineering. Stringing out ifs and cases makes it harder to see what's 
going on.


All the best

Conor

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


Re: Pattern guards

2006-09-28 Thread Iavor Diatchki

Hello,
I think that pattern guards are a nice generalization of ordinary
guards and they should be added to the language.  Of course, as you
point out, we can encode them using the Maybe monad, but the same is
true for nested patterns, and I don't think that they should be
removed from Haskell.  I think that the benefit of adding pattern
guards is similar to that of using nested patterns: it provides a
concise notation that is easy to explain and understand without having
to first learn about monads (even though there is a monad that is
hidden behind the scenes).  This, combined with the fact that pattern
guards are quite easy to implement, I think advocates in their favor.
-Iavor



On 9/28/06, Yitzchak Gale [EMAIL PROTECTED] wrote:

I would like to suggest a correction to ticket #56,
Pattern Guards.

It is easy to show that every expression written
using pattern guards can also be written in
Haskell 98 in a way that is essentially
equivalent in simplicity. (Proof below.)

In my opinion, the Haskell 98 version below is
more clear than the pattern guard version - it
makes the monad explicit. Even if you disagree,
I think it would be very difficult to argue that the
difference is important enough to justify the extreme
measure of adding new syntax to the language.

Therefore, the first two items under Pros are
false, and should be removed. The only remaining
Pro is that the extension is well-specified, which
has no value on its own.

The purpose of Haskell' is to remove warts from
Haskell, not add new ones. Pattern guards are
a serious wart - they further overload syntax that
is arguably already overused, as pointed out
in the referenced paper by Martin Erwig and
Simon Peyton Jones [EPJ].

I hope that there is still time to retract the evil decree
of definitely in Proposal Status for this ticket.

Regards,
Yitz

Proof: We first assume that the following declarations
are available, presumably from a library:

 data Exit e a = Continue a | Exit {runExit :: e}
 instance Monad (Exit e) where
   return = Continue
   Continue x = f = f x
   Exit e = _ = Exit e

(Note that this is essentially the same as the Monad
instance for Either defined in Control.Monad.Error,
except without the restriction that e be an instance
of Error.)

 maybeExit :: Maybe e - Exit e ()
 maybeExit = maybe (return ()) Exit

Now given any function binding using pattern guards:

funlhs
 | qual11, qual12, ..., qual1n = exp1
 | qual21, qual22, ..., qual2n = exp2
 ...

we translate the function binding into Haskell 98 as:

funlhs = runExit $ do
  maybeExit $ do {qual11'; qual12'; ...; qual1n'; return (exp1)}
  maybeExit $ do {qual21'; qual22'; ...; qual2n'; return (exp2)}
  ...

where

  qualij' - pat - return (e) if qualij is pat - e
  qualij' - guard (qualij) if qualij is a boolean expression
  qualij' - qualij if qualij is a let expression

For a conventional guard:

 | p = exp

we can simplify the translation to:

  when (p) $ Exit (exp)

Simplifications are also possible for other special cases.

This concludes the proof. Here are some examples, taken
from [EPJ]:

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

translates to:

 clunky env var1 var2 = runExit $ do
   maybeExit $ do
 val1 - lookup env var1
 val2 - lookup env var2
 return (val1 + val2)
  ...other equations for clunky

 filtSeq :: (a-Bool) - Seq a - Seq a
 filtSeq p xs
  | Just (y,ys) - lview xs, p y = lcons y (filtSeq p ys)
  | Just (y,ys) - lview xs  = filtSeq p ys
  | otherwise= nil

translates to:

 filtSeq :: (a-Bool) - Seq a - Seq a
 filtSeq p xs = runExit $ do
   maybeExit $ do
 (y,ys) - lview xs
 guard $ p y
 return $ lcons y $ filtSeq p ys
   maybeExit $ do
 (y,ys) - lview xs
 return $ filtSeq p ys
   Exit nil

Note that in this case, the Maybe monad alone is
sufficient. That eliminates both the double lookup and
the double pattern match, as discussed in [EPJ]:

 filtSeq :: (a-Bool) - Seq a - Seq a
 filtSeq p xs = fromMaybe nil $ do
   (y,ys) - lview xs
   return $ if (p y)
 then lcons y (filtSeq p ys)
 else filtSeq p ys
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime


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


Re: Haskell' Status Report

2006-09-28 Thread Stefan Monnier
 Ravi Nanavati has very helpfully put together a status report for the
 Haskell Prime process.  Please see this link, or read the pasted text
 below:

 http://hackage.haskell.org/trac/haskell-prime/wiki/Status'

This wiki is really neat.  I do wish there was some information in it about
the implementation status of those proposals, so we can tell if those things
are already implemented in most Haskell compilers/interpreters (and for how
long).


Stefan

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


Re: Haskell' Status Report

2006-09-28 Thread Ravi Nanavati
The rule-of-thumb (only violated in a few instances) has been that each 
proposal needs to be implemented in some Haskell compiler to be eligible 
for consideration as part of Haskell'.


The pages that describe each proposal in detail (including Pros and 
Cons) also generally include comments about what the implementation 
status of the proposal is in various compilers. You can find them via 
the link in the Description column of the status tables or via their 
associated ticket page. If there some specific proposals where more you 
feel implementation detail is needed, please feel free to let us know.


 - Ravi

Stefan Monnier wrote:

Ravi Nanavati has very helpfully put together a status report for the
Haskell Prime process.  Please see this link, or read the pasted text
below:



http://hackage.haskell.org/trac/haskell-prime/wiki/Status'


This wiki is really neat.  I do wish there was some information in it about
the implementation status of those proposals, so we can tell if those things
are already implemented in most Haskell compilers/interpreters (and for how
long).


Stefan

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


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


Re[2]: Pattern guards

2006-09-28 Thread Bulat Ziganshin
Hello Conor,

Thursday, September 28, 2006, 10:30:46 PM, you wrote:

   gcd x y | compare x y -
 LT = gcd x (y - x)
 GT = gcd (x - y) y
   gcd x _ = x

 or some such. I wish I could think of a better example without too much
 context, but such a thing escapes me for the moment. In general, I think
 it's good to collocate on the left as much as possible of a function's
 scrutineering. Stringing out ifs and cases makes it harder to see what's
 going on.

i like this. for me, left part of function definition is a half of
logical programming language, it only omits two-direction
pattern-matching mechanism


-- 
Best regards,
 Bulatmailto:[EMAIL PROTECTED]

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


Re: Re[2]: Pattern guards

2006-09-28 Thread Iavor Diatchki

Hello,
This particular example we can do with pattern guards
(although it seems that a simple 'case' is more appropriate for this example)

On 9/28/06, Bulat Ziganshin [EMAIL PROTECTED] wrote:

Hello Conor,

Thursday, September 28, 2006, 10:30:46 PM, you wrote:

   gcd x y | compare x y -
 LT = gcd x (y - x)
 GT = gcd (x - y) y
   gcd x _ = x


mygcd x y
 | LT - z   = mygcd x (y-x)
 | GT - z   = mygcd (x-y) y
 where
 z = compare x y

mygcd x _ = x

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


Re: Pattern guards

2006-09-28 Thread David Roundy
On Fri, Sep 29, 2006 at 02:59:49AM +0300, Yitzchak Gale wrote:
 Iavor Diatchki wrote:
 I think that the benefit of adding pattern guards is... it provides
 a concise notation
 
 Not significantly more concise than existing notation.

That's just not true.  If all your pattern guards happen to involve
the Maybe monad, then perhaps you can rewrite the pattern guard code
almost as concisely using monadic notation, but it does mean that the
moment you choose to do that you have to completely give up on using
Haskell's existing pattern matching to define your function, unless
you happen to be defining a particularly simple function.

How do you nearly as concisely write a function such as this in
Haskell 98?

 foo (Left bar) = a
 foo (Right x) | (b,foo) - break (==' ') x = b  ++ b
 foo (Left x) | (foo,c) - break (==' ') x = c  ++ c
 foo (Right x) | [Hello,n,how,are,you,d@(_:_)] - words x,
  last d == '?'
  = n ++  is not here right now, but  ++ n ++  is  ++
init d ++  fine.
 foo (Left x) | length x == 13 = Unlucky!
 foo (Right x) = x
 foo (Left x) = x

It's a contrived example, but the usefulness of pattern guards is only
greater on more realistic, more complicated functions.
-- 
David Roundy
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-prime