MonadState

MonadState 0.1 alpha The contents of this module are understood to be a straightforward implementation of part of the fokelore of the functional programming community, and therefore the contents are in the public domain. Rendered by Andy Gill, based on the paper Functional Programming with Overloading and Higher-Order Polymorphism, Mark P Jones, Advanced School of Functional Programming, 1995. This requires multi parameter classes and functional dependencies. Hugs98
> module MonadState ( > MonadState(..), > modify, > State, -- abstract > runState, > mapState, > evalState, > execState, > StateT, -- abstract > runStateT, > mapStateT, > evalStateT, > execStateT, > module MonadTrans > ) where > import Monad > import MonadTrans MonadState {- - This class has two functions. - get : returns the state from the internals of the monad, - put : changes the state inside the monad. -} > class (Monad m) => MonadState s m where > get :: m s > put :: s -> m () Monadic state transformer. Maps an old state to a new state inside a state monad. The old state is thrown away. Main> :t modify ((+1) :: Int -> Int) modify (...) :: (MonadState Int a) => a ()

This says that modify (+1) acts over any Monad that is a member of the MonadState class, with an Int state.

> modify :: (MonadState s m) => (s -> s) -> m () > modify f = do s <- get > put (f s) ------------------------------------------------------------------------------ {- Our parameterizable state monad -} > newtype State s a = State { runState :: s -> (a,s) } {- - The State Monad structure is paramterized over just the state: - -} > instance Functor (State s) where > fmap f p = State (\ s -> > let (x,s') = runState p s > in (f x,s')) > instance Monad (State s) where > return v = State (\ s -> (v,s)) > p >>= f = State (\ s -> let (r,s') = runState p s > in runState (f r) s') > fail str = State (\ s -> error str) > instance MonadState s (State s) where > get = State (\ s -> (s,s)) > put v = State (\ _ -> ((),v)) > mapState :: ((a,s) -> (b,s)) -> State s a -> State s b > mapState f m = State (f . runState m) > evalState :: State s a -> s -> a > evalState m s = fst (runState m s) > execState :: State s a -> s -> s > execState m s = snd (runState m s) ------------------------------------------------------------------------------ {- Our parameterizable state monad, with an inner monad -} > newtype StateT s m a = StateT { runStateT :: s -> m (a,s) } {- - The StateT Monad structure is paramterized over two things: - s: The State itself. - m: The inner monad. - - Here are some examples of use: - - (Parser from ParseLib with Hugs) - type Parser a = StateT String [] a - ==> StateT (String -> [(a,String)]) - For example, item can be written as: - item = do (x:xs) <- get - put xs - return x - - type BoringState s a = StateT s Indentity a - ==> StateT (s -> Identity (a,s)) - - type StateWithIO s a = StateT s IO a - ==> StateT (s -> IO (a,s)) - - type StateWithErr s a = StateT s Maybe a - ==> StateT (s -> Maybe (a,s)) -} > instance (Monad m) => Functor (StateT s m) where > -- fmap :: (a -> b) -> StateT s m a -> StateT s m b > fmap f p = StateT (\ s -> > do (x,s') <- runStateT p s > return (f x,s')) > > instance (Monad m) => Monad (StateT s m) where > return v = StateT (\ s -> return (v,s)) > p >>= f = StateT (\ s -> do (r,s') <- runStateT p s > runStateT (f r) s') > fail str = StateT (\ s -> fail str) > > instance (MonadPlus m) => MonadPlus (StateT s m) where > mzero = StateT (\ s -> mzero) > p `mplus` q = StateT (\ s -> runStateT p s `mplus` runStateT q s) > > instance (Monad m) => MonadState s (StateT s m) where > get = StateT (\ s -> return (s,s)) > put v = StateT (\ _ -> return ((),v)) > > instance MonadTrans (StateT s) where > lift f = StateT ( \ s -> do { r <- f ; runStateT (return r) s }) > mapStateT :: (m (a,s) -> n (b,s)) -> StateT s m a -> StateT s n b > mapStateT f m = StateT (f . runStateT m) > > evalStateT :: (Monad m) => StateT s m a -> s -> m a > evalStateT m s = > do (r,_) <- runStateT m s > return r > > execStateT :: (Monad m) => StateT s m a -> s -> m s > execStateT m s = > do (_,s) <- runStateT m s > return s ------------------------------------------------------------------------------