[Haskell-cafe] Lazy counting and printing
Anakim Border
akborder at gmail.com
Sat Mar 28 09:18:58 EDT 2009
Hi,
I have written a code like this:
import Control.Monad.State
countedRecords :: [Int] -> StateT Int IO [Int]
countedRecords [] = return []
countedRecords (r:rs) = do
modify (+1)
rest <- countedRecords rs
return $ r:rs
printEven :: [Int] -> StateT Int IO ()
printEven records = do
let even = filter (\n -> n `mod` 2 == 0) records
lift $ mapM_ (putStrLn . show) even
combine :: [Int] -> StateT Int IO ()
combine records = countedRecords records >>= printEven
main = do
let numbers = [1..1000000]
count <- execStateT (combine numbers) 0
putStrLn $ "Processed " ++ show count ++ " numbers."
My intent is that of processing a large collection of records (in this
example, integers) doing two things at once: count their total number
and print those that satisfy a certain condition. I would like to keep
the definitions of the two functions performing such tasks
independent. As a result I've used the State monad to hide
intermediate counts.
Unfortunately the code above breaks laziness, in that records are
first completely counted (and stored in memory) and only then filtered
and printed. If I redefine main as:
main = do
let numbers = [1..]
..
i.e. I produce an unbounded number of records, I get a stack overflow.
Moreover, I don't like the way countedRecords and printEven are
defined, because their type signatures are too "broad". I would prefer
them to be:
countedRecords :: [Int] -> State Int [Int]
printEven :: [Int] -> IO ()
and let "combine" do some sort of lifting into the StateT monad.
Is there any way to perform both operations lazily?
Thanks
More information about the Haskell-Cafe
mailing list