
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, ~wren