
On Saturday 04 July 2009, Uwe Hollerbach wrote:
Good evening, all, following up on my question regarding space leaks, I seem to have stumbled across something very promising. I said I was using this tiny function "lastOrNil" to get the last value in a list, or the empty (scheme) list if the haskell list was empty. The uses of it were all of the form
lastOrNil (mapM <something> <some list>)
so I wrote a different function mapML to do this directly:
mapML fn lst = mapMLA (List []) fn lst where mapMLA r _ [] = return r mapMLA ro fn (x:xs) = do rn <- fn x mapMLA rn fn xs
This isn't an accumulator, it's a replacer (or, if you like, the "accumulation" is "drop the old one on the floor"), it starts out with the scheme empty list that I want as the default, and it never even builds the list which it'll just dump an instant later. Shazam! Memory usage dropped by roughly an order of magnitude in my little Collatz benchmark, and incidentally runtime improved by 25% or so as well. The horror! :-)
Hi, IMHO expressing mapML using StateT would be a bit cleaner ;) mapML :: (Monad m) => (a -> m List) -> [a] -> m List mapML fn lst = execStateT mapMLAs (List []) where mapMLAs = sequence_ $ map mapMLA lst mapMLA x = (lift $ fn x) >>= put -- Marcin Kosiba