Why doesn't ContT relate to the inner monad?

The binding strategy for ContTignores the internal monad; in fact, the code is the same as for Cont.

Following an analogy with other Monad Transformers, I would implement it as follows:

return x = ContT ($ (return x))
(>>=) x f = ContT (\k -> runContT x ((=<<) (\a -> runContT (f a) k)))

Then, for example, this expression:

do 
    x1 <- ContT (\k -> k [1, 2])
    x2 <- ContT (\k -> k [10, 20])
    return ((+) x1 x2) 

The result will be [11, 21, 12, 22]

My question is, what is the reason for this design decision? Why it was implemented in a way that is very different from other Monad Transformers, note that the functor instance:

fmap f m = ContT $ \c -> runContT m (c . f)

but not:

fmap f m = ContT $ runCont $ (fmap . fmap) f (Cont (runContT m))

, Monad Transformers, , , , , , , , , -. , , ?

IdentityT , , Cont , Identity, ContT IdentityT?

+4
2

(>>=) ( , , , ), lift .

lift :: Monad m => m a -> ContT r m a
lift ma = ContT (ma >>=)

:

instance MonadTrans (ContT r) where
    lift m = ContT (m >>=)

import Control.Monad.Trans.Cont
import Control.Monad.Trans.Class

test :: ContT r [] Int
test = do
  x <- lift [1, 2]
  y <- lift [10, 20]
  return (x + y)

-- evalContT test == [11, 21, 12, 22]

, monad ContT , - .

+5

(>>=):

> let foo x f = ContT (\k -> runContT x ((=<<) (\a -> runContT (f a) k)))
> :t foo
foo
  :: Monad m =>
     ContT r m (m a) -> (a -> ContT r m a1) -> ContT r m a1
     ^^^^^^^^^^^^^^^

ContT r m a (>>=).

return:

> let bar  x = ContT ($ (return x))
> :t bar
bar :: Monad m1 => a -> ContT r m (m1 a)
                        ^^^^^^^^^^^^^^^^

m1.

+4

All Articles