crdt-1.0: lib/CRDT/Cv/LWW.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeFamilies #-}
module CRDT.Cv.LWW
( LWW (..)
, initial
, assign
, query
) where
import Data.Function (on)
import Data.Semigroup (Semigroup, (<>))
import Lens.Micro ((<&>))
import CRDT.Cv (CvRDT)
import LamportClock (Clock (newTimestamp), Timestamp)
-- | Last write wins. Assuming timestamp is unique.
data LWW a = LWW
{ timestamp :: !Timestamp
, value :: !a
}
deriving (Show)
instance Eq (LWW a) where
(==) = (==) `on` timestamp
instance Ord (LWW a) where
(<=) = (<=) `on` timestamp
-- | Merge by choosing more recent timestamp.
instance Semigroup (LWW a) where
(<>) = max
instance CvRDT (LWW a)
-- | Initialize state
initial :: Clock f => a -> f (LWW a)
initial value = newTimestamp <&> \timestamp -> LWW{timestamp = timestamp, value}
-- | Change state
assign :: Clock f => a -> LWW a -> f (LWW a)
assign value cur = newTimestamp <&> \timestamp -> cur <> LWW{timestamp, value}
-- | Query state
query :: LWW a -> a
query = value