2

我已经在这里问过这个问题,但我想我也会尝试。

如何添加MonadLogger到这个免费的单子变压器堆栈?

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’

是我正在编译的基本示例的链接。

4

2 回答 2

2

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

没有由数据类型声明的“派生”子句引起的 (MonadLogger (FreeT CraftDSL IO)) 实例

你想在你的 DSL do-blocks 中记录东西。为此,我们需要创建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类型。

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

于 2016-01-31T08:20:13.607 回答
1

添加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包不为彼此的转换器提供实例。

于 2016-01-29T06:00:23.570 回答