{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
module Control.Program.State
(
State(..)
, get
, put
, modify
, modify'
, newState
, modifyState
, modifyState'
) where
import Data.IORef (newIORef, readIORef, writeIORef)
import Control.Program (Has, Program, pullWith)
data State s = State
{ State s -> IO s
readState :: IO s
, State s -> s -> IO ()
writeState :: s -> IO ()
}
newState :: s -> IO (State s)
newState :: s -> IO (State s)
newState s
s = do
IORef s
ref <- s -> IO (IORef s)
forall a. a -> IO (IORef a)
newIORef s
s
State s -> IO (State s)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (State s -> IO (State s)) -> State s -> IO (State s)
forall a b. (a -> b) -> a -> b
$
State :: forall s. IO s -> (s -> IO ()) -> State s
State
{ readState :: IO s
readState = IORef s -> IO s
forall a. IORef a -> IO a
readIORef IORef s
ref
, writeState :: s -> IO ()
writeState = IORef s -> s -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef s
ref
}
modifyState :: State s -> (s -> s) -> IO ()
modifyState :: State s -> (s -> s) -> IO ()
modifyState State s
state s -> s
f =
State s -> IO s
forall s. State s -> IO s
readState State s
state IO s -> (s -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= State s -> s -> IO ()
forall s. State s -> s -> IO ()
writeState State s
state (s -> IO ()) -> (s -> s) -> s -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> s
f
modifyState' :: State s -> (s -> s) -> IO ()
modifyState' :: State s -> (s -> s) -> IO ()
modifyState' State s
state s -> s
f = do
s
s <- State s -> IO s
forall s. State s -> IO s
readState State s
state
let s' :: s
s' = s -> s
f s
s
s
s' s -> IO () -> IO ()
`seq` State s -> s -> IO ()
forall s. State s -> s -> IO ()
writeState State s
state s
s'
get :: e `Has` State s => Program e s
get :: Program e s
get = (State s -> IO s) -> Program e s
forall e t a. Has e t => (t -> IO a) -> Program e a
pullWith State s -> IO s
forall s. State s -> IO s
readState
put :: e `Has` State s => s -> Program e ()
put :: s -> Program e ()
put = (State s -> IO ()) -> Program e ()
forall e t a. Has e t => (t -> IO a) -> Program e a
pullWith ((State s -> IO ()) -> Program e ())
-> (s -> State s -> IO ()) -> s -> Program e ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State s -> s -> IO ()) -> s -> State s -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip State s -> s -> IO ()
forall s. State s -> s -> IO ()
writeState
modify :: e `Has` State s => (s -> s) -> Program e ()
modify :: (s -> s) -> Program e ()
modify = (State s -> IO ()) -> Program e ()
forall e t a. Has e t => (t -> IO a) -> Program e a
pullWith ((State s -> IO ()) -> Program e ())
-> ((s -> s) -> State s -> IO ()) -> (s -> s) -> Program e ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State s -> (s -> s) -> IO ()) -> (s -> s) -> State s -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip State s -> (s -> s) -> IO ()
forall s. State s -> (s -> s) -> IO ()
modifyState
modify' :: e `Has` State s => (s -> s) -> Program e ()
modify' :: (s -> s) -> Program e ()
modify' = (State s -> IO ()) -> Program e ()
forall e t a. Has e t => (t -> IO a) -> Program e a
pullWith ((State s -> IO ()) -> Program e ())
-> ((s -> s) -> State s -> IO ()) -> (s -> s) -> Program e ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State s -> (s -> s) -> IO ()) -> (s -> s) -> State s -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip State s -> (s -> s) -> IO ()
forall s. State s -> (s -> s) -> IO ()
modifyState'