[Haskell-beginners] Re: (ab)use compiler optimization

Heinrich Apfelmus 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. 
> 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 mailing list