Tom Pledger Tom.Pledger@peace.com
Thu, 10 Apr 2003 08:40:16 +1200

Mark T.B. Carroll writes:
 | I wanted a monadic unfoldr and couldn't see one so I thought I'd share two
 | possibilities I'd been playing with:
 | unfoldM_a :: Monad m => (b -> Maybe (m (a, b))) -> b -> m [a]
 | unfoldM_b :: Monad m => (b -> m (Maybe (a, b))) -> b -> m [a]

Of those two, I prefer unfoldM_b because it gives you the opportunity
to do some stuff in the monad before you decide between Just and

Here's a third, which merges the roles of Maybe and m.

    import Control.Monad.Error
    -- for instance MonadPlus IO
    -- and the reexport of MonadPlus

    unfoldM_c :: MonadPlus m => (b -> m (a, b)) -> b -> m [a]
    unfoldM_c f b =
        do (a, b) <- f b
           as <- unfoldM_c f b
           return (a:as)
        `mplus` return []

This has the (possibly undesirable) effect, when m is [], of
generating all prefixes of the full unfolded list.

- Tom