我已经问过这个问题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是我正在编写的基本示例的链接。
答案 0 :(得分:2)
将FreeT
添加到堆栈的基础可立即工作,但从
没有实例(MonadLogger(FreeT CraftDSL IO)) 来自数据类型声明的“派生”子句
你想记录你的DSL do-blocks中的东西。为此,我们需要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
约束适用于您的{{1}}类型。
此代码为我编译,但由于您没有提供最小的测试用例,我不确定它是否真的有效。
答案 1 :(得分: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 }
如果缺少实例,则需要手动编写,因为free
和monad-logger
包不会为其他变换器提供实例。