
There seems to be a misconception in this thread that there is something "non-functional" or "imperative" about using monads. That is simply not true. When what you are trying to write is most naturally and clearly expressed as a series of steps - there is no reason not to use a monad. Even when a function is most naturally written as purely recursive, in real-life code you often add "Monad m =>" to the type signature and wrap the function in a "return". This is primarily so that you can propagate exceptions. (I personally am not so impressed by the refactoring fears in the referenced paper, but yes, that is another reason.) True, there are a few rare monads that have non-lazy semantics; IO and ST come to mind. So I avoid those unless absolutely necessary. On Tue, Aug 30, 2005 at 12:40:27PM +0100, Thomas Davie wrote:
On Aug 30, 2005, at 12:13 PM, Bayley, Alistair wrote:
Something else I noticed about my non-monadic code was the way I was threading state through functions.
That was the classical way of doing state in functional languages, but in my opinion it is very bad style in modern Haskell.
I was tempted to introduce a State monad...
Right!
I was also wondering what the disadvantages of monadic style are?
Both the advantage and the disadvantage is that you break lazy evaluation.
Not true. Only if you use a non-lazy monad, like IO or ST. There is no inherent advantage or disadvantage to monads. If the idea is most clearly expressed as a monad, use a monad. If the idea is most clearly expressed recursively, write it recursively (but perhaps wrap it in "return"). Using that philosophy, I find that quite a bit of my code is monadic - most commonly State and StateT - and still perfectly functional and lazy.
90% of the time lazyness is your friend... but there is an occasional 10% of the time when it's useful to break lazyness.
I find the percentage much higher than 90%.
...monadifying your code can break some nice features,...
I do not know of any features it breaks.
On a side note, whenever I find myself tempted to pass state around, I consider whether using CPS is better...
I do not know how it could ever make sense to use CPS, except for a research project that explicitly requires it. (Yes, I know about callCC. I use a much simpler and clearer Exit monad instead.) -Yitz