[Haskell-cafe] walking a directory tree efficiently

wren ng thornton wren at freegeek.org
Sun Jan 18 02:37:01 EST 2009

Manlio Perillo wrote:
> By the way, I have managed to have a working program:
> http://hpaste.org/13919
> I would like to receive some advices:
> 1) I have avoided the do notation,

As Paolo Losi says, there's nothing wrong with do-notation. You should 
use whichever style makes your code the easiest to understand.

In order to increase your understanding it's a helpful exercise to write 
monadic code in applicative style instead of do-notation, just as it can 
be helpful to use points-free style instead of lambda abstractions. But 
these are just exercises to help you become more familiar with doing the 
transformations in your mind. At the end of the day, you should use 
whichever of these styles makes your code easiest to read. Sometimes 
that even means switching between them and using different styles in 
different places. There's no performance difference between them because 
the compiler does various transformations to normalize things before 
doing real work.

> using functions like liftM.
>    Is this a good practice?
>    Is this as efficient as using do notation?

I prefer using (liftM f m) instead of (m >>= return . f) which is more 
verbose and obfuscates the purity of f. Though personally liftM doesn't 
strike me as an infix operator and so I think it's clearer to use it in 
prefix form. The name doesn't support infixation as well as `elem`, 
`asTypeOf`, `isPrefixOf`, etc.

If all of your Monads define instances for Functor as well ---and they 
should!--- then you can use (<$>) from Control.Applicative as a good 
infix name. The functions liftM and fmap are equal. The Monad class 
should have Functor as a superclass since all monads are functors, but 
brokenly it doesn't. The only difference between using liftM and using 
fmap is which dictionaries get passed around for polymorphic functions 
(assuming they're not all compiled away). Sometimes there might be a 
small difference in clarity too, since not everyone realizes all monads 
are functors.

> 2) I have written some support functions: mapM' and filterM'
>    Are they well written and generic?
>    Are they already available in some package?
>    Can you suggest better names?

Your mapM' can be written as (fmap . fmap) which is more generic. 
Assuming your Monads are Functors, of course.

Your filterM' can be rewritten as ((=<<) . filterM) or as the somewhat 
more verbose (\f m -> m >>= filterM f)

Since these functions are so short and are used only once, I would 
suggest just writing the definitions inline instead of breaking them out 
and giving them names. Giving them names makes them seem more important 
than they are.

> 3) I find
>    (,) node `liftM` walkTree' path
>    not very readable.
>    Is it possible to express it in a more (not too much) verbose way?

liftM (\x -> (node,x)) (walkTree' path)

Don't be afraid of verbosity if you think it makes the code clearer to read.

Live well,

More information about the Haskell-Cafe mailing list