
On Sun, Aug 23, 2009 at 9:14 AM, Levi
Greenspan
Many thanks Jeremy. Your explanations are indeed very helpful. But they also strengthen my gut feeling that running two threads in the same M monad is hard (if not impossible) to do.
I think here is where you are going wrong; there is no "same M monad". Perhaps it will help if you saw how ReaderT works: newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a } That gives you these two functions: ReaderT :: (r -> m a) -> ReaderT r m a runReaderT :: ReaderT r m a -> r -> m a There's nothing magic about it; ReaderT just wraps up a function and provides "bind" and "return" so that you can glue actions together: (>>=) :: Monad m => ReaderT r m a -> (a -> ReaderT r m b) -> ReaderT r m b ma >>= f = ReaderT $ \r -> do a <- runReaderT ma r let mb = f a b <- runReaderT mb r return b (of course the code is written more concisely than this, but I am trying to help make it explicit) So internally *every* bind has multiple "runM"s inside of it, magically whipped up by the compiler inside of "deriving Monad". When you do "runM" explicitly here, you are just helping to lift "forkIO" back into your monad. -- ryan