Search code examples
haskellloggingmonad-transformersfree-monad

How do I add MonadLogger to my Free monad transformer stack?


I already asked this question here, but I thought I would try SO as well.

How do I add MonadLogger to this Free monad transformer stack?

newtype Craft a = Craft { unCraft :: ReaderT CraftEnv (FreeT CraftDSL IO) a }
  deriving ( Functor, Monad, MonadIO, Applicative
           , MonadReader CraftEnv, MonadFree CraftDSL, MonadThrow)

I was able to add MonadThrow without issue; I was hoping adding MonadLogger would be just as easy.

I tried adding it and I get this error:

No instance for (MonadLogger (FreeT CraftDSL IO))
  arising from the 'deriving' clause of a data type declaration

If I define an instance:

instance MonadLogger (FreeT CraftDSL IO) where
  monadLoggerLog a b c d = Trans.lift $ monadLoggerLog a b c d

I get this error:

Could not deduce (MonadLogger IO)
  arising from a use of ‘monadLoggerLog’

Here is a link to basic example of what I'm working on that compiles.


Solution

  • Adding LoggingT into the base of the stack works right away, but judging from

    No instance for (MonadLogger (FreeT CraftDSL IO)) arising from the 'deriving' clause of a data type declaration

    you want to log stuff in your DSL do-blocks. For this we need to make FreeT an instance of MonadLogger:

    instance (MonadLogger m, Functor f) => MonadLogger (FreeT f m) where
        monadLoggerLog loc source level msg = lift $ monadLoggerLog loc source level msg
    

    Thanks to LoggingT already be an instance of MonadLogger, the (MonadLogger m) => MonadLogger (FreeT f m) constraint holds for your Craft type.

    This code compiled for me, but since you didn't provide a minimal testcase i'm not sure if it really works.