I want to write a conjugate gradient solver in Haskell and want to use lazy lists to decouple the stop rule and output information from iterations. My code looks something like this:
data CGState = CGState { cgx :: Image , cgp :: Image , cgr :: Image , cgr2 :: Double } cg :: Operator -> Image -> [CGState] cg = [...] runCG :: (CGState -> Bool) -> Operator -> Image -> IO Image runCG stoprule op rhs = do let steps = takeWhile (not . stoprule) $ cg op rhs fmap last $ forM (zip [(1::Int)..] steps) $ \(n, cgs) -> do putStrLn $ show n ++ " " ++ show (sqrt $ cgr2 cgs) return $ cgx cgs
The idea is to iterate over the list, output some information, but save only the last iteration. However, running this code does not seem to garbage collect the previous iterations. I assume this is due to IO: if I rewrote code like
runCG :: (CGState -> Bool) -> Operator -> Image -> IO Image runCG stoprule op rhs = do let steps = takeWhile (not . stoprule) $ cg op rhs return $ cgx $ last steps
the problem does not arise, i.e. all but the last iteration gets directly collected garbage.
How can I achieve the same effect, being able to output some information about iterations?
source share