Bryan
Bryan

Reputation: 193

Is this an appropriate use of ContT?

I'm working on a project that requires me to write a small interpreter. The instructions have a simple tree structure and one of the commands has the effect of halting execution. So in the example below, "baz" is never printed.

import Control.Monad.Cont

data Instruction = Print String | Halt | Block [Instruction]
    deriving (Eq, Show)

instructions =
  [ Print "foo"
  , Block
    [ Print "bar"
    , Halt
    ]
  , Print "baz"
  ]

main :: IO ()
main = runContT (callCC $ interpret instructions)
                (const $ pure ())

interpret []     k = pure ()
interpret (a:as) k = case a of
    Print str -> liftIO (putStrLn str) >> interpret as k
    Block ins -> interpret ins k       >> interpret as k
    Halt      -> k ()

This is the first time I've seen a potential use for ContT in one of my projects. I was wondering if this is an appropriate use of it or if there is a simpler solution I might be overlooking.

Upvotes: 7

Views: 1737

Answers (1)

liminalisht
liminalisht

Reputation: 1253

Yes, this looks to be precisely the sort of use case for which Control.Monad.Cont is appropriate.

You are almost certainly aware of this, but for other readers, it's worth spelling out that if you'd written interpret so that it was a function from a list of instructions to an IO () like so:

main :: IO ()
main = interpret instructions

interpret :: [Instruction] -> IO ()
interpret []     = pure ()
interpret (a:as) = case a of
    Print str -> putStrLn str >> interpret as
    Block ins -> interpret ins >> interpret as
    Halt      -> pure ()

then foo bar and baz all would have printed. What you needed was an escape mechanism that would allow you to abort the entire computation and immediately return a value. This is precisely what callCC provides. Calling the named computation (k in your code) allows you to escape out of the whole computation, not just that level/layer.

So good job, you've found precisely the appropriate use case for ContT here, I believe.

Upvotes: 8

Related Questions