{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE DeriveDataTypeable #-} {- | Handling monad transformers. -} module LiveCoding.Cell.Monad.Trans where -- base import Control.Arrow (arr, (>>>)) import Data.Data (Data) -- transformers import Control.Monad.Trans.Reader (runReaderT, ReaderT) import Control.Monad.Trans.State.Strict (StateT (..), runStateT, evalStateT) import Control.Monad.Trans.Writer.Strict -- essence-of-live-coding import LiveCoding.Cell import LiveCoding.Cell.Monad -- | Push effectful state into the internal state of a cell runStateC :: (Data stateT, Monad m) => Cell (StateT stateT m) a b -- ^ A cell with a state effect -> stateT -- ^ The initial state -> Cell m a (b, stateT) -- ^ The cell, returning its current state runStateC cell stateT = hoistCellKleisliStateChange morph init cell where morph step State { .. } a = do ((b, stateInternal), stateT) <- runStateT (step stateInternal a) stateT return ((b, stateT), State { .. }) init stateInternal = State { .. } -- | Like 'runStateC', but does not return the current state. runStateC_ :: (Data stateT, Monad m) => Cell (StateT stateT m) a b -- ^ A cell with a state effect -> stateT -- ^ The initial state -> Cell m a b runStateC_ cell stateT = runStateC cell stateT >>> arr fst -- | The internal state of a cell to which 'runStateC' or 'runStateL' has been applied. data State stateT stateInternal = State { stateT :: stateT , stateInternal :: stateInternal } deriving (Data, Eq, Show) -- | Supply a 'ReaderT' environment before running the cell runReaderC :: r -> Cell (ReaderT r m) a b -> Cell m a b runReaderC r = hoistCell $ flip runReaderT r -- | Supply a 'ReaderT' environment live runReaderC' :: Monad m => Cell (ReaderT r m) a b -> Cell m (r, a) b runReaderC' = hoistCellKleisli_ $ \action (r, a) -> runReaderT (action a) r -- | Run the effects of the 'WriterT' monad, -- collecting all its output in the second element of the tuple. runWriterC :: (Monoid w, Monad m) => Cell (WriterT w m) a b -> Cell m a (w, b) runWriterC = hoistCellOutput $ fmap reorder . runWriterT where reorder ((b, s), w) = ((w, b), s)