Re: writing / status teams - call for volunteers
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
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
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
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
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
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
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
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
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
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