[Haskell-beginners] How Best to Deal with Nested Monads?
Brent Yorgey
byorgey at seas.upenn.edu
Thu Sep 15 02:18:50 CEST 2011
On Wed, Sep 14, 2011 at 06:48:29PM -0400, Michael Craig wrote:
> Say we've got these types
>
> lst :: m [a]
> getMB :: a -> m (Maybe b)
> getC :: b -> m c
>
> and we want to map getMB and getC over the elements of lst, all the while
> discarding elements x where getMB x == Nothing.
>
> (This could be generalized more by replacing Maybe with some monad m', but
> let's run with Maybe because it's easy to talk about.)
>
> The best I've got (after some help on IRC) is this not-so-easy-to-read
> oneliner:
>
> lst >>= (\x -> mapM (liftM (liftM getC) (getMB x)) >>= sequence
> . catMaybes
How about this:
lst >>= (mapM getMB >=> (return . catMaybes) >=> mapM getC)
Everyone always forgets about (>=>).
> This is hard to read, but it's also bad because we run sequence twice (once
> inside of mapM). If we want to do multiple things to each element of lst, it
> would be nice to process each element completely before moving on to the
> next.
I wouldn't worry about running sequence twice. Processing things by
chaining whole-structure transformations is the Haskell Way (tm). All
that business about "doing only one traversal" is for people
programming in strict languages to worry about. The compiler can often
turn a chain of wholesale transformations into a single traversal
anyway. In short, I see no particular reason why it is "nice" to
process each element completely before moving on. Isn't it nicer to
be able to think in a more modular style?
-Brent
More information about the Beginners
mailing list