
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against. Firstly: because in its more general forms the notation is confusing. Try this example: [(i,j,k) | i<-[1..3], j<-[1..3] | k <- [1..9]] In general it's hard to predict how the elements from each set of generators and filters will match up. Secondly: because the notation lacks expressive power. When I use zip in a comprehension, it's often in a definition like this one: positions x xs = [i | (i,x') <- zip [0..] xs, x==x'] I'm zipping the two lists together *so that I can relate the two* in a subsequent filter. The parallel comprehension notation cannot express this. (You can certainly write wrong_positions x xs = [i | i <- [0..] | x' <- xs, x==x'] but it does the wrong thing). Thirdly: because even in situations where it can be applied, the gain is small. Using zip explicitly is almost equally concise, and (thanks to being explicit) more readable and understandable. My opinion may be coloured by the fact that I never use the things. However, I think it's a mistake to add rarely used features with a small payoff to the language. It just makes the language larger, harder to learn, and harder to read for all but the expert, without much corresponding benefit. John

On Sat, 2006-02-04 at 15:11 +0100, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
Can I second this? The only time I ever used a parallel list comprehension was by accident. I accidentally used '|' rather than ',' in a list comprehension and ended up with a bug that was quite hard to track down. Now one could argue that I could make a similar mistake with pretty much any language feature, but it's precisely because it's a rarely used language feature that it makes this problem worse because you're not looking for that kind of problem. Duncan

On 2006-02-04 at 15:11+0100 John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
I also agree.
Firstly: because in its more general forms the notation is confusing. Try this example:
[(i,j,k) | i<-[1..3], j<-[1..3] | k <- [1..9]]
In general it's hard to predict how the elements from each set of generators and filters will match up.
and I always think it's going to do something cooler -- a "fair" list product (like "," only working on infinite lists), not a zip, and then I'm disappointed when I remember it doesn't. So it just uses up some syntax (ie adds possible errors) without adding anything really useful. There ought to be a list_product somewhere (I mean [1..] `list_product` [4..] == [(1,4),(2,4),(1,5),(3,4),(2,5),(1,6),...]). Is there? Jón -- Jón Fairbairn Jon.Fairbairn at cl.cam.ac.uk

On Feb 4, 2006, at 1:31 PM, Jon Fairbairn wrote:
... There ought to be a list_product somewhere (I mean [1..] `list_product` [4..] == [(1,4),(2,4),(1,5),(3,4),(2,5),(1,6),...]). Is there?
Not that I know of, but here's one which handles finite lists correctly; it'd be a nice addition to Data.List: dzip :: [a] -> [b] -> [(a,b)] dzip = dzipWith (,) dzipWith :: (a -> b -> c) -> [a] -> [b] -> [c] dzipWith f [] ys = [] dzipWith f as [] = [] dzipWith f as (y:ys) = dzipK ys [y] where dzipK (b:bs) rbs = zipWith f as rbs ++ dzipK bs (b : rbs) dzipK [] rbs = dzipT as where dzipT ys@(_:yt) = zipWith f ys rbs ++ dzipT yt dzipT [] = [] -Jan-Willem Maessen
Jón
-- Jón Fairbairn Jon.Fairbairn at cl.cam.ac.uk
_______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://haskell.org/mailman/listinfo/haskell-prime

cartesian xs ys = map (\[x,y] -> (x,y)) $ sequence [xs,ys]
On 04/02/06, Jan-Willem Maessen
On Feb 4, 2006, at 1:31 PM, Jon Fairbairn wrote:
... There ought to be a list_product somewhere (I mean [1..] `list_product` [4..] == [(1,4),(2,4),(1,5),(3,4),(2,5),(1,6),...]). Is there?
Not that I know of, but here's one which handles finite lists correctly; it'd be a nice addition to Data.List:
dzip :: [a] -> [b] -> [(a,b)] dzip = dzipWith (,)
dzipWith :: (a -> b -> c) -> [a] -> [b] -> [c] dzipWith f [] ys = [] dzipWith f as [] = [] dzipWith f as (y:ys) = dzipK ys [y] where dzipK (b:bs) rbs = zipWith f as rbs ++ dzipK bs (b : rbs) dzipK [] rbs = dzipT as where dzipT ys@(_:yt) = zipWith f ys rbs ++ dzipT yt dzipT [] = []
-Jan-Willem Maessen
Jón
-- Jón Fairbairn Jon.Fairbairn at cl.cam.ac.uk
_______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://haskell.org/mailman/listinfo/haskell-prime
_______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://haskell.org/mailman/listinfo/haskell-prime

On 2006-02-04 at 16:08EST Cale Gibbard wrote:
cartesian xs ys = map (\[x,y] -> (x,y)) $ sequence [xs,ys]
I'm lost. Isn't that just like cartesian xs ys = [(x,y)|x<-xs, y<-ys] ? Whereas...
On 04/02/06, Jan-Willem Maessen
wrote: On Feb 4, 2006, at 1:31 PM, Jon Fairbairn wrote:
... There ought to be a list_product somewhere (I mean [1..] `list_product` [4..] == [(1,4),(2,4),(1,5),(3,4),(2,5),(1,6),...]). Is there?
Not that I know of, but here's one which handles finite lists correctly; it'd be a nice addition to Data.List:
dzip :: [a] -> [b] -> [(a,b)] dzip = dzipWith (,)
dzipWith :: (a -> b -> c) -> [a] -> [b] -> [c] dzipWith f [] ys = [] dzipWith f as [] = [] dzipWith f as (y:ys) = dzipK ys [y] where dzipK (b:bs) rbs = zipWith f as rbs ++ dzipK bs (b : rbs) dzipK [] rbs = dzipT as where dzipT ys@(_:yt) = zipWith f ys rbs ++ dzipT yt dzipT [] = []
-Jan-Willem Maessen
...does seem to work for infinite lists! -- Jón Fairbairn Jon.Fairbairn at cl.cam.ac.uk

Oh, sorry about that. I posted too quickly, and hadn't noticed that
was the original intention.
- Cale
On 05/02/06, Jon Fairbairn
On 2006-02-04 at 16:08EST Cale Gibbard wrote:
cartesian xs ys = map (\[x,y] -> (x,y)) $ sequence [xs,ys]
I'm lost. Isn't that just like cartesian xs ys = [(x,y)|x<-xs, y<-ys] ?
Whereas...
On 04/02/06, Jan-Willem Maessen
wrote: On Feb 4, 2006, at 1:31 PM, Jon Fairbairn wrote:
... There ought to be a list_product somewhere (I mean [1..] `list_product` [4..] == [(1,4),(2,4),(1,5),(3,4),(2,5),(1,6),...]). Is there?
Not that I know of, but here's one which handles finite lists correctly; it'd be a nice addition to Data.List:
dzip :: [a] -> [b] -> [(a,b)] dzip = dzipWith (,)
dzipWith :: (a -> b -> c) -> [a] -> [b] -> [c] dzipWith f [] ys = [] dzipWith f as [] = [] dzipWith f as (y:ys) = dzipK ys [y] where dzipK (b:bs) rbs = zipWith f as rbs ++ dzipK bs (b : rbs) dzipK [] rbs = dzipT as where dzipT ys@(_:yt) = zipWith f ys rbs ++ dzipT yt dzipT [] = []
-Jan-Willem Maessen
...does seem to work for infinite lists! -- Jón Fairbairn Jon.Fairbairn at cl.cam.ac.uk

On Sat, Feb 04, 2006 at 06:31:56PM +0000, Jon Fairbairn wrote:
There ought to be a list_product somewhere (I mean [1..] `list_product` [4..] == [(1,4),(2,4),(1,5),(3,4),(2,5),(1,6),...]). Is there?
This is called "fair conjunction" in "Backtracking, Interleaving, and Terminating Monad Transformers" [1]. (>>-) :: [a] -> (a -> [b]) -> [b] [] >>- f = [] (x:xs) >>- f = interleave (f x) (xs >>- f) interleave :: [a] -> [a] -> [a] interleave [] ys = ys interleave (x:xs) ys = x : interleave ys xs t = take 6 ([1..] >>- \x -> [4..] >>- \y -> [(x, y)]) Andrew [1] http://okmij.org/ftp/Computation/monads.html#LogicT

On Feb 4, 2006, at 9:11 AM, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against. ...
I tend to agree. But to back myself up, I thought I'd do an informal survey of uses of "zip" or "zipWith" in comprehensions. I did this using "grep -C 5" and hand inspection, so tallys may be off by 1 or 2. I counted three things: 1) Uses of "zip" and friends which could be replaced by zip comprehensions, but which weren't simply numbering the elements of a list (OK) 2) Uses of the list numbering idiom "zip [n..] (...)" and "zip (...) [n...]" (Number) 3) Uses of "zip" and friends which are not list numbering, and cannot be replaced by zip comprehensions. (Not OK) Conclusion: Haskell would benefit from a library function for the list-numbering idiom. (Plus, such a library would play nicely with any evaluation strategy you care to name...) This would eliminate more than half the uses of "zip" in comprehension generators. I was surprised to see that phc would have been the biggest beneficiary of zip comprehensions! -Jan-Willem Maessen OK = Could use zip comprehensions. Number = zip [n..] (...) or zip (...) [n..] Not OK = Can't use zip comprehensions---prior or subsequent clauses OK Number Not OK phc 6 1 5 Djinn 4 DrIFT 4 fps 1 GHC 11 15 12 happy 11 HSlibs/ 2 8 libraries ---------------------------------------- Total 19 44 17

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
[...] For what's it worth: I totally agree with John. Not only does this seems to me like a feature that'll be so little used to justify the introduction of special syntax, I also it'll make the language far less accessible for newbies. Just my $ .02, Stefan -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (Darwin) iD8DBQFD5PybX0lh0JDNIpwRAvq6AKCo0iB5GQioWEvAdeJEp2V2ZHvZgwCdEnv6 U4X5NgQzv7bAHZdqcHUd5dE= =IjMp -----END PGP SIGNATURE-----

On Sat, Feb 04, 2006 at 03:11:10PM +0100, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
I disagree. :) I use them all the time and find them very useful. however, I do agree with some of your criticisms and would be interested if we can think of some sort of generalization of them. John -- John Meacham - ⑆repetae.net⑆john⑈

On Sat, Feb 04, 2006 at 11:58:15AM -0800, John Meacham wrote:
On Sat, Feb 04, 2006 at 03:11:10PM +0100, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
I disagree. :) I use them all the time and find them very useful.
however, I do agree with some of your criticisms and would be interested if we can think of some sort of generalization of them.
Hmmm... you can use zip, can't you? If you want to zip arbitrary number of lists, there is a trick that can help: zApp = zipWith ($) then zip3 [1..4] [2..] [3..] is equivalent to: repeat (,,) `zApp` [1..4] `zApp` [2..] `zApp` [3..] where the latter is easily extensible. You could also only use zip, if you don't mind working on nested pairs: zip (zip [1..4] [2..]) [3..] I don't use parallel list comprehensions. I am also zipping trees, and PLCs don't help me here. Best regards Tomasz -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland

Hello Tomasz, Saturday, February 04, 2006, 11:18:47 PM, you wrote: TZ> I don't use parallel list comprehensions. I am also zipping trees, TZ> and PLCs don't help me here. making `zip` a class function should please you :) -- Best regards, Bulat mailto:bulatz@HotPOP.com

On Sun, Feb 05, 2006 at 12:50:16AM +0300, Bulat Ziganshin wrote:
Hello Tomasz,
Saturday, February 04, 2006, 11:18:47 PM, you wrote:
TZ> I don't use parallel list comprehensions. I am also zipping trees, TZ> and PLCs don't help me here.
making `zip` a class function should please you :)
Good idea! Best regards Tomasz -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland

On Sat, Feb 04, 2006 at 03:11:10PM +0100, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
As there are many voices against and only John M speaking for these, it seems reasonable at least to move them from "probably yes" to "maybe".
My opinion may be coloured by the fact that I never use the things. However, I think it's a mistake to add rarely used features with a small payoff to the language. It just makes the language larger, harder to learn, and harder to read for all but the expert, without much corresponding benefit.
I agree, but then I feel the same way about pattern guards. I've used them only recently, and that was modifying code (GHC) that already had lots of Maybe-returning functions designed for use with pattern guards.

On Thu, Feb 16, 2006 at 09:06:24AM +0000, Ross Paterson wrote:
On Sat, Feb 04, 2006 at 03:11:10PM +0100, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
As there are many voices against and only John M speaking for these, it seems reasonable at least to move them from "probably yes" to "maybe".
I really like them, partially because it gives list comprehensions more power than plain old do notation.
My opinion may be coloured by the fact that I never use the things. However, I think it's a mistake to add rarely used features with a small payoff to the language. It just makes the language larger, harder to learn, and harder to read for all but the expert, without much corresponding benefit.
I agree, but then I feel the same way about pattern guards. I've used them only recently, and that was modifying code (GHC) that already had lots of Maybe-returning functions designed for use with pattern guards.
Oh golly, I can't live without pattern guards. they are the best thing since sliced bread. :) I don't know how people can write concise code without them. John -- John Meacham - ⑆repetae.net⑆john⑈

oops, sorry for the double post. I accidentally sent a draft along with the final result. John -- John Meacham - ⑆repetae.net⑆john⑈

John Meacham wrote:
Oh golly, I can't live without pattern guards. they are the best thing since sliced bread. :) I don't know how people can write concise code without them.
I agree. Pattern guards is a must for Haskell'. When you need them (which is often), there's no good substitute. -- Lennart

(warning. rambling) On Thu, Feb 16, 2006 at 09:06:24AM +0000, Ross Paterson wrote:
On Sat, Feb 04, 2006 at 03:11:10PM +0100, John Hughes wrote:
I noticed ticket #55--add parallel list comprehensions--which according to the ticket, will probably be adopted. I would argue against.
As there are many voices against and only John M speaking for these, it seems reasonable at least to move them from "probably yes" to "maybe".
I don't think that field on the wiki is meant to be taken with more than a grain of salt. The real meat should be in the pros and cons section on the attached page. Part of the reason I really like parallel list comprehensions is that they give substantially more power to list comprehensions over do notation. I would be worried about dropping things because people exist who have not used the feature. For all they know, they might love it once they start using it. Very little of haskell is manditory so there really is no need for everyone to explore every corner of the language, but a lot of the syntax makes our lives easier, sometimes substantially so.
My opinion may be coloured by the fact that I never use the things. However, I think it's a mistake to add rarely used features with a small payoff to the language. It just makes the language larger, harder to learn, and harder to read for all but the expert, without much corresponding benefit.
I agree, but then I feel the same way about pattern guards. I've used them only recently, and that was modifying code (GHC) that already had lots of Maybe-returning functions designed for use with pattern guards.
Oh golly. I can't live without pattern guards. they are the best darn thing since sliced bread. I highly recommend them. I would be anoyed at not having parallel list comprehensions, but would have to seriously refactor a ton of code if pattern guards disapeared. So much so that it would be less work to implement pattern guards for other compilers and submit the patches. I also always sort of liked the symmetry between pattern guards, list comprehensions, and do notation. list comprehensions are do-notation restricted to the list monad and pattern guards are do notation restricted to the identity monad... John -- John Meacham - ⑆repetae.net⑆john⑈

On Thu, Feb 16, 2006 at 01:27:52AM -0800, John Meacham wrote:
I would be worried about dropping things because people exist who have not used the feature. For all they know, they might love it once they start using it. Very little of haskell is manditory so there really is no need for everyone to explore every corner of the language, but a lot of the syntax makes our lives easier, sometimes substantially so.
Features do impact on people who never use them: when they make errors that stray near the syntactic and type-system space occupied by the feature, and when they read or modify code written by others. As JohnH said, every addition increases the cost of the language, and needs to bring significant benefit to justify inclusion.
Oh golly. I can't live without pattern guards.
Yes, I knew my position was more extreme there.

On Thu, Feb 16, 2006 at 10:20:25AM +0000, Ross Paterson wrote:
Features do impact on people who never use them: when they make errors that stray near the syntactic and type-system space occupied by the feature, and when they read or modify code written by others. As JohnH said, every addition increases the cost of the language, and needs to bring significant benefit to justify inclusion.
Oh, I didn't mean to imply the features wouldn't impact people that didn't use them. Just that they might not necessarily not use the feature because it is bad, or they wouldn't be happier with it, but rather because they just havn't learned it. Not that I am saying anything about parallel list comprehensions necessarily, but just in general I would be wary of dropping a feature just on the basis of some people not using it who have never tried it. not against dropping it, just wary without some more investigation into finding out a bit more why people don't use said feature. After all, they could just know a much cooler feature that subsumes it that I havn't found yet :)
Oh golly. I can't live without pattern guards.
Yes, I knew my position was more extreme there.
perhaps mine is too :) but they are very nice. John -- John Meacham - ⑆repetae.net⑆john⑈

Oh golly. I can't live without pattern guards. they are the best darn thing since sliced bread. I highly recommend them. I .. would have to seriously refactor a ton of code if pattern guards disapeared.
So much so that it would be less work to implement pattern guards for other compilers and submit the patches.
eh, well, pattern guards are nice. but, many of their uses are also easily replaced, by moving the pg-monad from the lhs to the rhs, and employing MonadPlus for the fall-throughs; something roughly like: f p1 | g1 = e1 .. f pn | gn = en where <stuff> --> f x = fromJust $ do {p1 <- return x; guard g1; return e1} .. `mplus` do {pn <- return x; guard gn; return en} where <stuff> for any pattern matches in the guards, just drop the "guard";-) grouping several guards under one pattern is also straightforward. the only problem is where to place any pattern-dependent wheres. the easy approach matches them lazily out of x, but that matches some things twice.. this is not an argument against pattern guards; but I often find to my surprise that many Haskellers still think that functions with several clauses can't be translated easily (without losing the basic structure [*]) because of the "fall-through" on pattern-match failure, so they might find this translation pattern useful; it could also be elaborated (recovering better error messages) into a naive, but readable, desugaring of pattern-guards and the like, for reports, and for not-yet-supporting implementations.. cheers, claus [*] to be more accurate, since you can move the whole group of clauses into a case, the barrier is seen between moving from the world of patterns and guards to the world of expressions. MonadPlus allows us to move back.

On 2006-02-16, Claus Reinke
Oh golly. I can't live without pattern guards. they are the best darn thing since sliced bread. I highly recommend them. I .. would have to seriously refactor a ton of code if pattern guards disapeared.
So much so that it would be less work to implement pattern guards for other compilers and submit the patches.
eh, well, pattern guards are nice. but, many of their uses are also easily replaced, by moving the pg-monad from the lhs to the rhs, and employing MonadPlus for the fall-throughs; something roughly like:
f p1 | g1 = e1 .. f pn | gn = en where <stuff>
-->
f x = fromJust $ do {p1 <- return x; guard g1; return e1} .. `mplus` do {pn <- return x; guard gn; return en} where <stuff>
This works, of course, but it looks far far uglier, and is harder to type. -- Aaron Denney -><-
participants (16)
-
Aaron Denney
-
Andres Loeh
-
Andrew Pimlott
-
Bulat Ziganshin
-
Cale Gibbard
-
Claus Reinke
-
Duncan Coutts
-
Jan-Willem Maessen
-
John Hughes
-
John Meacham
-
Jon Fairbairn
-
Jon Fairbairn
-
Lennart Augustsson
-
Ross Paterson
-
Stefan Holdermans
-
Tomasz Zielonka