packages feed

crdt 7.0 → 8.0

raw patch · 11 files changed

+119/−133 lines, 11 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- CRDT.LamportClock.Simulation: instance Control.Monad.Trans.Class.MonadTrans (CRDT.LamportClock.Simulation.LamportClockSimT s)
- CRDT.LamportClock.Simulation: instance Control.Monad.Trans.Class.MonadTrans (CRDT.LamportClock.Simulation.ProcessSimT s)
- CRDT.LamportClock.Simulation: instance GHC.Base.Functor m => GHC.Base.Functor (CRDT.LamportClock.Simulation.LamportClockSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Functor m => GHC.Base.Functor (CRDT.LamportClock.Simulation.ProcessSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => CRDT.LamportClock.Clock (CRDT.LamportClock.Simulation.ProcessSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => CRDT.LamportClock.Process (CRDT.LamportClock.Simulation.ProcessSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError GHC.Base.String (CRDT.LamportClock.Simulation.LamportClockSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (CRDT.LamportClock.Simulation.LamportClockSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (CRDT.LamportClock.Simulation.ProcessSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState s (CRDT.LamportClock.Simulation.ProcessSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Applicative (CRDT.LamportClock.Simulation.LamportClockSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Applicative (CRDT.LamportClock.Simulation.ProcessSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Monad (CRDT.LamportClock.Simulation.LamportClockSimT s m)
- CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Monad (CRDT.LamportClock.Simulation.ProcessSimT s m)
+ CRDT.LamportClock: instance CRDT.LamportClock.Clock m => CRDT.LamportClock.Clock (Control.Monad.Trans.State.Strict.StateT s m)
+ CRDT.LamportClock: instance CRDT.LamportClock.Process m => CRDT.LamportClock.Process (Control.Monad.Trans.State.Strict.StateT s m)
+ CRDT.LamportClock.Simulation: instance Control.Monad.Trans.Class.MonadTrans CRDT.LamportClock.Simulation.LamportClockSimT
+ CRDT.LamportClock.Simulation: instance Control.Monad.Trans.Class.MonadTrans CRDT.LamportClock.Simulation.ProcessSimT
+ CRDT.LamportClock.Simulation: instance GHC.Base.Functor m => GHC.Base.Functor (CRDT.LamportClock.Simulation.LamportClockSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Functor m => GHC.Base.Functor (CRDT.LamportClock.Simulation.ProcessSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => CRDT.LamportClock.Clock (CRDT.LamportClock.Simulation.ProcessSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => CRDT.LamportClock.Process (CRDT.LamportClock.Simulation.ProcessSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.Error.Class.MonadError GHC.Base.String (CRDT.LamportClock.Simulation.LamportClockSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (CRDT.LamportClock.Simulation.LamportClockSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (CRDT.LamportClock.Simulation.ProcessSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Applicative (CRDT.LamportClock.Simulation.LamportClockSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Applicative (CRDT.LamportClock.Simulation.ProcessSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Monad (CRDT.LamportClock.Simulation.LamportClockSimT m)
+ CRDT.LamportClock.Simulation: instance GHC.Base.Monad m => GHC.Base.Monad (CRDT.LamportClock.Simulation.ProcessSimT m)
- CRDT.LamportClock.Simulation: LamportClockSim :: (ExceptT String (RWST s () (Map Pid (ProcessState s)) m) a) -> LamportClockSimT s m a
+ CRDT.LamportClock.Simulation: LamportClockSim :: (ExceptT String (StateT (Map Pid LocalTime) m) a) -> LamportClockSimT m a
- CRDT.LamportClock.Simulation: ProcessSim :: (ReaderT Pid (LamportClockSimT s m) a) -> ProcessSimT s m a
+ CRDT.LamportClock.Simulation: ProcessSim :: (ReaderT Pid (LamportClockSimT m) a) -> ProcessSimT m a
- CRDT.LamportClock.Simulation: newtype LamportClockSimT s m a
+ CRDT.LamportClock.Simulation: newtype LamportClockSimT m a
- CRDT.LamportClock.Simulation: newtype ProcessSimT s m a
+ CRDT.LamportClock.Simulation: newtype ProcessSimT m a
- CRDT.LamportClock.Simulation: runLamportClockSim :: s -> LamportClockSim s a -> Either String a
+ CRDT.LamportClock.Simulation: runLamportClockSim :: LamportClockSim a -> Either String a
- CRDT.LamportClock.Simulation: runLamportClockSimT :: Monad m => s -> LamportClockSimT s m a -> m (Either String a)
+ CRDT.LamportClock.Simulation: runLamportClockSimT :: Monad m => LamportClockSimT m a -> m (Either String a)
- CRDT.LamportClock.Simulation: runProcessSim :: Pid -> ProcessSim s a -> LamportClockSim s a
+ CRDT.LamportClock.Simulation: runProcessSim :: Pid -> ProcessSim a -> LamportClockSim a
- CRDT.LamportClock.Simulation: runProcessSimT :: Pid -> ProcessSimT s m a -> LamportClockSimT s m a
+ CRDT.LamportClock.Simulation: runProcessSimT :: Pid -> ProcessSimT m a -> LamportClockSimT m a
- CRDT.LamportClock.Simulation: type LamportClockSim s = LamportClockSimT s Identity
+ CRDT.LamportClock.Simulation: type LamportClockSim = LamportClockSimT Identity
- CRDT.LamportClock.Simulation: type ProcessSim s = ProcessSimT s Identity
+ CRDT.LamportClock.Simulation: type ProcessSim = ProcessSimT Identity

Files

crdt.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 03da394dee75b1bb3cc8d9b26448adbfe3b32c0f4f91c1f62c6672bb5ab17d04+-- hash: f6c5e8a56fae4a26b32be8d375082402b27412d45fd5f75b9d227c7f77374a7c  name:           crdt-version:        7.0+version:        8.0 synopsis:       Conflict-free replicated data types description:    Definitions of CmRDT and CvRDT. Implementations for some classic CRDTs. category:       Distributed Systems
lib/CRDT/Cm/RGA.hs view
@@ -49,14 +49,6 @@             _           -> False         Nothing -> False --- before :: Vertex -> Vertex -> Bool--- before u v = b---     pre lookup(u) ∧ lookup(v)---     ∃w_1, ..., w_m ∈ verticesAdded:---         w_1 = u---         ∧ w_m = v---         ∧ ∀j: (w_j, w_{j+1}) ∈ edges- data RgaIntent a     = AddAfter (Maybe VertexId) a       -- ^ 'Nothing' means the beginning@@ -75,10 +67,7 @@     precedes _ _ = False  emptyPayload :: RgaPayload a-emptyPayload = RgaPayload-    { vertices = Vector.empty-    , vertexIxs = Map.empty-    }+emptyPayload = RgaPayload{vertices = Vector.empty, vertexIxs = Map.empty}  instance Ord a => CmRDT (RGA a) where     type Intent  (RGA a) = RgaIntent  a@@ -95,9 +84,8 @@         RgaPayload{vertexIxs} = payload         ok = Just $ do             case Map.lookupMax vertexIxs of-                Just (LamportTime maxKnownTime _, _) ->-                    advance maxKnownTime-                Nothing -> pure ()+                Just (LamportTime maxKnownTime _, _) -> advance maxKnownTime+                Nothing                              -> pure ()             newId <- getTime             pure $ OpAddAfter mOldId atom newId @@ -106,10 +94,7 @@         | otherwise        = Nothing      apply (OpAddAfter mOldId newAtom newId) payload =-        RgaPayload-            { vertices  = vertices'-            , vertexIxs = vertexIxs'-            }+        RgaPayload{vertices = vertices', vertexIxs = vertexIxs'}       where         RgaPayload{vertices, vertexIxs} = payload         n = length vertices
lib/CRDT/LamportClock.hs view
@@ -21,6 +21,7 @@                                          readTVar, writeTVar) import           Control.Monad.IO.Class (MonadIO, liftIO) import           Control.Monad.Reader (ReaderT, ask, runReaderT)+import           Control.Monad.State.Strict (StateT) import           Control.Monad.Trans (lift) import           Data.Binary (decode) import qualified Data.ByteString.Lazy as BSL@@ -97,6 +98,13 @@ instance Process m => Process (ReaderT r m) where     getPid = lift getPid +instance Process m => Process (StateT s m) where+    getPid = lift getPid+ instance Clock m => Clock (ReaderT r m) where+    advance = lift . advance+    getTime = lift getTime++instance Clock m => Clock (StateT s m) where     advance = lift . advance     getTime = lift getTime
lib/CRDT/LamportClock/Simulation.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} @@ -20,9 +21,8 @@                                        throwError) import           Control.Monad.Fail (MonadFail, fail) import           Control.Monad.Reader (ReaderT, ask, runReaderT)-import           Control.Monad.RWS.Strict (RWST, evalRWS, evalRWST)-import           Control.Monad.State.Strict (MonadState, get, gets, modify, put,-                                             state)+import           Control.Monad.State.Strict (StateT, evalState, evalStateT,+                                             modify, state) import           Control.Monad.Trans (MonadTrans, lift) import           Data.Functor.Identity (Identity) import           Data.Map.Strict (Map)@@ -33,36 +33,31 @@  -- | Lamport clock simulation. Key is 'Pid'. -- Non-present value is equivalent to (0, initial).-newtype LamportClockSimT s m a =-    LamportClockSim (ExceptT String (RWST s () (Map Pid (ProcessState s)) m) a)+newtype LamportClockSimT m a =+    LamportClockSim (ExceptT String (StateT (Map Pid LocalTime) m) a)     deriving (Applicative, Functor, Monad, MonadError String) -instance MonadTrans (LamportClockSimT s) where+instance MonadTrans LamportClockSimT where     lift = LamportClockSim . lift . lift -instance Monad m => MonadFail (LamportClockSimT s m) where+instance Monad m => MonadFail (LamportClockSimT m) where     fail = throwError -type LamportClockSim s = LamportClockSimT s Identity--data ProcessState s = ProcessState-    { time :: LocalTime-    , var  :: s-    }+type LamportClockSim = LamportClockSimT Identity  -- | ProcessSim inside Lamport clock simulation.-newtype ProcessSimT s m a = ProcessSim (ReaderT Pid (LamportClockSimT s m) a)+newtype ProcessSimT m a = ProcessSim (ReaderT Pid (LamportClockSimT m) a)     deriving (Applicative, Functor, Monad, MonadFail) -type ProcessSim s = ProcessSimT s Identity+type ProcessSim = ProcessSimT Identity -instance MonadTrans (ProcessSimT s) where+instance MonadTrans ProcessSimT where     lift = ProcessSim . lift . lift -instance Monad m => Process (ProcessSimT s m) where+instance Monad m => Process (ProcessSimT m) where     getPid = ProcessSim ask -instance Monad m => Clock (ProcessSimT s m) where+instance Monad m => Clock (ProcessSimT m) where     getTime = ProcessSim $ do         pid <- ask         time <- lift $ preIncrementTime pid@@ -70,50 +65,30 @@      advance time = ProcessSim $ do         pid <- ask-        lift . LamportClockSim $ do-            initial <- ask-            modify $ Map.alter (Just . advancePS initial) pid-      where-        advancePS initial Nothing = ProcessState{time, var = initial}-        advancePS _       (Just ProcessState{time = current, var}) =-            ProcessState{time = max time current, var}--instance Monad m => MonadState s (ProcessSimT s m) where-    get = ProcessSim $ do-        pid <- ask-        lift . LamportClockSim $ do-            initial <- ask-            gets $ maybe initial var . Map.lookup pid-    put var = ProcessSim $ do-        pid <- ask-        lift . LamportClockSim . modify $ Map.alter (Just . putPS) pid+        lift . LamportClockSim . modify $ Map.alter (Just . advancePS) pid       where-        putPS Nothing                   = ProcessState{time = 0, var}-        putPS (Just ProcessState{time}) = ProcessState{time,     var}+        advancePS = \case+            Nothing      -> time+            Just current -> max time current -runLamportClockSim :: s -> LamportClockSim s a -> Either String a-runLamportClockSim initial (LamportClockSim action) =-    fst $ evalRWS (runExceptT action) initial mempty+runLamportClockSim :: LamportClockSim a -> Either String a+runLamportClockSim (LamportClockSim action) =+    evalState (runExceptT action) mempty -runLamportClockSimT-    :: Monad m => s -> LamportClockSimT s m a -> m (Either String a)-runLamportClockSimT initial (LamportClockSim action) =-    fst <$> evalRWST (runExceptT action) initial mempty+runLamportClockSimT :: Monad m => LamportClockSimT m a -> m (Either String a)+runLamportClockSimT (LamportClockSim action) =+    evalStateT (runExceptT action) mempty -runProcessSim :: Pid -> ProcessSim s a -> LamportClockSim s a+runProcessSim :: Pid -> ProcessSim a -> LamportClockSim a runProcessSim pid (ProcessSim action) = runReaderT action pid -runProcessSimT :: Pid -> ProcessSimT s m a -> LamportClockSimT s m a+runProcessSimT :: Pid -> ProcessSimT m a -> LamportClockSimT m a runProcessSimT pid (ProcessSim action) = runReaderT action pid -preIncrementTime :: Monad m => Pid -> LamportClockSimT s m LocalTime-preIncrementTime pid = LamportClockSim $ do-    initial <- ask-    state $ \pss -> let-        ps@ProcessState{time} =-            case Map.lookup pid pss of-                Nothing -> ProcessState{time = 1, var = initial}-                Just ProcessState{time = current, var} ->-                    ProcessState{time = succ current, var}-        in-        (time, Map.insert pid ps pss)+preIncrementTime :: Monad m => Pid -> LamportClockSimT m LocalTime+preIncrementTime pid = LamportClockSim $ state $ \pss -> let+    time = case Map.lookup pid pss of+        Nothing      -> 1+        Just current -> succ current+    in+    (time, Map.insert pid time pss)
test/Cm/ORSet.hs view
@@ -7,6 +7,7 @@  module Cm.ORSet where +import           Control.Monad.State.Strict (evalStateT) import qualified Data.MultiMap as MultiMap import           Test.QuickCheck (counterexample, (.&&.), (===), (==>)) @@ -22,10 +23,11 @@ prop_Cm = cmrdtLaw @(ORSet Char)  -- | Example from fig. 14 from "A comprehensive study of CRDTs"-prop_fig14 α β a = expectRight . runLamportClockSim (initial @(ORSet Char)) $ do-    op1 <- runProcessSim β $ makeAndApplyOp (Add (a :: Char))-    op2 <- runProcessSim α $ makeAndApplyOp (Add a)-    op3 <- runProcessSim α $ makeAndApplyOp (Remove a)+prop_fig14 α β a = expectRight . runLamportClockSim $ do+    op1 <- runProcessSim β . eval . makeAndApplyOp $ Add (a :: Char)+    (op2, op3) <- runProcessSim α . eval $+        (,) <$> makeAndApplyOp (Add a)+            <*> makeAndApplyOp (Remove a)     pure $         α < β ==>         check "2"   [op2]           [a :- [Tag α 0]]          .&&.@@ -39,6 +41,7 @@         counterexample ("ops = " ++ opsLabel) $         counterexample ("ops = " ++ show ops) $         query' ops === result+    eval = (`evalStateT` initial @(ORSet Char))  query' :: (Ord a, Foldable f) => f (ORSet a) -> [(a, [Tag])] query' = MultiMap.assocs . elements . query
test/Cv/ORSet.hs view
@@ -18,11 +18,12 @@  test_Cv = cvrdtLaws @(ORSet Int) -prop_add pid (x :: Char) s = expectRight . runLamportClockSim undefined $-    runProcessSim pid $ not . lookup x . remove x <$> add x s+prop_add pid (x :: Char) s =+    expectRight . runLamportClockSim . runProcessSim pid $+        not . lookup x . remove x <$> add x s  -- | Difference from 'LwwElementSet' -- -- other replica can not accidentally delete x-prop_add_merge (x :: Char) pid s1 s0 = expectRight $-    runLamportClockSim undefined $-        runProcessSim pid $ lookup x . (<> s1) <$> add x s0+prop_add_merge (x :: Char) pid s1 s0 =+    expectRight . runLamportClockSim . runProcessSim pid $+        lookup x . (<> s1) <$> add x s0
test/Cv/RGA.hs view
@@ -15,12 +15,12 @@ import           Util (expectRight)  prop_fromString_toString s pid = expectRight $ do-    s' <- runLamportClockSim undefined $ runProcessSim pid $ fromString s+    s' <- runLamportClockSim . runProcessSim pid $ fromString s     pure $ toString s' === s  test_Cv = cvrdtLaws @RgaString -prop_edit v1 s2 pid = expectRight . runLamportClockSim undefined $ do+prop_edit v1 s2 pid = expectRight . runLamportClockSim $ do     v2 <- runProcessSim pid $ edit s2 v1     pure $ toString v2 === s2 
test/LWW.hs view
@@ -26,13 +26,13 @@ test_Cv = cvrdtLaws @(LWW Char)  prop_assign pid1 pid2 (formerValue :: Char) latterValue =-    expectRight . runLamportClockSim undefined $ do+    expectRight . runLamportClockSim $ do         state1 <- runProcessSim pid1 $ initialize formerValue         state2 <- runProcessSim pid2 $ assign latterValue state1         pure $ query state2 === latterValue  prop_merge_with_former pid1 pid2 (formerValue :: Char) latterValue =-    expectRight . runLamportClockSim undefined $ do+    expectRight . runLamportClockSim $ do         state1 <- runProcessSim pid1 $ initialize formerValue         state2 <- runProcessSim pid2 $ assign latterValue state1         pure $ query (state1 <> state2) === latterValue
test/Laws.hs view
@@ -14,7 +14,8 @@     , opCommutativity     ) where -import           Control.Monad.State.Strict (MonadState, get, modify)+import           Control.Monad.State.Strict (MonadState, StateT, evalStateT,+                                             execStateT, get, modify) import           Control.Monad.Trans (lift) import           Data.Functor.Identity (runIdentity) import           Data.Maybe (isJust)@@ -59,31 +60,31 @@ -- | CmRDT law: concurrent ops commute cmrdtLaw     :: forall op.-    ( CmRDT op, Show op-    , Arbitrary (Intent  op), Show (Intent  op)-    , Arbitrary (Payload op), Show (Payload op)+    ( CmRDT op+    , Show op+    , Arbitrary (Intent  op)+    , Show (Intent  op)+    , Show (Payload op)     )     => Property cmrdtLaw = property concurrentOpsCommute   where-    concurrentOpsCommute payload pid1 pid2 pid3 =+    concurrentOpsCommute pid1 pid2 pid3 =         pid1 < pid2 && pid2 < pid3 ==>-        forAll genOps $ \case+        forAll genFixture $ \case             Right ((in1, op1), (in2, op2), state3) ->                 concurrent op1 op2 ==>                 opCommutativity (in1, op1) (in2, op2) state3             Left _ -> discard       where-        genOps = fmap runIdentity $ runGenT $ runLamportClockSimT payload $ (,,)-            <$> runProcessSimT pid1 (do-                    _ <- genAndApplyOps @op-                    genAndApplyOp @op)-            <*> runProcessSimT pid2 (do-                    _ <- genAndApplyOps @op-                    genAndApplyOp @op)-            <*> runProcessSimT pid3 (do-                    _ <- genAndApplyOps @op-                    get)+        genFixture = fmap runIdentity . runGenT . runLamportClockSimT $ (,,)+            <$> runProcessSimT pid1 genStateAndTakeLastOp+            <*> runProcessSimT pid2 genStateAndTakeLastOp+            <*> runProcessSimT pid3 genState+        genState = (`execStateT` initial @op) $ genAndApplyOps @op+        genStateAndTakeLastOp = (`evalStateT` initial @op) $ do+            _ <- genAndApplyOps @op+            genAndApplyOp @op  opCommutativity     :: forall op.@@ -102,7 +103,7 @@         .&&.         (apply op1 . apply op2) state === (apply op2 . apply op1) state   where-    makeOp' = makeOp @op @(ProcessSim (Payload op))+    makeOp' = makeOp @op @ProcessSim  genAndApplyOp     :: ( CmRDT op, Arbitrary (Intent op)@@ -128,7 +129,16 @@     => m [(Intent op, op)] genAndApplyOps = GenT.listOf genAndApplyOp -instance MonadGen m => MonadGen (ProcessSimT s m) where+instance MonadGen m => MonadGen (ProcessSimT m) where+    liftGen = lift . liftGen+    variant = undefined+    sized f = do+        size <- liftGen getSize+        f size+    resize = undefined+    choose = liftGen . choose++instance MonadGen m => MonadGen (StateT s m) where     liftGen = lift . liftGen     variant = undefined     sized f = do
test/LwwElementSet.hs view
@@ -25,19 +25,19 @@ test_Cv = cvrdtLaws @(LwwElementSet Char)  prop_add (s :: LwwElementSet Char) x pid1 =-    expectRight . runLamportClockSim undefined $ do+    expectRight . runLamportClockSim $ do         s1 <- runProcessSim pid1 $ add x s         pure $ lookup x s1  prop_remove (s :: LwwElementSet Char) x pid1 pid2 =-    expectRight . runLamportClockSim undefined $ do+    expectRight . runLamportClockSim $ do         s1 <- runProcessSim pid1 $ add x s         s2 <- runProcessSim pid2 $ remove x s1         pure . not $ lookup x s2  -- | Difference from 'TwoPSet' -- no removal bias prop_no_removal_bias (s :: LwwElementSet Char) x pid1 pid2 pid3 =-    expectRight . runLamportClockSim undefined $ do+    expectRight . runLamportClockSim $ do         s1 <- runProcessSim pid1 $ add x s         s2 <- runProcessSim pid2 $ remove x s1         s3 <- runProcessSim pid3 $ add x s2@@ -45,7 +45,7 @@  -- | Difference from 'ORSet' -- other replica can accidentally delete x prop_they_accidentally_delete_our_value (s :: LwwElementSet Char) x pid1 pid2 =-    expectRight . runLamportClockSim undefined $ do+    expectRight . runLamportClockSim $ do         s1 <- runProcessSim pid1 $ add x s         s2 <- runProcessSim pid2 $ remove x =<< add x s         pure . not . lookup x $ s1 <> s2
test/RGA.hs view
@@ -6,7 +6,7 @@  module RGA where -import           Control.Monad.State.Strict (get)+import           Control.Monad.State.Strict (execStateT, runStateT) import           Data.Maybe (isJust) import qualified Data.Vector as Vector import           Test.QuickCheck (conjoin, counterexample, (===))@@ -25,7 +25,7 @@ prop_makeOp =     isJust         (makeOp @(RGA Char) (AddAfter Nothing 'a') (initial @(RGA Char))-        :: Maybe (ProcessSim () (RGA Char)))+        :: Maybe (ProcessSim (RGA Char)))  prop_makeAndApplyOp = conjoin     [ counterexample "result3"  $ result3  === Right (op3, payload3)@@ -46,18 +46,19 @@     payload2 = load $ Vector.fromList [time2 :- Just '2', time3 :- Just '3']     payload12 = load $ Vector.fromList         [time2 :- Just '2', time1 :- Just '1', time3 :- Just '3']-    result3 = runLamportClockSim (initial @(RGA Char)) $-        runProcessSim (Pid 3) $ do+    result3 =+        runLamportClockSim .+        runProcessSim (Pid 3) .+        (`runStateT` initial @(RGA Char)) $ do             advance 2-            (,) <$> makeAndApplyOp @(RGA Char) (AddAfter Nothing '3')-                <*> get-    result2 = runLamportClockSim payload3 $ runProcessSim (Pid 2) $ do-        advance 1-        (,) <$> makeAndApplyOp @(RGA Char) (AddAfter Nothing '2')-            <*> get-    result1 = runLamportClockSim payload3 $ runProcessSim (Pid 1) $-        (,) <$> makeAndApplyOp @(RGA Char) (AddAfter Nothing '1')-            <*> get+            makeAndApplyOp @(RGA Char) (AddAfter Nothing '3')+    result2 =+        runLamportClockSim . runProcessSim (Pid 2) . (`runStateT` payload3) $ do+            advance 1+            makeAndApplyOp @(RGA Char) (AddAfter Nothing '2')+    result1 =+        runLamportClockSim . runProcessSim (Pid 1) . (`runStateT` payload3) $+            makeAndApplyOp @(RGA Char) (AddAfter Nothing '1')     result12 = apply op2 payload1     result21 = apply op1 payload2 @@ -66,16 +67,19 @@     Right (load $ Vector.fromList         [LamportTime t pid :- Just c | t <- [1..] | c <- s])   where-    result = runLamportClockSim (initial @(RGA Char)) $-        runProcessSim pid $ do-            _ <- fromString s-            get+    result =+        runLamportClockSim .+        runProcessSim pid .+        (`execStateT` initial @(RGA Char)) $+        fromString s  prop_fromString_toString s pid =     expectRightK result $ \s' -> toString s' === s   where-    result = runLamportClockSim (initial @(RGA Char)) $ runProcessSim pid $ do-        _ <- fromString s-        get+    result =+        runLamportClockSim .+        runProcessSim pid .+        (`execStateT` initial @(RGA Char)) $+        fromString s  prop_Cm = cmrdtLaw @(RGA Char)