External monad update only in monad transformer

I have a monad for the calculation, which can fail and makes some entries:

f1 :: WriterT [String] (Either String) a 

I have a function that will not fail, but will make some entries:

 f2 :: Writer [String] b 

What is the best way to update the writer monad in f1 using the log from f2 and capture the output of the calculation of f2? At the moment I am doing this:

 f2result <- (\(r,l) -> do {tell l; return r}) (runWriter f2) 

I use the elevator to update the internal monad with a different calculation, so switching between Writer and Either the monads do not solve the problem.

+7
source share
2 answers

If you define f2 , refactoring f2 can be the easiest way, so it will be defined as follows:

  f2 :: Monad m => WriterT [String] mb 

This should not be too complicated, because Writer wb is defined as WriterT w Identity b , and the Identity monad does nothing.

Then you can connect them by doing f1 >> f2 .

If you cannot override f2 , you can always define your own with the appropriate signature:

  f2' :: Monad m => WriterT [String] mb f2' = WriterT . return $ runWriter f2 

And if you have a bunch of f2 for wrapping, you can always define a function to wrap them for you

  wrap :: Monad m => Writer wb -> WriterT wmb wrap = WriterT . return . runWriter 

So you can do f1 >> wrap f2a >> wrap f2b >> wrap f2c ...

+4
source

As a continuation of the rampion answer, you can instead reorganize f2 on any MonadWriter :

 f2 :: MonadWriter [String] m => ma 

It is impossible to change your definition, you can wrap it in the same way as ramping:

 f2' :: MonadWriter [String] m => ma f2' = do let (a,w) = runWriter f2 tell w return a 

The [String] argument for MonadWriter requires this GHC pragma:

 {-# LANGUAGE FlexibleContexts #-} 

As always, pragmas are placed on top of the module.

In the comments, rampion provided a version of the function wrapper in this parameter:

 wrap :: MonadWriter wm => Writer wb -> mb wrap = uncurry (<<) . (return *** tell) . runWriter where (<<) = flip (>>) 
+4
source

All Articles