
Hi, I came upon this when playing with foldr and filter. Compare the two definitions: testr n = foldr (\x y -> x && y) True [t | (_, t) <- zip [1 .. n] [True, True ..]] testr' n = foldr (\x y -> y && x) True [t | (_, t) <- zip [1 .. n] [True, True ..]] I tried these functions on ghci (The Glorious Glasgow Haskell Compilation System, version 7.0.3), and get the following results (with :set +s): testr 1000000 => True (0.01 secs, 7920832 bytes) testr' 1000000 => True (8.72 secs, 446585344 bytes) This bizarre (at least to me) behavior also applies to ||. Should I mind the orderings of the parameters (especially the accumulator) in the function passed to foldr? Thak you for reading. Sincerely yours, Frodo Chao

Yeah, you should absolutely mind the order of the parameters (or more
generally, when the operation isn't commutative), the strictness of the
function's second parameter. In this case, both (&&) and (||) are strict in
their first parameter, but both "short circuit" if the first parameter is
False/True, and don't evaluate their second parameter. The short-circuiting
(via laziness) terminates foldr's traversal of the entire list structure and
saves the program lots of work. By flipping the arguments, you're basically
forcing testr' to traverse the entire list before saying what it knew from
the beginning.
On Tue, Oct 11, 2011 at 10:45 PM, Frodo Chao
Hi,
I came upon this when playing with foldr and filter. Compare the two definitions:
testr n = foldr (\x y -> x && y) True [t | (_, t) <- zip [1 .. n] [True, True ..]] testr' n = foldr (\x y -> y && x) True [t | (_, t) <- zip [1 .. n] [True, True ..]]
I tried these functions on ghci (The Glorious Glasgow Haskell Compilation System, version 7.0.3), and get the following results (with :set +s):
testr 1000000 => True (0.01 secs, 7920832 bytes) testr' 1000000 => True (8.72 secs, 446585344 bytes)
This bizarre (at least to me) behavior also applies to ||. Should I mind the orderings of the parameters (especially the accumulator) in the function passed to foldr?
Thak you for reading.
Sincerely yours, Frodo Chao
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

* Daniel Peebles
Yeah, you should absolutely mind the order of the parameters (or more generally, when the operation isn't commutative), the strictness of the function's second parameter. In this case, both (&&) and (||) are strict in their first parameter, but both "short circuit" if the first parameter is False/True, and don't evaluate their second parameter. The short-circuiting (via laziness) terminates foldr's traversal of the entire list structure and saves the program lots of work. By flipping the arguments, you're basically forcing testr' to traverse the entire list before saying what it knew from the beginning.
He takes && of True's, so short-circuiting considerations should not apply.
On Tue, Oct 11, 2011 at 10:45 PM, Frodo Chao
wrote: Hi,
I came upon this when playing with foldr and filter. Compare the two definitions:
testr n = foldr (\x y -> x && y) True [t | (_, t) <- zip [1 .. n] [True, True ..]] testr' n = foldr (\x y -> y && x) True [t | (_, t) <- zip [1 .. n] [True, True ..]]
I tried these functions on ghci (The Glorious Glasgow Haskell Compilation System, version 7.0.3), and get the following results (with :set +s):
testr 1000000 => True (0.01 secs, 7920832 bytes) testr' 1000000 => True (8.72 secs, 446585344 bytes)
This bizarre (at least to me) behavior also applies to ||. Should I mind the orderings of the parameters (especially the accumulator) in the function passed to foldr?
Thak you for reading.
Sincerely yours, Frodo Chao
-- Roman I. Cheplyaka :: http://ro-che.info/

Hi Frodo, If you happen to have a memory consumption graph somewhere on the screen you can see that while testr does not need considerable amounts of memory, testr' does. This can also be seen by ghci’s output. The reason is that with testr we are building something like True && [thunk] which then evalutes to [thunk] which looks at the next element in the list and evaluates to True && [thunk] while with testr', we start with [thunk] && True and becaues && evalutes its first agument first, this thunk is entered and we get ([thunk] && True) && True and so on: (([thunk] && True) && True) && True ((([thunk] && True) && True) && True) && True ... until we reach the end of the list, with an inner True && True. At this point, this chain of thunks is reduced to True as you can see, there is much more memory stuff to do in testr' than in testr. If you replace && by || you’ll see that testr' behaves very similar to the && variant, while testr finishes immediately, no matter how large the parameter, due to the short circuiting mentioned by Daniel. Greetings, Joachim -- Joachim "nomeata" Breitner mail@joachim-breitner.de | nomeata@debian.org | GPG: 0x4743206C xmpp: nomeata@joachim-breitner.de | http://www.joachim-breitner.de/

* Frodo Chao
Hi,
I came upon this when playing with foldr and filter. Compare the two definitions:
testr n = foldr (\x y -> x && y) True [t | (_, t) <- zip [1 .. n] [True, True ..]] testr' n = foldr (\x y -> y && x) True [t | (_, t) <- zip [1 .. n] [True, True ..]]
I tried these functions on ghci (The Glorious Glasgow Haskell Compilation System, version 7.0.3), and get the following results (with :set +s):
testr 1000000 => True (0.01 secs, 7920832 bytes) testr' 1000000 => True (8.72 secs, 446585344 bytes)
This bizarre (at least to me) behavior also applies to ||. Should I mind the orderings of the parameters (especially the accumulator) in the function passed to foldr?
The definition of foldr is (equivalent to) foldr f a [] = a foldr f a (x:xs) = f x (foldr f a xs) Thus, in testr you invoke foldr (&&) a [True, True ..] = True && foldr (&&) a [True, True ..] Now, && is True && x = x False && _ = False So, True && foldr (&&) a [True, True ..] is transformed to foldr (&&) a [True, True ..] (with smaller list of True's, of course). You see that execution is tail-recursive here. You chop off the head of the list, process it and then only care about the rest of the list. In testr', however, && pattern-matches on the "a" argument to foldr. Its evaluation requires the whole tail of the list to be traversed, so it's not tail-recursive. -- Roman I. Cheplyaka :: http://ro-che.info/

Hi,
Thank you all for you replies.
I think now I understand Haskell better.
Best regards,
Frodo
2011/10/12 Frodo Chao
Hi,
I came upon this when playing with foldr and filter. Compare the two definitions:
testr n = foldr (\x y -> x && y) True [t | (_, t) <- zip [1 .. n] [True, True ..]] testr' n = foldr (\x y -> y && x) True [t | (_, t) <- zip [1 .. n] [True, True ..]]
I tried these functions on ghci (The Glorious Glasgow Haskell Compilation System, version 7.0.3), and get the following results (with :set +s):
testr 1000000 => True (0.01 secs, 7920832 bytes) testr' 1000000 => True (8.72 secs, 446585344 bytes)
This bizarre (at least to me) behavior also applies to ||. Should I mind the orderings of the parameters (especially the accumulator) in the function passed to foldr?
Thak you for reading.
Sincerely yours, Frodo Chao
participants (4)
-
Daniel Peebles
-
Frodo Chao
-
Joachim Breitner
-
Roman Cheplyaka