0

I have a simple continuation type (similar to the Free monad):

data C m a = C {runC :: (a -> m a) -> m a}

toBeContinued :: Int -> C Maybe Int
toBeContinued i = C $ \todo -> todo i

continuing :: Int -> Maybe Int
continuing i = Just 100

I'm then looking to create two interleaved threads of these suspended continuations, all of which to be executed using the same continuing function:

data PoorMans m a = Atomic (m (PoorMans m a)) | Done a

instance Monad m => Monad (PoorMans m) where
  (>>=) (Atomic m) f = Atomic $ (liftM (>>= f) m)
  (>>=) (Done m) f = f m
  return  = Done

atomic :: Monad m => m a -> PoorMans m a
atomic m = Atomic $ liftM Done m

runThread :: Monad m => m a -> PoorMans m a
runThread (Atomic m) = m >>= runThread
runThread (Done m) = return m

interleave :: Monad m => PoorMans m a -> PoorMans m a -> PoorMans m a
interleave (Atomic m1) (Atomic m2) = do
    n1 <- m1
    n2 <- m2
    interleave n1 n2
interleave (Done _) m2 = m2
interleave m1 (Done _) = m1

I'm now trying to create two threads of suspended operations, which I can then pass to interleave then into runThread with a continuation operation to be applied to all suspended operations:

createSuspendedOperations :: Int -> PoorMans (C Maybe) Int
createSuspendedOperations i = atomic $ toBeContinued 12

Error:

 No instance for (Monad (C Maybe))
    arising from a use of ‘atomic’

I understand that I must make C an instance of Monad as atomic is bound by Monad m =>:

 instance Monad m => Monad (C m) where

However here I am stuck as to how to define the behaviors of >>= and return for C m a?

Babra Cunningham
  • 2,949
  • 1
  • 23
  • 50

1 Answers1

1

There's no way this is a monad, because a is an invariant parameter of C m a. (Here is an FPComplete post about variance.)

You might want to take a look at the "continuation monad" in transformers.

Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56