Impossible to derive Instance of MonadWriter for Continuation Monad Transformer?

前端 未结 1 799
Happy的楠姐
Happy的楠姐 2021-01-04 17:16

I try to make a derived instance for MonadWriter of the Continuation Monad Transformer. This is how i tried it:

{-# LANGUAGE MultiParamTypeClasses, FlexibleI         


        
1条回答
  •  無奈伤痛
    2021-01-04 17:51

    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.

    0 讨论(0)
提交回复
热议问题