Consider the following program:
module Main where
import Control.Monad.List
main = runListT $ do
x <- ListT $ return $ [0..1000000000]
lift $ print x
Ideally, we would want the list to be garbage collected as we consume it, so that this program only uses constant memory. But when I compile and run it with
ghc Main.hs -O2 -o Main
I see that it keep using more and more memory. How do I convince Haskell to GC the consumed elements of the list?
The Haskell runtime system employs a generational garbage collector (GC) with two generations 2. Generations are numbered starting with the youngest generation at zero. Values are always allocated in a special part of the youngest generation called the nursery.
The fundamental challenge garbage collection addresses is freeing memory that is not, or is not known to be, used in a stack-like fashion. It is most especially useful when there is no clear place in the source code that can be pinpointed as the end of the object's lifetime.
The ListT
in transformers
doesn't stream or run in constant space. The ListT
in pipes
does!
import Control.Monad (mzero)
import Pipes
main = runListT (do
x <- Select (each [0..1000000000])
lift (print x)
mzero )
I also just uploaded pipes-4.1.4
today, which relaxes runListT
to not require the mzero
at the end, so then it would just be:
-- Requires `pipes-4.1.4`
import Pipes
main = runListT (do
x <- Select (each [0..1000000000])
lift (print x) )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With