I'm playing with the Cont
monad tricks described here and in this SO question.
This function lets you "jump back" to earlier in the computation, taking a parameter so you can do things differently:
import Control.Monad.Cont
import Control.Monad.State.Strict
import Control.Monad.Writer.Strict
getCC' :: MonadCont m => a -> m (a,a -> m b)
getCC' x0 = callCC (\c -> let f x = c (x, f) in return (x0, f))
I have these toy examples of monad transformers on top of Cont
:
foo :: WriterT String (Cont String) ()
foo = do
(stop,loop) <- getCC' False
if stop
then do tell "bbb"
else do tell "aaa"
loop True
foo' :: StateT String (Cont String) ()
foo' = do
(stop,loop) <- getCC' False
if stop
then do modify $ \s -> s ++ "bbb"
else do modify $ \s -> s ++ "aaa"
loop True
In the first example (as explained in the linked SO question) the effects of Cont
have "priority" over the effects of the WriterT
. When we reset the computation, the log is lost:
*Main> print $ runCont (execWriterT foo) id
"bbb"
The second example does exactly the same thing, only using StateT
instead of WriterT
. However, in this case the log is preserved!
*Main> print $ runCont (execStateT foo' "") id
"aaabbb"
What is the explanation of this discrepancy?