purescript/purescript-lists

Big problem with not big list

xgrommx opened this issue · 1 comments

Hello everyone! I have some experiments with lazy list. But I have some problem.

module Main where

import Prelude (Unit, map, mod, show, ($), (*), (+), (/=), (<<<), (<=))
import Data.List.Lazy (all, filter, repeat, take, iterate, length, takeWhile, (:))
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Data.Lazy (defer, force)

main :: Eff (console::CONSOLE) Unit
main = do
  -- log <<< show <<< length <<< take 1000000 <<< map (_+10) <<< repeat $ 1 -- works
  -- log <<< show <<< length <<< take 10000000 <<< map (_+10) <<< repeat $ 1 -- hard
  -- log <<< show <<< length <<< take 100000000 <<< map (_+10) <<< repeat $ 1 -- oh my...
  -- log <<< show <<< length <<< take 100000 <<< iterate(_+1) $ 1 -- Maximum call stack size exceeded
  -- log <<< show <<< length <<< take 10000 <<< iterate(_+1) $ 1 -- Maximum call stack size exceeded
  log <<< show <<< length <<< take 1000 <<< iterate(_+1) $ 1 -- only this code works!!!

As u can see iterate has some strange behavior. I think this problem in map here https://github.com/purescript/purescript-lists/blob/master/src/Data/List/Lazy.purs#L189

Or maybe I don't know how use lazy list in purescript. If it is, please help me =)

Nice to meet you everyone! I came across the same problem. It seems that it is iterate that is not stack-safe.

An alternative, hand-made implementation of mine seems to work:

myIterate :: forall a. (a -> a) -> a -> List a
myIterate f x = List $ defer \_ -> Cons x (myIterate f (f x))

main = log <<< show <<< length <<< take 100000 <<< myIterate(_+1) $ 1
-- prints 100000