Search code examples
haskelltypescontinuationscoroutinecontinuation-passing

Is there a way to capture the continuations in a do notation?


Since the following do block:

do
  x <- foo
  y <- bar
  return x + y

is desugared to the following form:

foo >>= (\x -> bar >>= (\y -> return x + y))

aren't \x -> ... and y -> ... actually continuations here?

I was wondering if there is a way to capture the continuations in the definition of bind, but I can't get the types right. I.e:

data Pause a = Pause a | Stop

instance Monad Pause where
  return x = Stop
  m >>= k = Pause k         -- this doesn't work of course

Now I tried muddling around with the types:

data Pause a = Pause a (a -> Pause ???) | Stop
                       ------- k ------

But this doesn't work either. Is there no way to capture these implicit continuations?

Btw, I know about the Cont monad, I'm just experimenting and trying out stuff.


Solution

  • OK I'm not really sure, but let me put a few thoughts. I'm not quite sure what it ought to mean to capture the continuation. You could, for example, capture the whole do block in a structure:

    {-# LANGUAGE ExistentialQuantification #-}
    
    import Control.Monad
    
    data MonadExp b = Return b | forall a. Bind (MonadExp a) (a -> MonadExp b)
    
    instance Monad MonadExp where
        return x = Return x
        f >>= g = Bind f g
    

    For example:

    block :: MonadExp Int
    block = do
        x <- return 1
        y <- return 2
        return $ x + y
    
    instance Show (MonadExp a) where
        show (Return _) = "Return _"
        show (Bind _ _) = "Bind _ _"
    
    print block
    >> Bind _ _
    

    And then evaluate the whole thing:

    finish :: MonadExp a -> a
    finish (Return x) = x
    finish (Bind f g) = finish $ g (finish f)
    
    print $ finish block
    >> 3
    

    Or step through it and see the parts

    step :: MonadExp a -> MonadExp a
    step (Return _) = error "At the end"
    step (Bind f g) = g $ finish f
    
    print $ step block
    >> Bind _ _
    print $ step $ step block
    >> Return _
    

    Well, now that I think about it more, that's probably not what you're asking. But maybe it'll help you think.