
Hi -- I'm using ghc 6.6, and I had some questions about the extend of laziness and foldr. I've noticed the following:
x = foldr (:) [] [1..] (take 10) x
yields [1..10] Which is great.. however, what I'd like to fold the list over a tuple:
foo x (l,payload) = ((x:l), payload) (x,_) = foldr foo ([], Nothing) [1..] (take 10) x
Doesn't terminate, until the stack overflows So I'm clearly expecting ghc to be more psychic than it's currently capable. But what I'd like to do is pass an infinite list through a processing function which maintains some state (foo could easily be a pseudo random number generator), and take the first bit of it. Any help? Thanks, Ranjan Bagchi

Hello,
So I'm clearly expecting ghc to be more psychic than it's currently capable. But what I'd like to do is pass an infinite list through a processing function which maintains some state (foo could easily be a pseudo random number generator), and take the first bit of it.
Any help?
Intuitively, your state is flowing from the end of the list back towards the beginning in your code. If you really want a right fold where the state flows from left to right, you could try this: foldrSt st f v [] = v st foldrSt st f v (x:xs) = let (st', f') = f st x in f' (foldrSt st' f v xs) and then rewrite foo as: foo payload x = (payload, (\l -> x:l)) then: take 10 $ foldrSt Nothing foo (\st -> []) [1..] evaluates to [1 .. 10]. -Jeff

Hello,
If you really want a right fold where the state flows from left to right, you could try this:
foldrSt st f v [] = v st foldrSt st f v (x:xs) = let (st', f') = f st x in f' (foldrSt st' f v xs)
In full monadic generality, we could define: foldrM f v [] = v foldrM f v (x:xs) = do f' <- f x v' <- foldrM f v xs f' v' -- -- test functions -- fooM x = return (\l -> return $ x : l) foo1M x = do -- st <- get put $ st + 1 return (\l -> return $ (x + st) : l) and get the following evaluations (with Control.Monad.State imported): *Cafe> runState (foldrM fooM (return []) [1..10]) 0 ([1,2,3,4,5,6,7,8,9,10],0) *Cafe> runState (foldrM foo1M (return []) [1..10]) 0 ([1,3,5,7,9,11,13,15,17,19],10) Of course replacing [1..10] with [1..] will cause non-termination, since runState returns the final state as well as the result. However we also get: *Cafe> take 10 $ evalState (foldrM fooM (return []) [1..]) 0 [1,2,3,4,5,6,7,8,9,10] *Cafe> take 10 $ evalState (foldrM foo1M (return []) [1..]) 0 [1,3,5,7,9,11,13,15,17,19] since evalState discards the final state. However, if you really just want to process infinite lists, you should be using map and filter (or mapM and filterM). -Jeff

On 12/9/06, Ranjan Bagchi
Which is great.. however, what I'd like to fold the list over a tuple:
foo x (l,payload) = ((x:l), payload) (x,_) = foldr foo ([], Nothing) [1..] (take 10) x
Doesn't terminate, until the stack overflows
Look at Data.List's mapAccumR function.
--
Taral

Thank you -- turns out that mapAccumL did exactly what I wanted it to, push state through processing a very large list. Thanks, Ranjan On Dec 10, 2006, at 10:18 AM, Taral wrote:
On 12/9/06, Ranjan Bagchi
wrote: Which is great.. however, what I'd like to fold the list over a tuple:
foo x (l,payload) = ((x:l), payload) (x,_) = foldr foo ([], Nothing) [1..] (take 10) x
Doesn't terminate, until the stack overflows
Look at Data.List's mapAccumR function.
-- Taral
"You can't prove anything." -- Gödel's Incompetence Theorem
participants (4)
-
jeff p
-
Matthew Brecknell
-
Ranjan Bagchi
-
Taral