Re: [GHC] #3709: Data.Either.partitionEithers is not lazy enough

#3709: Data.Either.partitionEithers is not lazy enough
This is a behavioural change, e.g.: Main> case partitionEithers1 [Left 'a', error "Not me"] of (x : _, _) -> x Program error: Not me Main> case partitionEithers2 [Left 'a', error "Not me"] of (x : _, _) -> x 'a'
Yes, and isn't that the point of the bugfix? No non-bottoming program has changed, but fewer programs fail now. I find it hard to imagine that anyone could have been relying on getting a crash here.
Shouldn't it be discussed on the libraries list first?
Possibly, although I believe we have never treated a change towards being more lazy as an API change before. Making something more strict usually provokes discussion, because it causes more programs to crash, but making things lazier is usually considered a bugfix. Copying to libraries@, to see if there are any objections. If there are, feel free to back out the patch. -> See http://hackage.haskell.org/trac/ghc/ticket/3709 Regards, Malcolm

On Thu, 3 Dec 2009, Malcolm Wallace wrote:
#3709: Data.Either.partitionEithers is not lazy enough
This is a behavioural change, e.g.: Main> case partitionEithers1 [Left 'a', error "Not me"] of (x : _, _) -> x Program error: Not me Main> case partitionEithers2 [Left 'a', error "Not me"] of (x : _, _) -> x 'a'
Yes, and isn't that the point of the bugfix? No non-bottoming program has changed, but fewer programs fail now. I find it hard to imagine that anyone could have been relying on getting a crash here.
Making something more lazy can cause a memory leak.

On 03/12/2009 14:12, Henning Thielemann wrote:
On Thu, 3 Dec 2009, Malcolm Wallace wrote:
#3709: Data.Either.partitionEithers is not lazy enough
This is a behavioural change, e.g.: Main> case partitionEithers1 [Left 'a', error "Not me"] of (x : _, _) -> x Program error: Not me Main> case partitionEithers2 [Left 'a', error "Not me"] of (x : _, _) -> x 'a'
Yes, and isn't that the point of the bugfix? No non-bottoming program has changed, but fewer programs fail now. I find it hard to imagine that anyone could have been relying on getting a crash here.
Making something more lazy can cause a memory leak.
and a time leak, or a stack overflow. People might complain if we made foldl' more lazy :-) Cheers, Simon

No non-bottoming program has changed, but fewer programs fail now. I find it hard to imagine that anyone could have been relying on getting a crash here.
Making something more lazy can cause a memory leak.
But in this case, leaving it strict would be responsible for a memory leak, whereas laziness removes the leak for some cases. In those cases where the lazy version still has a memory leak, the strict version also suffers from the same leak.
and a time leak, or a stack overflow. People might complain if we made foldl' more lazy :-)
I believe there is general agreement that Haskell library functions should be lazy by default. Where there is a compelling case for strictness, it is usually noted by changing the name, e.g. foldl vs foldl'. Where something has explicitly been strictified, of course making it lazy again would rightly provoke howls of protest. But where a function seems to be *un*intentionally too strict...? To come back to the specifics of partitionEithers, is anyone arguing that, in this case, the original over-strictness is either intentional, or useful? Regards, Malcolm

On Fri, 2009-12-04 at 01:19 +0000, Malcolm Wallace wrote:
No non-bottoming program has changed, but fewer programs fail now. I find it hard to imagine that anyone could have been relying on getting a crash here.
Making something more lazy can cause a memory leak.
To come back to the specifics of partitionEithers, is anyone arguing that, in this case, the original over-strictness is either intentional, or useful?
I don't think anyone is complaining about this specific case. I think we agree that the general principle is to make things lazy except where there are compelling reasons to do otherwise. As another example, intersperse (and intercalate) could be made slightly more lazy with no loss of efficiency (indeed it looks like it could be an improvement): intersperse :: a -> [a] -> [a] intersperse _ [] = [] intersperse sep (x0:xs0) = x0 : go xs0 where go [] = [] go (x:xs) = sep : x : go xs vs the standard def: intersperse :: a -> [a] -> [a] intersperse sep [] = [] intersperse sep [x] = [x] intersperse sep (x:xs) = x : sep : intersperse sep xs intersperse '_' ('x' : undefined) = 'x' : undefined vs List.intersperse '_' ('x' : undefined) = undefined Duncan

Excerpts from Duncan Coutts's message of Fri Dec 04 18:22:05 +0100 2009:
On Fri, 2009-12-04 at 01:19 +0000, Malcolm Wallace wrote:
No non-bottoming program has changed, but fewer programs fail now. I find it hard to imagine that anyone could have been relying on getting a crash here.
Making something more lazy can cause a memory leak.
To come back to the specifics of partitionEithers, is anyone arguing that, in this case, the original over-strictness is either intentional, or useful?
I don't think anyone is complaining about this specific case. I think we agree that the general principle is to make things lazy except where there are compelling reasons to do otherwise.
+1 (for a lazier partitionEithers, intersperse and intercalate) -- Nicolas Pouillard http://nicolaspouillard.fr
participants (5)
-
Duncan Coutts
-
Henning Thielemann
-
Malcolm Wallace
-
Nicolas Pouillard
-
Simon Marlow