{-- A state monad transformer like that described in Mark P. Jones's article in Jeuring/Meijers (Eds.): "Advanced Functional Programming...", Berlin/Heidelberg 1995 --} module STM where import MonadT {-- s :: state, m a : monad to be composed --} data STM s m a = STM (s -> m (a,s)) instance Monad m => Functor (STM s m) where fmap f (STM transform) = STM (\state -> do (x,state') <- transform state return (f x, state')) instance Monad m => Monad (STM s m) where (STM transform) >>= f = STM (\state -> do (x,state') <- transform state let (STM transform') = f x transform' state') return x = STM (\state -> return (x,state)) instance MonadT (STM s) where lift op = STM (\state -> do result <- op return (result,state)) start = run (error "attempt to access unitialized STM state") {-- applies first argument to state and returns new state. --} modify :: Monad m => (a -> a) -> STM a m a modify f = STM (\state -> return (state,f state)) {-- perform calculation of the STM in the embedded monad m a, using state 'state' as initial state. --} run :: Monad m => s -> STM s m a -> m a run state (STM transform) = do result <- transform state return (fst result)