{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

{-|
Copyright: © 2021-2023 IOHK, 2024 Cardano Foundation
License: Apache-2.0

Delta types for 'Data.Map.Map'.
-}
module Data.Delta.Map
    ( DeltaMap(..)
    ) where

import Prelude

import Data.Delta.Core
    ( Delta (..)
    )
import Data.Map.Strict
    ( Map
    )
import qualified Data.Map.Strict as Map

{-------------------------------------------------------------------------------
    Delta type for 'Map'
-------------------------------------------------------------------------------}
-- | Delta type for 'Map'.
data DeltaMap key da
    = Insert key (Base da)
    | Delete key
    | Adjust key da

deriving instance (Show key, Show da, Show (Base da)) => Show (DeltaMap key da)
instance (Ord key, Delta da)
    => Delta (DeltaMap key da) where
    type Base (DeltaMap key da) = Map key (Base da)
    apply :: DeltaMap key da -> Base (DeltaMap key da) -> Base (DeltaMap key da)
apply (Insert key
key Base da
a) = key -> Base da -> Map key (Base da) -> Map key (Base da)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert key
key Base da
a
    apply (Delete key
key) = key -> Map key (Base da) -> Map key (Base da)
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete key
key
    apply (Adjust key
key da
da) = (Base da -> Base da)
-> key -> Map key (Base da) -> Map key (Base da)
forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
Map.adjust (da -> Base da -> Base da
forall delta. Delta delta => delta -> Base delta -> Base delta
apply da
da) key
key