I recently had two functions of very similar shape, only difference was that one
was pure and the other need some I/O. The former was easily written using
mapAccumL. I failed to find a function like
mapAccumL that runs in a monad,
so I wrote up the following:
mapAccumM :: (Monad m, Traversable t) => (a -> b -> m (a, c)) -> a -> t b -> m (a, t c) mapAccumM f a l = swap <$> runStateT (mapM go l) a where go i = do s <- get (s', r) <- lift $ f s i put s' return r
Bring on the comments/suggestions/improvements/etc!