module Hydra.API.Projection where
import Hydra.Prelude
import Control.Concurrent.Class.MonadSTM (modifyTVar', newTVarIO)
data Projection stm event model = Projection
{ forall (stm :: * -> *) event model.
Projection stm event model -> stm model
getLatest :: stm model
, forall (stm :: * -> *) event model.
Projection stm event model -> event -> stm ()
update :: event -> stm ()
}
mkProjection ::
MonadSTM m =>
model ->
(model -> event -> model) ->
m (Projection (STM m) event model)
mkProjection :: forall (m :: * -> *) model event.
MonadSTM m =>
model
-> (model -> event -> model) -> m (Projection (STM m) event model)
mkProjection model
startingModel model -> event -> model
project = do
TVar m model
tv <- model -> m (TVar m model)
forall a. a -> m (TVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO model
startingModel
Projection (STM m) event model
-> m (Projection (STM m) event model)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
Projection
{ $sel:getLatest:Projection :: STM m model
getLatest = TVar m model -> STM m model
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m model
tv
, $sel:update:Projection :: event -> STM m ()
update = TVar m model -> event -> STM m ()
update TVar m model
tv
}
where
update :: TVar m model -> event -> STM m ()
update TVar m model
tv event
event =
TVar m model -> (model -> model) -> STM m ()
forall a. TVar m a -> (a -> a) -> STM m ()
forall (m :: * -> *) a.
MonadSTM m =>
TVar m a -> (a -> a) -> STM m ()
modifyTVar' TVar m model
tv ((model -> model) -> STM m ()) -> (model -> model) -> STM m ()
forall a b. (a -> b) -> a -> b
$ \model
m ->
model -> event -> model
project model
m event
event