------------------------------------------------------------------------------- |-- Module : Control.Monad.Trans.State.Strict-- Copyright : (c) Andy Gill 2001,-- (c) Oregon Graduate Institute of Science and Technology, 2001-- License : BSD-style (see the file libraries/base/LICENSE)---- Maintainer : libraries@haskell.org-- Stability : experimental-- Portability : portable---- Strict state monads.---- This module is inspired by the paper-- /Functional Programming with Overloading and-- Higher-Order Polymorphism/,-- Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)-- Advanced School of Functional Programming, 1995.---- See below for examples.-----------------------------------------------------------------------------moduleControl.Monad.Trans.State.Strict(-- * The State monadState,state,runState,evalState,execState,mapState,withState,-- * The StateT monad transformerStateT(..),evalStateT,execStateT,mapStateT,withStateT,-- * State operationsget,put,modify,gets,-- * Lifting other operationsliftCallCC,liftCallCC',liftCatch,liftListen,liftPass,)whereimportControl.ApplicativeimportControl.MonadimportControl.Monad.FiximportControl.Monad.IdentityimportControl.Monad.Trans-- ----------------------------------------------------------------------------- | A parameterizable state monad where /s/ is the type of the state-- to carry and /a/ is the type of the /return value/.typeStates=StateTsIdentitystate::(s->(a,s))->Statesastatef=StateT(Identity.f)runState::Statesa->s->(a,s)runStatem=runIdentity.runStateTm-- |Evaluate this state monad with the given initial state,throwing-- away the final state. Very much like @fst@ composed with-- @runstate@.evalState::Statesa-- ^The state to evaluate->s-- ^An initial value->a-- ^The return value of the state applicationevalStatems=fst(runStatems)-- |Execute this state and return the new state, throwing away the-- return value. Very much like @snd@ composed with-- @runstate@.execState::Statesa-- ^The state to evaluate->s-- ^An initial value->s-- ^The new stateexecStatems=snd(runStatems)-- |Map a stateful computation from one (return value, state) pair to-- another. For instance, to convert numberTree from a function that-- returns a tree to a function that returns the sum of the numbered-- tree (see the Examples section for numberTree and sumTree) you may-- write:---- > sumNumberedTree :: (Eq a) => Tree a -> State (Table a) Int-- > sumNumberedTree = mapState (\ (t, tab) -> (sumTree t, tab)) . numberTreemapState::((a,s)->(b,s))->Statesa->StatesbmapStatef=mapStateT(Identity.f.runIdentity)-- |Apply this function to this state and return the resulting state.withState::(s->s)->Statesa->StatesawithState=withStateT-- ----------------------------------------------------------------------------- | A parameterizable state monad for encapsulating an inner-- monad.---- The StateT Monad structure is parameterized over two things:---- * s - The state.---- * 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 Identity 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))newtypeStateTsma=StateT{runStateT::s->m(a,s)}-- |Similar to 'evalState'evalStateT::(Monadm)=>StateTsma->s->maevalStateTms=do(a,_)<-runStateTmsreturna-- |Similar to 'execState'execStateT::(Monadm)=>StateTsma->s->msexecStateTms=do(_,s')<-runStateTmsreturns'-- |Similar to 'mapState'mapStateT::(m(a,s)->n(b,s))->StateTsma->StateTsnbmapStateTfm=StateT$f.runStateTm-- |Similar to 'withState'withStateT::(s->s)->StateTsma->StateTsmawithStateTfm=StateT$runStateTm.finstance(Functorm)=>Functor(StateTsm)wherefmapfm=StateT$\s->fmap(\(a,s')->(fa,s'))$runStateTmsinstance(Functorm,Monadm)=>Applicative(StateTsm)wherepure=return(<*>)=apinstance(Functorm,MonadPlusm)=>Alternative(StateTsm)whereempty=mzero(<|>)=mplusinstance(Monadm)=>Monad(StateTsm)wherereturna=StateT$\s->return(a,s)m>>=k=StateT$\s->do(a,s')<-runStateTmsrunStateT(ka)s'failstr=StateT$\_->failstrinstance(MonadPlusm)=>MonadPlus(StateTsm)wheremzero=StateT$\_->mzerom`mplus`n=StateT$\s->runStateTms`mplus`runStateTnsinstance(MonadFixm)=>MonadFix(StateTsm)wheremfixf=StateT$\s->mfix$\~(a,_)->runStateT(fa)sinstanceMonadTrans(StateTs)whereliftm=StateT$\s->doa<-mreturn(a,s)instance(MonadIOm)=>MonadIO(StateTsm)whereliftIO=lift.liftIOget::(Monadm)=>StateTsmsget=StateT$\s->return(s,s)put::(Monadm)=>s->StateTsm()puts=StateT$\_->return((),s)-- | Monadic state transformer.---- Maps an old state to a new state inside a state monad.-- The old state is thrown away.modify::(Monadm)=>(s->s)->StateTsm()modifyf=dos<-getput(fs)-- | Gets specific component of the state, using a projection function-- supplied.gets::(Monadm)=>(s->a)->StateTsmagetsf=dos<-getreturn(fs)-- | Uniform lifting of a @callCC@ operation to the new monad.-- This version rolls back to the original state on entering the-- continuation.liftCallCC::((((a,s)->m(b,s))->m(a,s))->m(a,s))->((a->StateTsmb)->StateTsma)->StateTsmaliftCallCCcallCCf=StateT$\s->callCC$\c->runStateT(f(\a->StateT$\_->c(a,s)))s-- | In-situ lifting of a @callCC@ operation to the new monad.-- This version uses the current state on entering the continuation.liftCallCC'::((((a,s)->m(b,s))->m(a,s))->m(a,s))->((a->StateTsmb)->StateTsma)->StateTsmaliftCallCC'callCCf=StateT$\s->callCC$\c->runStateT(f(\a->StateT$\s'->c(a,s')))s-- | Lift a @catchError@ operation to the new monad.liftCatch::(m(a,s)->(e->m(a,s))->m(a,s))->StateTsma->(e->StateTsma)->StateTsmaliftCatchcatchErrormh=StateT$\s->runStateTms`catchError`\e->runStateT(he)s-- | Lift a @listen@ operation to the new monad.liftListen::Monadm=>(m(a,s)->m((a,s),w))->StateTsma->StateTsm(a,w)liftListenlistenm=StateT$\s->do((a,s'),w)<-listen(runStateTms)return((a,w),s')-- | Lift a @pass@ operation to the new monad.liftPass::Monadm=>(m((a,s),b)->m(a,s))->StateTsm(a,b)->StateTsmaliftPasspassm=StateT$\s->pass$do((a,f),s')<-runStateTmsreturn((a,s'),f)