A confusing title for a confusing question! I understand a) monads, b) the IO monad, c) the Cont monad (Control.Monad.Cont), and d) the ContT continuation transformer monad. (And I vaguely understand monad transformers in general -- though not enough to answer this question.) I understand how to write a program where all the functions are in the Cont monad (Cont r a), and I understand how to write a program where all the functions are in the combined Cont/IO monad (ContT r IO a).
But I'm wondering how I might write a program where some functions are in a combined Cont/IO monad (ContT r IO a) and other functions are just in the Cont monad (Cont r a). Basically, I want to write the whole program in continuation style, but only use the IO monad where necessary (much like in "regular" Haskell code, I only use the IO monad where necessary).
For example consider these two functions, in non-continuation style:
foo :: Int -> IO Int
foo n = do
let x = n + 1
print x
return $ bar x
bar :: Int -> Int
bar m = m * 2
Note that foo requires IO but bar is pure. Now I figured out how to write this code fully using the continuation monad, but I needed to thread IO through bar as well:
foo :: Int -> ContT r IO Int
foo n = do
let x = n + 1
liftIO $ print x
bar x
bar :: Int -> ContT r IO Int
bar m = return $ m * 2
I do want all my code in continuation style, but I don't want to have to use the IO monad on functions that don't require it. Basically, I would like to define bar like this:
bar :: Int -> Cont r Int
bar m = return $ m * 2
Unfortunately, I can't find a way to call a Cont r a monad function (bar) from inside a ContT r IO a monad function (foo). Is there any way to "lift" a non-transformed monad into a transformed one? i.e., how can I change the line "bar x" in foo so that it can correctly call bar :: Int -> Cont r Int?