Created
April 25, 2013 01:31
-
-
Save stesh/5456884 to your computer and use it in GitHub Desktop.
The State transformer monad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- State transformer monad -- | |
| -- | |
| -- 1. Typeclass MonadState, declaring stateful operations | |
| -- 2. A datatype to work with | |
| -- 3. An implementation of Monad | |
| -- 4. An implementation of MonadTrans | |
| -- 5. An implementation of MonadState | |
| -- 6. The State Monad for free, by transforming Identity | |
| class (Monad m) => MonadState s m | m -> s where | |
| -- get the current state out of the monad | |
| get :: m s | |
| -- insert a new state into the monad | |
| put :: s -> m () | |
| newtype StateT s m a = StateT { | |
| -- s: the initial state | |
| -- m: the inner monad | |
| -- Make rocket go now. | |
| runStateT :: s -> m (a, s) | |
| } | |
| instance (Monad m) => Monad (StateT s m) where | |
| -- RHS `return` is the inner monad's return | |
| return a = StateT $ \s -> return (a, s) | |
| m >>= k = StateT $ \s -> do | |
| -- Obtain the new value and state from m, given current state s | |
| (a, s') <- runStateT m s | |
| -- k $ a does the binding | |
| -- thread the new state s' into the continuation | |
| runStateT (k a) s' | |
| instance (Monad m) => MonadTrans (StateT s m) where | |
| -- to lift an inner monadic action into this monad, | |
| -- perform it in the inner monad, and leave the state | |
| -- untouched. | |
| lift m = StateT $ \s -> do | |
| a <- m | |
| return (a, s) | |
| instance (Monad m) => MonadState (StateT s m) where | |
| -- return a StateT step which happens to have the current state as its | |
| -- value, and which doesn't modify the current state in the process | |
| get = StateT $ \s -> return (s, s) | |
| -- return a StateT step which, no matter what the current state is, | |
| -- overwrites it with the given state. | |
| put s = StateT $ \_ -> return ((), s) | |
| newtype Identity a = Identity { | |
| runIdentity :: a | |
| } | |
| instance Monad Identity where | |
| return a = Identity a | |
| m >>= k = k $ runIdentity m | |
| type State s = StateT s Identity |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment