module CRDT.Cv.GCounter ( GCounter (..) , initial , query -- * Operation , increment ) where import Data.IntMap.Strict (IntMap) import qualified Data.IntMap.Strict as IntMap import Data.Semilattice (Semilattice) -- | Grow-only counter. newtype GCounter a = GCounter (IntMap a) deriving (Eq, Show) instance Ord a => Semigroup (GCounter a) where GCounter x <> GCounter y = GCounter $ IntMap.unionWith max x y -- | See 'CvRDT' instance Ord a => Semilattice (GCounter a) -- | Increment counter increment :: Num a => Word -- ^ replica id -> GCounter a -> GCounter a increment replicaId (GCounter imap) = GCounter (IntMap.insertWith (+) i 1 imap) where i = fromIntegral replicaId -- | Initial state initial :: GCounter a initial = GCounter IntMap.empty -- | Get value from the state query :: Num a => GCounter a -> a query (GCounter v) = sum v