prob-fx-0.1.0.0: src/Effects/State.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{- | The state effect
-}
module Effects.State (
State(..)
, get
, put
, modify
, handleState) where
import Prog ( discharge, Member(inj), Prog(..) )
-- | The state effect
data State s a where
Get :: State s s
Put :: s -> State s ()
-- | Get the state
get :: (Member (State s) es) => Prog es s
get = Op (inj Get) Val
-- | Set the state
put :: (Member (State s) es) => s -> Prog es ()
put s = Op (inj $ Put s) Val
-- | Apply a function to the state
modify :: Member (State s) es => (s -> s) -> Prog es ()
modify f = get >>= put . f
-- | Handle the @State s@ effect
handleState ::
-- | Initial state
s
-- | Initial program
-> Prog (State s ': es) a
-- | Pure value and final state
-> Prog es (a, s)
handleState s m = loop s m where
loop :: s -> Prog (State s ': es) a -> Prog es (a, s)
loop s (Val x) = return (x, s)
loop s (Op u k) = case discharge u of
Right Get -> loop s (k s)
Right (Put s') -> loop s' (k ())
Left u' -> Op u' (loop s . k)