仅在monad变换器中更新外部monad

msk*_*kel 7 monads haskell monad-transformers

我有一个可能失败的计算monad并进行一些日志记录:

f1 :: WriterT [String] (Either String) a
Run Code Online (Sandbox Code Playgroud)

我有一个功能,不会失败,但做一些日志记录:

f2 :: Writer [String] b
Run Code Online (Sandbox Code Playgroud)

使用f2中的日志更新f1中的writer monad的最佳方法是什么,并捕获f2计算的输出?目前我正在这样做:

f2result <- (\(r,l) -> do {tell l; return r}) (runWriter f2)
Run Code Online (Sandbox Code Playgroud)

我使用lift来更新内部monad的计算方法不同,因此切换Writer和Either monad都无法解决问题.

ram*_*ion 4

如果您定义了f2,最简单的方法可能是重构,f2因此它的定义如下:

 f2 :: Monad m => WriterT [String] m b
Run Code Online (Sandbox Code Playgroud)

这应该不会太难,因为Writer w b被定义为WriterT w Identity b,并且Identitymonad 不会给你任何东西。

然后你就可以通过这样做来链接它们f1 >> f2

如果您无法重新定义f2,您始终可以使用适当的签名定义您自己的:

 f2' :: Monad m => WriterT [String] m b
 f2' = WriterT . return $ runWriter f2
Run Code Online (Sandbox Code Playgroud)

如果你有一堆f2要包装的东西,你总是可以定义一个函数来为你包装它们

 wrap :: Monad m => Writer w b -> WriterT w m b
 wrap = WriterT . return . runWriter
Run Code Online (Sandbox Code Playgroud)

所以你可以做f1 >> wrap f2a >> wrap f2b >> wrap f2c ...