Monads can do many amazing, crazy things. They can create variables which hold a superposition of values. They can allow you to access data from the future before you comput
{-# LANGUAGE TupleSections #-}
newtype Pause s x = Pause (s -> (s, Either x (Pause s x)))
instance Monad (Pause s) where
return x = Pause (, Left x)
Pause k >>= f = Pause $ \s -> let (s', v) = k s in
case v of
Left x -> step (f x) s'
Right x -> (s', Right (x >>= f))
mutate :: (s -> s) -> Pause s ()
mutate f = Pause (\s -> (f s, Left ()))
yield :: Pause s ()
yield = Pause (, Right (return ()))
step :: Pause s x -> s -> (s, Either x (Pause s x))
step (Pause x) = x
That's how I would wrote this. I gave step
a bit more general definition, it could be as well named runPause
. In fact thinking about type of step
lead me to definition of Pause
.
In the monad-coroutine package you will find a general monad transformer. The Pause s
monad is the same as Coroutine (State s) Id
. You can combine coroutines with other monads.
Related: the Prompt monad in http://themonadreader.files.wordpress.com/2010/01/issue15.pdf