Skip to content
Snippets Groups Projects
Delta.hs 1.39 KiB
Newer Older
Jens Nolte's avatar
Jens Nolte committed
module Qd.Observable.Delta where

import Qd.Observable
import Qd.Prelude

import Conduit
import qualified Data.HashMap.Strict as HM
import Data.Binary (Binary(..))
Jens Nolte's avatar
Jens Nolte committed

data Delta k v = Reset (HM.HashMap k v) | Add k v | Change k v | Remove k
  deriving (Eq, Show, Generic)
instance (Binary k, Binary v) => Binary (Delta k v) where
  get = undefined
  put = undefined

class Observable (HM.HashMap k v) o => DeltaObservable k v o | o -> k, o -> v where
  subscribeDelta :: o -> (Delta k v -> IO ()) -> IO SubscriptionHandle
  subscribeDelta = undefined
  subscribeDeltaC :: o -> ConduitT () (Delta k v) IO ()
  subscribeDeltaC = undefined
  {-# MINIMAL subscribeDelta | subscribeDeltaC #-}

observeHashMapDefaultImpl :: forall k v o. (Eq k, Hashable k) => DeltaObservable k v o => o -> (HM.HashMap k v -> IO ()) -> IO SubscriptionHandle
observeHashMapDefaultImpl o callback = do
  hashMapRef <- newIORef HM.empty
  subscribeDelta o (deltaCallback hashMapRef)
  where
    deltaCallback :: IORef (HM.HashMap k v) -> Delta k v -> IO ()
    deltaCallback hashMapRef delta = callback =<< atomicModifyIORef' hashMapRef ((\x->(x,x)) . (applyDelta delta))
    applyDelta :: Delta k v -> HM.HashMap k v -> HM.HashMap k v
    applyDelta (Reset state) = const state
    applyDelta (Add key value) = HM.insert key value
    applyDelta (Change key value) = HM.insert key value
    applyDelta (Remove key) = HM.delete key