{-# OPTIONS_GHC -Wno-redundant-constraints#-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Store (
Store (..)
, Query (..)
, Whole (..)
, SimpleStore
, mkSimpleStore
, UpdateStore
, mkUpdateStore
, mkQueryStore
, hoistStore
, embedStore
, pairStores
, newCachedStore
, updateLoad
, loadWhenNothing
, embedStore'
, newStore
, NotInitialized (..)
, updateSequence
) where
import Prelude
import Control.Applicative
( liftA2
)
import Control.Concurrent.Class.MonadSTM
( MonadSTM
, atomically
, modifyTVar'
, newTVarIO
, readTVar
, readTVarIO
, retry
, writeTVar
)
import Control.Exception
( Exception
, SomeException (..)
, toException
)
import Control.Monad
( foldM_
, join
)
import Control.Monad.Class.MonadThrow
( MonadEvaluate
, MonadMask
, MonadThrow
, evaluate
, finally
, mask
, throwIO
)
import Data.Delta
( Delta (..)
, Embedding
, Embedding' (..)
, Replace (..)
)
import Data.Delta.Embedding
( inject
, project
)
import Data.Delta.Embedding.Internal
( Machine (..)
)
import Data.Kind
( Type
)
import GHC.Generics
( (:+:) (..)
)
data Store m (qa :: Type -> Type) da = Store
{
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
, forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS :: Base da -> m ()
, forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS
:: Maybe (Base da)
-> da
-> m ()
, forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> forall b. qa b -> m b
queryS :: forall b. qa b -> m b
}
newStore
:: (MonadSTM m, MonadThrow m, Delta da, Query qa, Base da ~ World qa)
=> m (Store m qa da)
newStore :: forall (m :: * -> *) da (qa :: * -> *).
(MonadSTM m, MonadThrow m, Delta da, Query qa,
Base da ~ World qa) =>
m (Store m qa da)
newStore = do
TVar m (Either SomeException (World qa))
ref <- Either SomeException (World qa)
-> m (TVar m (Either SomeException (World qa)))
forall a. a -> m (TVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO (Either SomeException (World qa)
-> m (TVar m (Either SomeException (World qa))))
-> Either SomeException (World qa)
-> m (TVar m (Either SomeException (World qa)))
forall a b. (a -> b) -> a -> b
$ SomeException -> Either SomeException (World qa)
forall a b. a -> Either a b
Left (SomeException -> Either SomeException (World qa))
-> SomeException -> Either SomeException (World qa)
forall a b. (a -> b) -> a -> b
$ NotInitialized -> SomeException
forall e. Exception e => e -> SomeException
toException NotInitialized
NotInitialized
let load :: m (Either SomeException (World qa))
load = STM m (Either SomeException (World qa))
-> m (Either SomeException (World qa))
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TVar m (Either SomeException (World qa))
-> STM m (Either SomeException (World qa))
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m (Either SomeException (World qa))
ref)
Store m qa da -> m (Store m qa da)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Store m qa da -> m (Store m qa da))
-> Store m qa da -> m (Store m qa da)
forall a b. (a -> b) -> a -> b
$ Store
{ loadS :: m (Either SomeException (Base da))
loadS = m (Either SomeException (Base da))
m (Either SomeException (World qa))
load
, queryS :: forall b. qa b -> m b
queryS = \qa b
q -> qa b -> World qa -> b
forall b. qa b -> World qa -> b
forall (qa :: * -> *) b. Query qa => qa b -> World qa -> b
query qa b
q (World qa -> b) -> m (World qa) -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Either SomeException (World qa) -> m (World qa)
forall (m :: * -> *) b.
MonadThrow m =>
Either SomeException b -> m b
throwLeft (Either SomeException (World qa) -> m (World qa))
-> m (Either SomeException (World qa)) -> m (World qa)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m (Either SomeException (World qa))
load)
, writeS :: Base da -> m ()
writeS = STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> (World qa -> STM m ()) -> World qa -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TVar m (Either SomeException (World qa))
-> Either SomeException (World qa) -> STM m ()
forall a. TVar m a -> a -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m (Either SomeException (World qa))
ref (Either SomeException (World qa) -> STM m ())
-> (World qa -> Either SomeException (World qa))
-> World qa
-> STM m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. World qa -> Either SomeException (World qa)
forall a b. b -> Either a b
Right
, updateS :: Maybe (Base da) -> da -> m ()
updateS = \Maybe (Base da)
_ -> STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> (da -> STM m ()) -> da -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TVar m (Either SomeException (World qa))
-> (Either SomeException (World qa)
-> Either SomeException (World qa))
-> 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 (Either SomeException (World qa))
ref ((Either SomeException (World qa)
-> Either SomeException (World qa))
-> STM m ())
-> (da
-> Either SomeException (World qa)
-> Either SomeException (World qa))
-> da
-> STM m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (World qa -> World qa)
-> Either SomeException (World qa)
-> Either SomeException (World qa)
forall a b.
(a -> b) -> Either SomeException a -> Either SomeException b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((World qa -> World qa)
-> Either SomeException (World qa)
-> Either SomeException (World qa))
-> (da -> World qa -> World qa)
-> da
-> Either SomeException (World qa)
-> Either SomeException (World qa)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. da -> Base da -> Base da
da -> World qa -> World qa
forall delta. Delta delta => delta -> Base delta -> Base delta
apply
}
data NotInitialized = NotInitialized deriving (NotInitialized -> NotInitialized -> Bool
(NotInitialized -> NotInitialized -> Bool)
-> (NotInitialized -> NotInitialized -> Bool) -> Eq NotInitialized
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NotInitialized -> NotInitialized -> Bool
== :: NotInitialized -> NotInitialized -> Bool
$c/= :: NotInitialized -> NotInitialized -> Bool
/= :: NotInitialized -> NotInitialized -> Bool
Eq, Int -> NotInitialized -> ShowS
[NotInitialized] -> ShowS
NotInitialized -> String
(Int -> NotInitialized -> ShowS)
-> (NotInitialized -> String)
-> ([NotInitialized] -> ShowS)
-> Show NotInitialized
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NotInitialized -> ShowS
showsPrec :: Int -> NotInitialized -> ShowS
$cshow :: NotInitialized -> String
show :: NotInitialized -> String
$cshowList :: [NotInitialized] -> ShowS
showList :: [NotInitialized] -> ShowS
Show)
instance Exception NotInitialized
type SimpleStore m a = Store m (Whole a) (Replace a)
mkSimpleStore
:: forall m a
. (Monad m, MonadThrow m)
=> m (Either SomeException a)
-> (a -> m ())
-> SimpleStore m a
mkSimpleStore :: forall (m :: * -> *) a.
(Monad m, MonadThrow m) =>
m (Either SomeException a) -> (a -> m ()) -> SimpleStore m a
mkSimpleStore m (Either SomeException a)
loadS a -> m ()
writeS =
m (Either SomeException a)
-> (a -> m ())
-> (Maybe a -> Replace a -> m ())
-> UpdateStore m (Replace a)
forall (m :: * -> *) a da.
(Monad m, MonadThrow m, a ~ Base da, Delta da) =>
m (Either SomeException a)
-> (a -> m ()) -> (Maybe a -> da -> m ()) -> UpdateStore m da
mkUpdateStore m (Either SomeException a)
loadS a -> m ()
writeS Maybe a -> Replace a -> m ()
update'
where
update' :: Maybe a -> Replace a -> m ()
update' Maybe a
_ (Replace a
a) = a -> m ()
writeS a
a
type UpdateStore m da = Store m (Whole (Base da)) da
mkUpdateStore
:: forall m a da
. (Monad m, MonadThrow m, a ~ Base da, Delta da)
=> m (Either SomeException a)
-> (a -> m ())
-> (Maybe a -> da -> m ())
-> UpdateStore m da
mkUpdateStore :: forall (m :: * -> *) a da.
(Monad m, MonadThrow m, a ~ Base da, Delta da) =>
m (Either SomeException a)
-> (a -> m ()) -> (Maybe a -> da -> m ()) -> UpdateStore m da
mkUpdateStore m (Either SomeException a)
loadS a -> m ()
writeS Maybe a -> da -> m ()
updateS =
Store{m (Either SomeException a)
m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
loadS :: m (Either SomeException a)
loadS, queryS :: forall b. Whole a b -> m b
queryS=Whole a b -> m b
forall b. Whole a b -> m b
query', a -> m ()
Base da -> m ()
writeS :: Base da -> m ()
writeS :: a -> m ()
writeS, Maybe a -> da -> m ()
Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base da) -> da -> m ()
updateS :: Maybe a -> da -> m ()
updateS}
where
query' :: forall b. Whole a b -> m b
query' :: forall b. Whole a b -> m b
query' Whole a b
Whole = m (Either SomeException a)
loadS m (Either SomeException a)
-> (Either SomeException a -> m b) -> m b
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either SomeException a -> m a
Either SomeException a -> m b
forall (m :: * -> *) b.
MonadThrow m =>
Either SomeException b -> m b
throwLeft
mkQueryStore :: forall m qa da
. (MonadThrow m, Delta da, Query qa, Base da ~ World qa)
=> (forall b. qa b -> m b)
-> UpdateStore m da
-> Store m qa da
mkQueryStore :: forall (m :: * -> *) (qa :: * -> *) da.
(MonadThrow m, Delta da, Query qa, Base da ~ World qa) =>
(forall b. qa b -> m b) -> UpdateStore m da -> Store m qa da
mkQueryStore forall b. qa b -> m b
queryS Store{m (Either SomeException (Base da))
loadS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
loadS,Base da -> m ()
writeS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS :: Base da -> m ()
writeS,Maybe (Base da) -> da -> m ()
updateS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base da) -> da -> m ()
updateS} =
Store{qa b -> m b
forall b. qa b -> m b
queryS :: forall b. qa b -> m b
queryS :: forall b. qa b -> m b
queryS,m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
loadS,Base da -> m ()
writeS :: Base da -> m ()
writeS :: Base da -> m ()
writeS,Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base da) -> da -> m ()
updateS}
class Query qa where
type family World qa
query :: qa b -> World qa -> b
data Whole a b where
Whole :: Whole a a
instance Query (Whole a) where
type World (Whole a) = a
query :: forall b. Whole a b -> World (Whole a) -> b
query Whole a b
Whole World (Whole a)
a = b
World (Whole a)
a
newCachedStore
:: forall m qa da
. ( MonadSTM m, MonadThrow m, MonadEvaluate m
, Delta da, Query qa, Base da ~ World qa
)
=> Store m qa da -> m (Store m qa da)
newCachedStore :: forall (m :: * -> *) (qa :: * -> *) da.
(MonadSTM m, MonadThrow m, MonadEvaluate m, Delta da, Query qa,
Base da ~ World qa) =>
Store m qa da -> m (Store m qa da)
newCachedStore Store{m (Either SomeException (Base da))
loadS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
loadS,Base da -> m ()
writeS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS :: Base da -> m ()
writeS,Maybe (Base da) -> da -> m ()
updateS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base da) -> da -> m ()
updateS} = do
TVar m Bool
islocked <- Bool -> m (TVar m Bool)
forall a. a -> m (TVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO Bool
False
let withLock :: forall b. m b -> m b
withLock :: forall b. m b -> m b
withLock m b
action = do
STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ TVar m Bool -> STM m Bool
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m Bool
islocked STM m Bool -> (Bool -> STM m ()) -> STM m ()
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
Bool
False -> TVar m Bool -> Bool -> STM m ()
forall a. TVar m a -> a -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m Bool
islocked Bool
True
m b
action m b -> m () -> m b
forall a b. m a -> m b -> m a
forall (m :: * -> *) a b. MonadThrow m => m a -> m b -> m a
`finally` STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (TVar m Bool -> Bool -> STM m ()
forall a. TVar m a -> a -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m Bool
islocked Bool
False)
TVar m (Maybe (World qa))
cache <- Maybe (World qa) -> m (TVar m (Maybe (World qa)))
forall a. a -> m (TVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO (Maybe (Base da)
Maybe (World qa)
forall a. Maybe a
Nothing :: Maybe (Base da))
let writeCache :: Maybe (World qa) -> STM m ()
writeCache = TVar m (Maybe (World qa)) -> Maybe (World qa) -> STM m ()
forall a. TVar m a -> a -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m (Maybe (World qa))
cache
let load :: m (Either SomeException (Base da))
load :: m (Either SomeException (Base da))
load = m (m (Either SomeException (Base da)))
-> m (Either SomeException (Base da))
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (m (m (Either SomeException (Base da)))
-> m (Either SomeException (Base da)))
-> m (m (Either SomeException (Base da)))
-> m (Either SomeException (Base da))
forall a b. (a -> b) -> a -> b
$ STM m (m (Either SomeException (Base da)))
-> m (m (Either SomeException (Base da)))
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (m (Either SomeException (Base da)))
-> m (m (Either SomeException (Base da))))
-> STM m (m (Either SomeException (Base da)))
-> m (m (Either SomeException (Base da)))
forall a b. (a -> b) -> a -> b
$ do
Maybe (World qa)
ma <- TVar m (Maybe (World qa)) -> STM m (Maybe (World qa))
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m (Maybe (World qa))
cache
case Maybe (World qa)
ma of
Maybe (World qa)
Nothing -> TVar m Bool -> STM m Bool
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m Bool
islocked STM m Bool
-> (Bool -> STM m (m (Either SomeException (World qa))))
-> STM m (m (Either SomeException (World qa)))
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> STM m (m (Either SomeException (World qa)))
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
Bool
False -> m (Either SomeException (World qa))
-> STM m (m (Either SomeException (World qa)))
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (m (Either SomeException (World qa))
-> STM m (m (Either SomeException (World qa))))
-> m (Either SomeException (World qa))
-> STM m (m (Either SomeException (World qa)))
forall a b. (a -> b) -> a -> b
$ m (Either SomeException (World qa))
-> m (Either SomeException (World qa))
forall b. m b -> m b
withLock (m (Either SomeException (World qa))
-> m (Either SomeException (World qa)))
-> m (Either SomeException (World qa))
-> m (Either SomeException (World qa))
forall a b. (a -> b) -> a -> b
$ do
Either SomeException (World qa)
ea <- m (Either SomeException (Base da))
m (Either SomeException (World qa))
loadS
case Either SomeException (World qa)
ea of
Left SomeException
e -> Either SomeException (World qa)
-> m (Either SomeException (World qa))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SomeException (World qa)
-> m (Either SomeException (World qa)))
-> Either SomeException (World qa)
-> m (Either SomeException (World qa))
forall a b. (a -> b) -> a -> b
$ SomeException -> Either SomeException (World qa)
forall a b. a -> Either a b
Left SomeException
e
Right World qa
a -> do
STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe (World qa) -> STM m ()
writeCache (Maybe (World qa) -> STM m ()) -> Maybe (World qa) -> STM m ()
forall a b. (a -> b) -> a -> b
$ World qa -> Maybe (World qa)
forall a. a -> Maybe a
Just World qa
a
Either SomeException (World qa)
-> m (Either SomeException (World qa))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SomeException (World qa)
-> m (Either SomeException (World qa)))
-> Either SomeException (World qa)
-> m (Either SomeException (World qa))
forall a b. (a -> b) -> a -> b
$ World qa -> Either SomeException (World qa)
forall a b. b -> Either a b
Right World qa
a
Just World qa
a -> m (Either SomeException (World qa))
-> STM m (m (Either SomeException (World qa)))
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (m (Either SomeException (World qa))
-> STM m (m (Either SomeException (World qa))))
-> m (Either SomeException (World qa))
-> STM m (m (Either SomeException (World qa)))
forall a b. (a -> b) -> a -> b
$ Either SomeException (World qa)
-> m (Either SomeException (World qa))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SomeException (World qa)
-> m (Either SomeException (World qa)))
-> Either SomeException (World qa)
-> m (Either SomeException (World qa))
forall a b. (a -> b) -> a -> b
$ World qa -> Either SomeException (World qa)
forall a b. b -> Either a b
Right World qa
a
Store m qa da -> m (Store m qa da)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Store m qa da -> m (Store m qa da))
-> Store m qa da -> m (Store m qa da)
forall a b. (a -> b) -> a -> b
$ Store
{ loadS :: m (Either SomeException (Base da))
loadS = m (Either SomeException (Base da))
load
, queryS :: forall b. qa b -> m b
queryS = \qa b
q -> qa b -> World qa -> b
forall b. qa b -> World qa -> b
forall (qa :: * -> *) b. Query qa => qa b -> World qa -> b
query qa b
q (World qa -> b) -> m (World qa) -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Either SomeException (World qa) -> m (World qa)
forall (m :: * -> *) b.
MonadThrow m =>
Either SomeException b -> m b
throwLeft (Either SomeException (World qa) -> m (World qa))
-> m (Either SomeException (World qa)) -> m (World qa)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m (Either SomeException (Base da))
m (Either SomeException (World qa))
load)
, writeS :: Base da -> m ()
writeS = \Base da
a -> m () -> m ()
forall b. m b -> m b
withLock (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe (World qa) -> STM m ()
writeCache (World qa -> Maybe (World qa)
forall a. a -> Maybe a
Just Base da
World qa
a)
Base da -> m ()
writeS Base da
a
, updateS :: Maybe (Base da) -> da -> m ()
updateS = m (Either SomeException (Base da))
-> (SomeException -> m ())
-> (Base da -> da -> m ())
-> Maybe (Base da)
-> da
-> m ()
forall e (m :: * -> *) t b da.
(Exception e, Monad m) =>
m (Either e t)
-> (e -> m b) -> (t -> da -> m b) -> Maybe t -> da -> m b
updateLoad m (Either SomeException (Base da))
load SomeException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO ((Base da -> da -> m ()) -> Maybe (Base da) -> da -> m ())
-> (Base da -> da -> m ()) -> Maybe (Base da) -> da -> m ()
forall a b. (a -> b) -> a -> b
$ \Base da
old da
delta -> m () -> m ()
forall b. m b -> m b
withLock (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
World qa
new <- World qa -> m (World qa)
forall a. a -> m a
forall (m :: * -> *) a. MonadEvaluate m => a -> m a
evaluate (World qa -> m (World qa)) -> World qa -> m (World qa)
forall a b. (a -> b) -> a -> b
$ da -> Base da -> Base da
forall delta. Delta delta => delta -> Base delta -> Base delta
apply da
delta Base da
old
STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe (World qa) -> STM m ()
writeCache (Maybe (World qa) -> STM m ()) -> Maybe (World qa) -> STM m ()
forall a b. (a -> b) -> a -> b
$ World qa -> Maybe (World qa)
forall a. a -> Maybe a
Just World qa
new
Maybe (Base da) -> da -> m ()
updateS (World qa -> Maybe (World qa)
forall a. a -> Maybe a
Just Base da
World qa
old) da
delta
}
embedStore :: (MonadSTM m, MonadMask m, Delta da)
=> Embedding da db -> UpdateStore m db -> m (UpdateStore m da)
embedStore :: forall (m :: * -> *) da db.
(MonadSTM m, MonadMask m, Delta da) =>
Embedding da db -> UpdateStore m db -> m (UpdateStore m da)
embedStore Embedding da db
embed UpdateStore m db
bstore = do
TVar m (Maybe (Machine da db))
machine <- Maybe (Machine da db) -> m (TVar m (Maybe (Machine da db)))
forall a. a -> m (TVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO Maybe (Machine da db)
forall a. Maybe a
Nothing
let readMachine :: m (Maybe (Machine da db))
readMachine = TVar m (Maybe (Machine da db)) -> m (Maybe (Machine da db))
forall a. TVar m a -> m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> m a
readTVarIO TVar m (Maybe (Machine da db))
machine
writeMachine :: Machine da db -> m ()
writeMachine = STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ())
-> (Machine da db -> STM m ()) -> Machine da db -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TVar m (Maybe (Machine da db)) -> Maybe (Machine da db) -> STM m ()
forall a. TVar m a -> a -> STM m ()
forall (m :: * -> *) a. MonadSTM m => TVar m a -> a -> STM m ()
writeTVar TVar m (Maybe (Machine da db))
machine (Maybe (Machine da db) -> STM m ())
-> (Machine da db -> Maybe (Machine da db))
-> Machine da db
-> STM m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Machine da db -> Maybe (Machine da db)
forall a. a -> Maybe a
Just
let load :: m (Either SomeException (Base da))
load = UpdateStore m db -> m (Either SomeException (Base db))
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS UpdateStore m db
bstore m (Either SomeException (Base db))
-> (Either SomeException (Base db)
-> m (Either SomeException (Base da)))
-> m (Either SomeException (Base da))
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
e -> Either SomeException (Base da)
-> m (Either SomeException (Base da))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SomeException (Base da)
-> m (Either SomeException (Base da)))
-> Either SomeException (Base da)
-> m (Either SomeException (Base da))
forall a b. (a -> b) -> a -> b
$ SomeException -> Either SomeException (Base da)
forall a b. a -> Either a b
Left SomeException
e
Right Base db
b -> case Embedding da db
-> Base db -> Either SomeException (Base da, Machine da db)
forall da db.
Embedding da db
-> Base db -> Either SomeException (Base da, Machine da db)
project Embedding da db
embed Base db
b of
Left SomeException
e -> Either SomeException (Base da)
-> m (Either SomeException (Base da))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SomeException (Base da)
-> m (Either SomeException (Base da)))
-> Either SomeException (Base da)
-> m (Either SomeException (Base da))
forall a b. (a -> b) -> a -> b
$ SomeException -> Either SomeException (Base da)
forall a b. a -> Either a b
Left SomeException
e
Right (Base da
a,Machine da db
mab) -> do
Machine da db -> m ()
writeMachine Machine da db
mab
Either SomeException (Base da)
-> m (Either SomeException (Base da))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SomeException (Base da)
-> m (Either SomeException (Base da)))
-> Either SomeException (Base da)
-> m (Either SomeException (Base da))
forall a b. (a -> b) -> a -> b
$ Base da -> Either SomeException (Base da)
forall a b. b -> Either a b
Right Base da
a
write :: Base da -> m ()
write Base da
a = do
let mab :: Machine da db
mab = Embedding da db -> Base da -> Machine da db
forall da db. Embedding da db -> Base da -> Machine da db
inject Embedding da db
embed Base da
a
((forall a. m a -> m a) -> m ()) -> m ()
forall b. ((forall a. m a -> m a) -> m b) -> m b
forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m ()) -> m ())
-> ((forall a. m a -> m a) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
m () -> m ()
forall a. m a -> m a
restore (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UpdateStore m db -> Base db -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS UpdateStore m db
bstore (Machine da db -> Base db
forall da db. Machine da db -> Base db
state_ Machine da db
mab)
Machine da db -> m ()
writeMachine Machine da db
mab
update :: Maybe (Base da) -> da -> m ()
update = m (Either SomeException (Base da))
-> (SomeException -> m ())
-> (Base da -> da -> m ())
-> Maybe (Base da)
-> da
-> m ()
forall e (m :: * -> *) t b da.
(Exception e, Monad m) =>
m (Either e t)
-> (e -> m b) -> (t -> da -> m b) -> Maybe t -> da -> m b
updateLoad m (Either SomeException (Base da))
load SomeException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO ((Base da -> da -> m ()) -> Maybe (Base da) -> da -> m ())
-> (Base da -> da -> m ()) -> Maybe (Base da) -> da -> m ()
forall a b. (a -> b) -> a -> b
$ \Base da
a da
da -> do
m (Maybe (Machine da db))
readMachine m (Maybe (Machine da db))
-> (Maybe (Machine da db) -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe (Machine da db)
Nothing -> do
Base da -> m ()
write (da -> Base da -> Base da
forall delta. Delta delta => delta -> Base delta -> Base delta
apply da
da Base da
a)
Just Machine da db
mab1 -> do
let (db
db, Machine da db
mab2) = Machine da db -> (Base da, da) -> (db, Machine da db)
forall da db. Machine da db -> (Base da, da) -> (db, Machine da db)
step_ Machine da db
mab1 (Base da
a,da
da)
((forall a. m a -> m a) -> m ()) -> m ()
forall b. ((forall a. m a -> m a) -> m b) -> m b
forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m ()) -> m ())
-> ((forall a. m a -> m a) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
m () -> m ()
forall a. m a -> m a
restore (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UpdateStore m db -> Maybe (Base db) -> db -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS UpdateStore m db
bstore (Base db -> Maybe (Base db)
forall a. a -> Maybe a
Just (Base db -> Maybe (Base db)) -> Base db -> Maybe (Base db)
forall a b. (a -> b) -> a -> b
$ Machine da db -> Base db
forall da db. Machine da db -> Base db
state_ Machine da db
mab2) db
db
Machine da db -> m ()
writeMachine Machine da db
mab2
UpdateStore m da -> m (UpdateStore m da)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (UpdateStore m da -> m (UpdateStore m da))
-> UpdateStore m da -> m (UpdateStore m da)
forall a b. (a -> b) -> a -> b
$ m (Either SomeException (Base da))
-> (Base da -> m ())
-> (Maybe (Base da) -> da -> m ())
-> UpdateStore m da
forall (m :: * -> *) a da.
(Monad m, MonadThrow m, a ~ Base da, Delta da) =>
m (Either SomeException a)
-> (a -> m ()) -> (Maybe a -> da -> m ()) -> UpdateStore m da
mkUpdateStore m (Either SomeException (Base da))
load Base da -> m ()
write Maybe (Base da) -> da -> m ()
update
embedStore'
:: (Monad m, MonadThrow m)
=> Embedding' da db -> UpdateStore m db -> UpdateStore m da
embedStore' :: forall (m :: * -> *) da db.
(Monad m, MonadThrow m) =>
Embedding' da db -> UpdateStore m db -> UpdateStore m da
embedStore' Embedding'{b -> Either SomeException a
load :: b -> Either SomeException a
load :: ()
load,a -> b
write :: a -> b
write :: ()
write,a -> b -> da -> db
update :: a -> b -> da -> db
update :: ()
update} Store{m (Either SomeException (Base db))
loadS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base db))
loadS,Base db -> m ()
writeS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS :: Base db -> m ()
writeS,Maybe (Base db) -> db -> m ()
updateS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base db) -> db -> m ()
updateS} =
let
loadL :: m (Either SomeException a)
loadL = (b -> Either SomeException a
load (b -> Either SomeException a)
-> Either SomeException b -> Either SomeException a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) (Either SomeException b -> Either SomeException a)
-> m (Either SomeException b) -> m (Either SomeException a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Either SomeException b)
m (Either SomeException (Base db))
loadS
updateL :: Maybe a -> da -> m ()
updateL Maybe a
ma da
da = case Maybe a
ma of
Just a
a -> m (Either SomeException b)
m (Either SomeException (Base db))
loadS m (Either SomeException b)
-> (Either SomeException b -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Right b
b -> Maybe (Base db) -> db -> m ()
updateS (b -> Maybe b
forall a. a -> Maybe a
Just b
b) (a -> b -> da -> db
update a
a b
b da
da)
Maybe a
Nothing -> do
Either SomeException a
ea <- m (Either SomeException a)
loadL
case Either SomeException a
ea of
Left SomeException
e -> SomeException -> m ()
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO SomeException
e
Right a
a -> Maybe a -> da -> m ()
updateL (a -> Maybe a
forall a. a -> Maybe a
Just a
a) da
da
in m (Either SomeException a)
-> (a -> m ())
-> (Maybe a -> da -> m ())
-> Store m (Whole (Base da)) da
forall (m :: * -> *) a da.
(Monad m, MonadThrow m, a ~ Base da, Delta da) =>
m (Either SomeException a)
-> (a -> m ()) -> (Maybe a -> da -> m ()) -> UpdateStore m da
mkUpdateStore m (Either SomeException a)
loadL (b -> m ()
Base db -> m ()
writeS (b -> m ()) -> (a -> b) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
write) Maybe a -> da -> m ()
updateL
hoistStore
:: Monad m
=> (forall a. m a -> n a)
-> Store m qa da
-> Store n qa da
hoistStore :: forall (m :: * -> *) (n :: * -> *) (qa :: * -> *) da.
Monad m =>
(forall a. m a -> n a) -> Store m qa da -> Store n qa da
hoistStore forall a. m a -> n a
f Store{m (Either SomeException (Base da))
loadS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS :: m (Either SomeException (Base da))
loadS,Base da -> m ()
writeS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS :: Base da -> m ()
writeS,Maybe (Base da) -> da -> m ()
updateS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS :: Maybe (Base da) -> da -> m ()
updateS,forall b. qa b -> m b
queryS :: forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> forall b. qa b -> m b
queryS :: forall b. qa b -> m b
queryS} = Store
{ loadS :: n (Either SomeException (Base da))
loadS = m (Either SomeException (Base da))
-> n (Either SomeException (Base da))
forall a. m a -> n a
f m (Either SomeException (Base da))
loadS
, writeS :: Base da -> n ()
writeS = m () -> n ()
forall a. m a -> n a
f (m () -> n ()) -> (Base da -> m ()) -> Base da -> n ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base da -> m ()
writeS
, updateS :: Maybe (Base da) -> da -> n ()
updateS = \Maybe (Base da)
ma -> m () -> n ()
forall a. m a -> n a
f (m () -> n ()) -> (da -> m ()) -> da -> n ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (Base da) -> da -> m ()
updateS Maybe (Base da)
ma
, queryS :: forall b. qa b -> n b
queryS = m b -> n b
forall a. m a -> n a
f (m b -> n b) -> (qa b -> m b) -> qa b -> n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. qa b -> m b
forall b. qa b -> m b
queryS
}
pairStores
:: Monad m
=> Store m qa da
-> Store m qb db
-> Store m (qa :+: qb) (da,db)
pairStores :: forall (m :: * -> *) (qa :: * -> *) da (qb :: * -> *) db.
Monad m =>
Store m qa da -> Store m qb db -> Store m (qa :+: qb) (da, db)
pairStores Store m qa da
sa Store m qb db
sb = Store
{ loadS :: m (Either SomeException (Base (da, db)))
loadS = (Base da -> Base db -> (Base da, Base db))
-> Either SomeException (Base da)
-> Either SomeException (Base db)
-> Either SomeException (Base da, Base db)
forall a b c.
(a -> b -> c)
-> Either SomeException a
-> Either SomeException b
-> Either SomeException c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) (Either SomeException (Base da)
-> Either SomeException (Base db)
-> Either SomeException (Base da, Base db))
-> m (Either SomeException (Base da))
-> m (Either SomeException (Base db)
-> Either SomeException (Base da, Base db))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Store m qa da -> m (Either SomeException (Base da))
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS Store m qa da
sa m (Either SomeException (Base db)
-> Either SomeException (Base da, Base db))
-> m (Either SomeException (Base db))
-> m (Either SomeException (Base da, Base db))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Store m qb db -> m (Either SomeException (Base db))
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS Store m qb db
sb
, queryS :: forall b. (:+:) qa qb b -> m b
queryS = \case
L1 qa b
qa -> Store m qa da -> forall b. qa b -> m b
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> forall b. qa b -> m b
queryS Store m qa da
sa qa b
qa
R1 qb b
qb -> Store m qb db -> forall b. qb b -> m b
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> forall b. qa b -> m b
queryS Store m qb db
sb qb b
qb
, writeS :: Base (da, db) -> m ()
writeS = \(Base da
a,Base db
b) -> Store m qa da -> Base da -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS Store m qa da
sa Base da
a m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Store m qb db -> Base db -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Base da -> m ()
writeS Store m qb db
sb Base db
b
, updateS :: Maybe (Base (da, db)) -> (da, db) -> m ()
updateS = \Maybe (Base (da, db))
mi (da
da,db
db) ->
case Maybe (Base (da, db))
mi of
Maybe (Base (da, db))
Nothing -> Store m qa da -> Maybe (Base da) -> da -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS Store m qa da
sa Maybe (Base da)
forall a. Maybe a
Nothing da
da m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Store m qb db -> Maybe (Base db) -> db -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS Store m qb db
sb Maybe (Base db)
forall a. Maybe a
Nothing db
db
Just (Base da
a,Base db
b) -> Store m qa da -> Maybe (Base da) -> da -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS Store m qa da
sa (Base da -> Maybe (Base da)
forall a. a -> Maybe a
Just Base da
a) da
da m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Store m qb db -> Maybe (Base db) -> db -> m ()
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> Maybe (Base da) -> da -> m ()
updateS Store m qb db
sb (Base db -> Maybe (Base db)
forall a. a -> Maybe a
Just Base db
b) db
db
}
updateLoad :: (Exception e, Monad m)
=> m (Either e t)
-> (e -> m b)
-> (t -> da -> m b)
-> Maybe t
-> da
-> m b
updateLoad :: forall e (m :: * -> *) t b da.
(Exception e, Monad m) =>
m (Either e t)
-> (e -> m b) -> (t -> da -> m b) -> Maybe t -> da -> m b
updateLoad m (Either e t)
load e -> m b
handle t -> da -> m b
update' Maybe t
Nothing da
da = do
Either e t
ea <- m (Either e t)
load
case Either e t
ea of
Left e
e -> e -> m b
handle e
e
Right t
x -> t -> da -> m b
update' t
x da
da
updateLoad m (Either e t)
_load e -> m b
_ t -> da -> m b
update' (Just t
x) da
da = t -> da -> m b
update' t
x da
da
throwLeft :: MonadThrow m => Either SomeException b -> m b
throwLeft :: forall (m :: * -> *) b.
MonadThrow m =>
Either SomeException b -> m b
throwLeft = \case
Left (SomeException e
e) -> e -> m b
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO e
e
Right b
a -> b -> m b
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
a
loadWhenNothing
:: (Monad m, MonadThrow m, Delta da)
=> Maybe (Base da) -> Store m qa da -> m (Base da)
loadWhenNothing :: forall (m :: * -> *) da (qa :: * -> *).
(Monad m, MonadThrow m, Delta da) =>
Maybe (Base da) -> Store m qa da -> m (Base da)
loadWhenNothing (Just Base da
a) Store m qa da
_ = Base da -> m (Base da)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Base da
a
loadWhenNothing Maybe (Base da)
Nothing Store m qa da
store = Store m qa da -> m (Either SomeException (Base da))
forall (m :: * -> *) (qa :: * -> *) da.
Store m qa da -> m (Either SomeException (Base da))
loadS Store m qa da
store m (Either SomeException (Base da))
-> (Either SomeException (Base da) -> m (Base da)) -> m (Base da)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either SomeException (Base da) -> m (Base da)
forall (m :: * -> *) b.
MonadThrow m =>
Either SomeException b -> m b
throwLeft
updateSequence
:: (Monad m, Delta delta)
=> (Base delta -> delta -> m ())
-> Base delta
-> [delta]
-> m ()
updateSequence :: forall (m :: * -> *) delta.
(Monad m, Delta delta) =>
(Base delta -> delta -> m ()) -> Base delta -> [delta] -> m ()
updateSequence Base delta -> delta -> m ()
f Base delta
s = (Base delta -> delta -> m (Base delta))
-> Base delta -> [delta] -> m ()
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m ()
foldM_ Base delta -> delta -> m (Base delta)
update' Base delta
s ([delta] -> m ()) -> ([delta] -> [delta]) -> [delta] -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [delta] -> [delta]
forall a. [a] -> [a]
reverse
where
update' :: Base delta -> delta -> m (Base delta)
update' Base delta
s' delta
da = Base delta -> delta -> m ()
f Base delta
s' delta
da m () -> m (Base delta) -> m (Base delta)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Base delta -> m (Base delta)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (delta
da delta -> Base delta -> Base delta
forall delta. Delta delta => delta -> Base delta -> Base delta
`apply` Base delta
s')