prob-fx-0.1.0.2: src/Effects/State.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{- | 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 the current state
Get :: State s s
-- | Set the current state
Put :: s -> State s ()
-- | Wrapper function for @Get@
get :: Member (State s) es => Prog es s
get = Op (inj Get) Val
-- | Wrapper function for @Set@
put :: (Member (State s) es) => s -> Prog es ()
put s = Op (inj $ Put s) Val
-- | Wrapper function for 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
-> Prog (State s ': es) a
-- | (output, 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)