Desidero scrivere un risolutore di gradienti coniugati in Haskell e voglio utilizzare liste pigre per disaccoppiare la regola di arresto e l'output di informazioni dalle iterazioni. Il mio codice è essenzialmente simile a questo:Garbage collection di un elenco durante l'esecuzione di un'azione IO su di esso
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
L'idea è quella di iterare l'elenco, uscita qualche informazione, ma conservano solo l'ultima iterazione. Tuttavia, quando si esegue questo codice, non sembra raccogliere i precedenti iterati. La mia ipotesi è che questo è collegato a IO: se riscrivo il codice come
runCG :: (CGState -> Bool) -> Operator -> Image -> IO Image
runCG stoprule op rhs = do
let steps = takeWhile (not . stoprule) $ cg op rhs
return $ cgx $ last steps
il problema non si verifica, vale a dire tutto, ma l'iterata finale ottiene rifiuti raccolti direttamente.
Come posso ottenere lo stesso effetto pur essendo in grado di generare alcune informazioni sulle iterazioni?