content: -- |Functions for working with 'Topic's built around monad
  -- transformers. These make it possible to, for example, repeat a
  -- stateful action to produce a 'Topic''s values.
  module Ros.Topic.Transformers where
  import Control.Arrow
  import qualified Control.Monad.State.Lazy as L
  import qualified Control.Monad.State.Strict as S
  import Control.Monad.Reader
  import Ros.Topic
  
  -- |Run a 'Topic' built around a lazy @'L.StateT' s@ monad using a
  -- given initial state.
  runTopicState :: Monad m => Topic (L.StateT s m) a -> s -> Topic m a
  runTopicState t s = Topic $ do ((x,t'), s') <- L.runStateT (runTopic t) s
                                 return (x, runTopicState t' s')
  
  -- |Run a 'Topic' build around a strict @'S.StateT' s@ monad using a
  -- given initial state.
  runTopicState' :: Monad m => Topic (S.StateT s m) a -> s -> Topic m a
  runTopicState' t s = Topic $ do ((x,t'), s') <- S.runStateT (runTopic t) s
                                  return (x, runTopicState' t' s')
  
  -- |Run a 'Topic' built around a 'ReaderT r' monad using a value for
  -- reading.
  runTopicReader :: (Functor m, Monad m) => Topic (ReaderT r m) a -> r -> Topic m a
  runTopicReader t r = go t
    where go (Topic ma) = Topic $ second go `fmap` runReaderT ma r
  
  -- |Map a monadic function over a 'Topic', in the process lifting the
  -- 'Topic' into a new monad.
  liftMap :: (MonadTrans t, Monad m, Monad (t m)) => 
             (a -> t m b) -> Topic m a -> Topic (t m) b
  liftMap f = go
    where go (Topic ma) = Topic $ do (x,t') <- lift ma
                                     x' <- f x
                                     return (x', go t')
  