import Control.Monad.Trans.Cont import Control.Monad.Trans import Control.Monad(void) data Val = MkVal data RetC = MkRetC data Other = MkOther needsCallback :: (Val -> IO RetC) -> IO RetC needsCallback cb = cb MkVal returnsValM :: ContT RetC IO Val returnsValM = ContT needsCallback usesValM :: ContT RetC IO Other usesValM = do val <- returnsValM lift $ putStrLn "i am using Val as if it were a value" seq val $ pure MkOther -- here you can put anything that uses your Val value -- the seq is just to show that we can force the val as if we had it callbackM :: Other -> IO RetC callbackM MkOther = pure MkRetC main :: IO () main = do putStrLn "before needsCallback" void $ runContT usesValM callbackM putStrLn "after needsCallback"