如何将 MonadLogger 添加到我的免费 monad 转换器堆栈?

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

我已经问过这个问题了here,但我想我也会试试。

如何将 MonadLogger 添加到这个免费的 monad 转换器堆栈?

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

我能够毫无问题地添加 MonadThrow;我希望添加 MonadLogger 也一样简单。

我尝试添加它,但出现此错误:

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

如果我定义一个实例:

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

我收到这个错误:

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

Here 是我正在编译的基本示例的 link。

LoggingT添加到转换器栈中,即

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

或者如果您需要登录解释 DSL:

newtype Craft a = Craft { unCraft :: ReaderT CraftEnv (FreeT CraftDSL (LoggingT IO)) a }

如果缺少实例,那么您需要手动编写它们,因为 freemonad-logger 包不为彼此的转换器提供实例。

LoggingT 添加到堆栈的底部立即生效,但从

判断

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

您想在 DSL do 块中记录内容。为此,我们需要使 FreeT 成为 MonadLogger:

的一个实例
instance (MonadLogger m, Functor f) => MonadLogger (FreeT f m) where
    monadLoggerLog loc source level msg = lift $ monadLoggerLog loc source level msg

由于 LoggingT 已经是 MonadLogger 的实例,(MonadLogger m) => MonadLogger (FreeT f m) 约束适用于您的 Craft 类型。

这段代码是为我编译的,但由于您没有提供最小测试用例,我不确定它是否真的有效。