
Brent: Thanks for reminding me about (>=>). Far more readable! But regarding
the sequence thing: I can think of all sorts of reasons why we'd want to do
a single traversal. How about when lst is long or infinite? In general, it's
more useful to produce output incrementally than all at once at the end.
Mike S Craig
(908) 328 8030
On Wed, Sep 14, 2011 at 8:18 PM, Brent Yorgey
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
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners