[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:
> 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
> 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.
More information about the Haskell-Cafe