{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}

module CRDT.Cm.Counter
    ( Counter (..)
    ) where

import           CRDT.Cm (CausalOrd (..), CmRDT (..))

data Counter a = Increment | Decrement
    deriving (Counter a
Counter a -> Counter a -> Bounded (Counter a)
forall a. Counter a
forall a. a -> a -> Bounded a
maxBound :: Counter a
$cmaxBound :: forall a. Counter a
minBound :: Counter a
$cminBound :: forall a. Counter a
Bounded, Int -> Counter a
Counter a -> Int
Counter a -> [Counter a]
Counter a -> Counter a
Counter a -> Counter a -> [Counter a]
Counter a -> Counter a -> Counter a -> [Counter a]
(Counter a -> Counter a)
-> (Counter a -> Counter a)
-> (Int -> Counter a)
-> (Counter a -> Int)
-> (Counter a -> [Counter a])
-> (Counter a -> Counter a -> [Counter a])
-> (Counter a -> Counter a -> [Counter a])
-> (Counter a -> Counter a -> Counter a -> [Counter a])
-> Enum (Counter a)
forall a. Int -> Counter a
forall a. Counter a -> Int
forall a. Counter a -> [Counter a]
forall a. Counter a -> Counter a
forall a. Counter a -> Counter a -> [Counter a]
forall a. Counter a -> Counter a -> Counter a -> [Counter a]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Counter a -> Counter a -> Counter a -> [Counter a]
$cenumFromThenTo :: forall a. Counter a -> Counter a -> Counter a -> [Counter a]
enumFromTo :: Counter a -> Counter a -> [Counter a]
$cenumFromTo :: forall a. Counter a -> Counter a -> [Counter a]
enumFromThen :: Counter a -> Counter a -> [Counter a]
$cenumFromThen :: forall a. Counter a -> Counter a -> [Counter a]
enumFrom :: Counter a -> [Counter a]
$cenumFrom :: forall a. Counter a -> [Counter a]
fromEnum :: Counter a -> Int
$cfromEnum :: forall a. Counter a -> Int
toEnum :: Int -> Counter a
$ctoEnum :: forall a. Int -> Counter a
pred :: Counter a -> Counter a
$cpred :: forall a. Counter a -> Counter a
succ :: Counter a -> Counter a
$csucc :: forall a. Counter a -> Counter a
Enum, Counter a -> Counter a -> Bool
(Counter a -> Counter a -> Bool)
-> (Counter a -> Counter a -> Bool) -> Eq (Counter a)
forall a. Counter a -> Counter a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Counter a -> Counter a -> Bool
$c/= :: forall a. Counter a -> Counter a -> Bool
== :: Counter a -> Counter a -> Bool
$c== :: forall a. Counter a -> Counter a -> Bool
Eq, Int -> Counter a -> ShowS
[Counter a] -> ShowS
Counter a -> String
(Int -> Counter a -> ShowS)
-> (Counter a -> String)
-> ([Counter a] -> ShowS)
-> Show (Counter a)
forall a. Int -> Counter a -> ShowS
forall a. [Counter a] -> ShowS
forall a. Counter a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Counter a] -> ShowS
$cshowList :: forall a. [Counter a] -> ShowS
show :: Counter a -> String
$cshow :: forall a. Counter a -> String
showsPrec :: Int -> Counter a -> ShowS
$cshowsPrec :: forall a. Int -> Counter a -> ShowS
Show)

instance (Num a, Eq a) => CmRDT (Counter a) where
    type Payload (Counter a) = a

    initial :: Payload (Counter a)
initial = Payload (Counter a)
0

    apply :: Counter a -> Payload (Counter a) -> Payload (Counter a)
apply = \case
        Counter a
Increment -> (a -> a -> a
forall a. Num a => a -> a -> a
+ a
1)
        Counter a
Decrement -> a -> a -> a
forall a. Num a => a -> a -> a
subtract a
1

-- | Empty order, allowing arbitrary reordering
instance CausalOrd (Counter a) where
    precedes :: Counter a -> Counter a -> Bool
precedes Counter a
_ Counter a
_ = Bool
False