{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
module CRDT.Cm.TwoPSet
( TwoPSet (..)
) where
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import CRDT.Cm (CausalOrd (..), CmRDT (..))
data TwoPSet a = Add a | Remove a
deriving (Eq, Show)
instance Ord a => CmRDT (TwoPSet a) where
type Payload (TwoPSet a) = Map a Bool
initial = Map.empty
makeOp op payload = case op of
Add _ -> Just $ pure op
Remove a
| isKnown a -> Just $ pure op
| otherwise -> Nothing
where
isKnown a = Map.member a payload
apply = \case
Add a -> Map.insertWith (&&) a True
Remove a -> Map.insert a False
instance Eq a => CausalOrd (TwoPSet a) where
Add b `precedes` Remove a = a == b
_ `precedes` _ = False