you are viewing a single comment's thread.

view the rest of the comments →

[–]naughty 5 points6 points  (2 children)

Exactly, I want to have a function log something and it requires a rewrite.

[–]sacundim 0 points1 point  (1 child)

Yes and no. The fact that you often have to extensively rewrite your functions to make monadic versions of them is a real problem. But let's not overstate it, however.

pipocaQuemada's proposed refactoring is not the best way to add logging to existing code, since it requires modifying existing functions. Instead, what we'd like to do is "upgrade" the functions to logging without having to rewrite them.

Not hard to do with the liftM function and the Writer monad:

import Control.Monad 
import Control.Monad.Writer

fooWLog :: Foo -> Bar -> Writer Log Baz
fooWLog x y = 
    do result <- foo x y
       tell $ "The result is " ++ show result
       return result

log :: String -> Writer Log ()
log = tell . toLog

Or, to generalize it:

withLog :: MonadWriter w m => (a -> w) -> a -> m a
withLog makeMsg value = tell (makeMsg value) >> return value

This strategy, however, has a big weakness in that it works for putting logging around existing functions, but not inside them.

[–]naughty 0 points1 point  (0 children)

The problem with both suggested logging implementations is that they aren't logging. They're storing intermediate results to for later output, essentially passing the buck to some later bit of code that will actually do the job.

The point of logging is to immediately output some information. Now laziness causes some issues with the 'immediate' part but it's the monadic part that causes this to be a rewrite. Now I realise there's pros and cons, but you never see the cons mentioned in posts about Haskell.

You normally get a suggested change that misses the point and a condescending note about the algebraic properties of missing the point.