I try to make a derived instance for MonadWriter of the Continuation Monad Transformer. This is how i tried it:
{-# LANGUAGE MultiParamTypeClasses, FlexibleI
I don't think it's possible. For reference, here's the meaning of ContT:
ContT r m a = (a -> m r) -> m r
Here's my starting point for listen:
listen m = ContT $ \c ->
runCont m (\x -> c (x,w))
The question is, where do we get w? w will come from the computation that runCont m performs before it calls our function \x -> c (x,w) with its return value x. That is, the information we need to pass to c comes from runCont, so we would need to do something like this:
listen m = ContT $ \c -> do
rec (r,w) <- listen . runContT m $ \x -> c (x,w)
return r
(Needs LANGUAGE DoRec and MonadFix m in the context)
Although that typechecks, it is not correct. w is now the value written by the entire computation, not just the portion before calling our continuation \x -> c (x,w).
Do you see what you would need to do? I know my answer is essentially "I think it's impossible because I can't think of a way to do it" (what Conal Elliott calls "proof by lack of imagination"), but I think my lack of imagination is correct this time. The information we need is destroyed before we have a chance to peek at it.
I believe this instance is possible with the Codensity monad transformer:
newtype CodensityT m a = CodensityT { runCodensityT :: forall r. (a -> m r) -> m r }
which gives you the same performance improvements as Cont in the cases where it does that, but doesn't support callCC. This is because you can runCodensityT in the middle of a computation with whatever r you want.
listen m = CodensityT $ \c -> listen (runCodensityT m return) >>= c
Maybe callCC is the problem. I wouldn't be surprised if you could come up with an example combining listen and callCC that would create a paradox.