[Haskell-cafe] Control.Monad.Cont fun

Tomasz Zielonka tomasz.zielonka at gmail.com
Thu Jul 7 13:08:23 EDT 2005


Hello!

Some time ago I wanted to return the escape continuation out of the
callCC block, like this:

  getCC = callCC (\c -> return c)

But of course this wouldn't compile.

I thought that it would be useful to be able to keep the current
continuation and resume it later, like you can in do in scheme. Well,
it was easy to do this in Haskell in the (ContT r IO) monad, by using an
IORef. But I wasn't able to solve this for all MonadCont monads.

After more then year of on-and-off trials, I've finally managed to do
this! ;-)

  import Control.Monad.Cont

  getCC :: MonadCont m => m (m a)
  getCC = callCC (\c -> let x = c x in return x)

  getCC' :: MonadCont m => a -> m (a, a -> m b)
  getCC' x0 = callCC (\c -> let f x = c (x, f) in return (x0, f))

getCC allows to set a backward "goto label". Here's an example:

  -- prints "hello!" in an endless loop
  test :: IO ()
  test = (`runContT` return) $ do
      jump <- getCC
      lift (putStrLn "hello!")
      jump

getCC' allows to jump back with arguments:

  -- prints integers from 0 to 10, then prints finish and ends
  test' :: IO ()
  test' = (`runContT` return) $ do
      (x, jumpWith) <- getCC' 0
      lift (print x)
      when (x < 10) (jumpWith (x + 1))
      lift (putStrLn "finish")

I think this is rather cool! :-)

Besides sharing my happiness, I want to ask some questions:

- what would be the best names for these functions

- is it possible to define a MonadFix instance for Cont / ContT?

- do you think it would be a good idea to add them to
  Control.Monad.Cont?

Best regards
Tomasz


More information about the Haskell-Cafe mailing list