2020-05-18 15:59:07 +03:00
|
|
|
module Control.Monad.State
|
|
|
|
|
|
|
|
import public Control.Monad.Identity
|
|
|
|
import public Control.Monad.Trans
|
|
|
|
|
|
|
|
||| A computation which runs in a context and produces an output
|
|
|
|
public export
|
2020-12-11 14:58:26 +03:00
|
|
|
interface Monad m => MonadState stateType m | m where
|
2020-05-18 15:59:07 +03:00
|
|
|
||| Get the context
|
|
|
|
get : m stateType
|
|
|
|
||| Write a new context/output
|
|
|
|
put : stateType -> m ()
|
|
|
|
|
|
|
|
||| The transformer on which the State monad is based
|
|
|
|
public export
|
|
|
|
record StateT (stateType : Type) (m : Type -> Type) (a : Type) where
|
|
|
|
constructor ST
|
2020-09-15 07:30:49 +03:00
|
|
|
runStateT' : stateType -> m (stateType, a)
|
2020-05-18 15:59:07 +03:00
|
|
|
|
|
|
|
public export
|
|
|
|
implementation Functor f => Functor (StateT stateType f) where
|
2020-09-15 06:31:28 +03:00
|
|
|
map f (ST g) = ST (\st => map (map f) (g st)) where
|
2020-05-18 15:59:07 +03:00
|
|
|
|
|
|
|
public export
|
|
|
|
implementation Monad f => Applicative (StateT stateType f) where
|
2020-09-15 06:31:28 +03:00
|
|
|
pure x = ST (\st => pure (st, x))
|
2020-05-18 15:59:07 +03:00
|
|
|
|
|
|
|
(ST f) <*> (ST a)
|
|
|
|
= ST (\st =>
|
2020-09-15 06:31:28 +03:00
|
|
|
do (r, g) <- f st
|
|
|
|
(t, b) <- a r
|
|
|
|
pure (t, g b))
|
2020-05-18 15:59:07 +03:00
|
|
|
|
|
|
|
public export
|
|
|
|
implementation Monad m => Monad (StateT stateType m) where
|
|
|
|
(ST f) >>= k
|
|
|
|
= ST (\st =>
|
2020-09-15 06:31:28 +03:00
|
|
|
do (st', v) <- f st
|
2020-05-18 15:59:07 +03:00
|
|
|
let ST kv = k v
|
|
|
|
kv st')
|
|
|
|
|
|
|
|
public export
|
|
|
|
implementation Monad m => MonadState stateType (StateT stateType m) where
|
|
|
|
get = ST (\x => pure (x, x))
|
2020-09-15 06:31:28 +03:00
|
|
|
put x = ST (\y => pure (x, ()))
|
2020-05-18 15:59:07 +03:00
|
|
|
|
|
|
|
public export
|
|
|
|
implementation MonadTrans (StateT stateType) where
|
|
|
|
lift x
|
|
|
|
= ST (\st =>
|
|
|
|
do r <- x
|
2020-09-15 06:31:28 +03:00
|
|
|
pure (st, r))
|
2020-05-18 15:59:07 +03:00
|
|
|
|
|
|
|
public export
|
|
|
|
implementation (Monad f, Alternative f) => Alternative (StateT st f) where
|
|
|
|
empty = lift empty
|
|
|
|
(ST f) <|> (ST g) = ST (\st => f st <|> g st)
|
|
|
|
|
2020-08-05 00:19:45 +03:00
|
|
|
public export
|
|
|
|
implementation HasIO m => HasIO (StateT stateType m) where
|
2020-09-15 06:31:28 +03:00
|
|
|
liftIO io = ST $ \s => liftIO $ io_bind io $ \a => pure (s, a)
|
2020-08-05 00:19:45 +03:00
|
|
|
|
2020-05-18 15:59:07 +03:00
|
|
|
||| Apply a function to modify the context of this computation
|
|
|
|
public export
|
|
|
|
modify : MonadState stateType m => (stateType -> stateType) -> m ()
|
|
|
|
modify f
|
|
|
|
= do s <- get
|
|
|
|
put (f s)
|
|
|
|
|
|
|
|
||| Evaluate a function in the context held by this computation
|
|
|
|
public export
|
|
|
|
gets : MonadState stateType m => (stateType -> a) -> m a
|
|
|
|
gets f
|
|
|
|
= do s <- get
|
|
|
|
pure (f s)
|
|
|
|
|
2020-09-15 07:30:49 +03:00
|
|
|
||| Unwrap and apply a StateT monad computation.
|
|
|
|
public export
|
|
|
|
%inline
|
|
|
|
runStateT : stateType -> StateT stateType m a -> m (stateType, a)
|
|
|
|
runStateT s act = runStateT' act s
|
|
|
|
|
2020-12-17 04:28:08 +03:00
|
|
|
||| Unwrap and apply a StateT monad computation, but discard the final state.
|
|
|
|
public export
|
|
|
|
evalStateT : Functor m => stateType -> StateT stateType m a -> m a
|
|
|
|
evalStateT s = map snd . runStateT s
|
|
|
|
|
|
|
|
||| Unwrap and apply a StateT monad computation, but discard the resulting value.
|
|
|
|
public export
|
|
|
|
execStateT : Functor m => stateType -> StateT stateType m a -> m stateType
|
|
|
|
execStateT s = map fst . runStateT s
|
|
|
|
|
2020-05-18 15:59:07 +03:00
|
|
|
||| The State monad. See the MonadState interface
|
|
|
|
public export
|
|
|
|
State : (stateType : Type) -> (ty : Type) -> Type
|
|
|
|
State = \s, a => StateT s Identity a
|
|
|
|
|
2020-09-15 07:30:49 +03:00
|
|
|
||| Unwrap and apply a State monad computation.
|
2020-05-18 15:59:07 +03:00
|
|
|
public export
|
2020-12-17 04:31:56 +03:00
|
|
|
runState : stateType -> State stateType a -> (stateType, a)
|
2020-09-15 07:30:49 +03:00
|
|
|
runState s act = runIdentity (runStateT s act)
|
2020-05-18 15:59:07 +03:00
|
|
|
|
2020-09-15 07:30:49 +03:00
|
|
|
||| Unwrap and apply a State monad computation, but discard the final state.
|
2020-05-18 15:59:07 +03:00
|
|
|
public export
|
2020-09-15 07:30:49 +03:00
|
|
|
evalState : stateType -> State stateType a -> a
|
|
|
|
evalState s = snd . runState s
|
2020-05-18 15:59:07 +03:00
|
|
|
|
2020-09-15 07:30:49 +03:00
|
|
|
||| Unwrap and apply a State monad computation, but discard the resulting value.
|
2020-05-18 15:59:07 +03:00
|
|
|
public export
|
2020-09-15 07:30:49 +03:00
|
|
|
execState : stateType -> State stateType a -> stateType
|
|
|
|
execState s = fst . runState s
|