[Haskell-beginners] Re: (ab)use compiler optimization
apfelmus at quantentunnel.de
Fri Oct 9 07:10:28 EDT 2009
Martin Hofmann wrote:
> I thought, that maybe I can (ab)use the compiler to switch logging on
> and off as needed before compiling. I tried to either always return an
> empty Log when running the WriterT, or just always ignore logging
> depending on a constant and hoped GHC to optimize the logging away.
> _NOLOGGING = True
> runWT :: (Monad m) => (WriterT Log m a) -> m (a, Log)
> runWT m
> | _NOLOGGING = runWriterT m empty >>= \(a,_) -> return (a,emptyLog )
> | otherwise = runWriterT m emptyLog
> logging :: Message -> WriterT Log m ()
> logging msg = if _NOLOGGING then return () else tell msg
> However, according to the heap profile there is still a lot of 'Log' in
> the memory. So, is this possible this way at all and if not, is there
> another (apart from removing all logging by hand).
Most likely, the WriterT monad is still constructing a log, except that
it now looks like
emptyLog `mappend` emptyLog `mappend` ... etc.
Of course, this is equal to emptyLog but it's never evaluated and
these huge expressions are eating up memory.
I think that importing WriterT from Control.Monad.Writer.Strict should
solve the problem. With that, you can revert to
runWT = runWriterT
as well, only logging needs to be implemented as you did.
Another method, which is guaranteed to work, is to implement a minuscule
custom logging monad like this:
module Logger where
type Logger m a = WriterT Log m a
runLogger = runWriterT
logging = tell
and replace it with
module MockLogger where
type Logger m a = m a
runLogger = fmap $ \a -> (a,emptyLog)
logging = const $ return ()
when you don't want to log anything.
More information about the Beginners