{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

-- | A collection of useful combinators to shorten the code in other places.
--
-- This whole module provides ways to combine tables of two ledger states to
-- produce another one. It is written very much ad-hoc and we should probably
-- think of some way to make this more ergonomic. In particular for functions
-- that take two ledger states, it is unclear if it will keep the in-memory part
-- of the first or the second one.
module Ouroboros.Consensus.Ledger.Tables.Utils (
    -- * Projection and injection
    ltprj
  , ltwith
    -- * Basic operations
  , emptyLedgerTables
  , forgetLedgerTables
    -- * Operations on 'DiffMK'
    -- ** Apply diffs
  , applyDiffForKeys
  , applyDiffForKeysOnTables
  , applyDiffs
    -- ** Create diffs
  , calculateDifference
  , noNewTickingDiffs
  , valuesAsDiffs
    -- ** Combining diffs
  , prependDiffs
    -- * Operations on 'TrackingMK'
    -- ** Augment
  , attachAndApplyDiffs
  , attachEmptyDiffs
  , prependTrackingDiffs
    -- ** Reduce
  , trackingToDiffs
  , trackingToValues
    -- * Union values
  , unionValues
    -- * Exposed for @cardano-api@
  , applyDiffsMK
  , restrictValuesMK
    -- * Testing
  , applyDiffs'
  , rawAttachAndApplyDiffs -- used in test
  , rawCalculateDifference -- used in test
  , restrictValues'
  ) where

import qualified Data.Map.Strict as Map
import           Ouroboros.Consensus.Ledger.Tables
import qualified Ouroboros.Consensus.Ledger.Tables.Diff as Diff

{-------------------------------------------------------------------------------
  Projection and injection
-------------------------------------------------------------------------------}

ltwith ::
     ( HasLedgerTables l
     , CanMapMK mk'
     , CanMapKeysMK mk'
     , ZeroableMK mk'
     )
  => l mk
  -> LedgerTables l mk'
  -> l mk'
ltwith :: forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith = l mk -> LedgerTables l mk' -> l mk'
forall (mk :: MapKind) (any :: MapKind).
(CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l any -> LedgerTables l mk -> l mk
forall (l :: LedgerStateKind) (mk :: MapKind) (any :: MapKind).
(HasLedgerTables l, CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l any -> LedgerTables l mk -> l mk
withLedgerTables

ltprj ::
     (HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk)
  => l mk
  -> LedgerTables l' mk
ltprj :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj = LedgerTables l mk -> LedgerTables l' mk
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
SameUtxoTypes l l' =>
LedgerTables l mk -> LedgerTables l' mk
castLedgerTables (LedgerTables l mk -> LedgerTables l' mk)
-> (l mk -> LedgerTables l mk) -> l mk -> LedgerTables l' mk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. l mk -> LedgerTables l mk
forall (mk :: MapKind).
(CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l mk
forall (l :: LedgerStateKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l mk
projectLedgerTables

{-------------------------------------------------------------------------------
  Utils aliases: tables
-------------------------------------------------------------------------------}

-- | Replace tables with an empty diff. Can be used to specify that a ledger
-- state tick produces no new UTXO entries.
noNewTickingDiffs :: HasLedgerTables l
                  => l any
                  -> l DiffMK
noNewTickingDiffs :: forall (l :: LedgerStateKind) (any :: MapKind).
HasLedgerTables l =>
l any -> l DiffMK
noNewTickingDiffs l any
l = l any -> LedgerTables l DiffMK -> l DiffMK
forall (mk :: MapKind) (any :: MapKind).
(CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l any -> LedgerTables l mk -> l mk
forall (l :: LedgerStateKind) (mk :: MapKind) (any :: MapKind).
(HasLedgerTables l, CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l any -> LedgerTables l mk -> l mk
withLedgerTables l any
l LedgerTables l DiffMK
forall (mk :: MapKind) (l :: LedgerStateKind).
(ZeroableMK mk, LedgerTableConstraints l) =>
LedgerTables l mk
emptyLedgerTables

-- | Remove the ledger tables
forgetLedgerTables :: HasLedgerTables l => l mk -> l EmptyMK
forgetLedgerTables :: forall (l :: LedgerStateKind) (mk :: MapKind).
HasLedgerTables l =>
l mk -> l EmptyMK
forgetLedgerTables l mk
l = l mk -> LedgerTables l EmptyMK -> l EmptyMK
forall (mk :: MapKind) (any :: MapKind).
(CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l any -> LedgerTables l mk -> l mk
forall (l :: LedgerStateKind) (mk :: MapKind) (any :: MapKind).
(HasLedgerTables l, CanMapMK mk, CanMapKeysMK mk, ZeroableMK mk) =>
l any -> LedgerTables l mk -> l mk
withLedgerTables l mk
l LedgerTables l EmptyMK
forall (mk :: MapKind) (l :: LedgerStateKind).
(ZeroableMK mk, LedgerTableConstraints l) =>
LedgerTables l mk
emptyLedgerTables

-- | Empty values for every table
emptyLedgerTables :: (ZeroableMK mk, LedgerTableConstraints l) => LedgerTables l mk
emptyLedgerTables :: forall (mk :: MapKind) (l :: LedgerStateKind).
(ZeroableMK mk, LedgerTableConstraints l) =>
LedgerTables l mk
emptyLedgerTables = (forall k v. LedgerTableConstraints' l k v => mk k v)
-> LedgerTables l mk
forall (l :: LedgerStateKind) (mk :: MapKind).
LedgerTableConstraints l =>
(forall k v. LedgerTableConstraints' l k v => mk k v)
-> LedgerTables l mk
ltpure mk k v
forall k v. (Ord k, Eq v) => mk k v
forall k v. LedgerTableConstraints' l k v => mk k v
forall (mk :: MapKind) k v. (ZeroableMK mk, Ord k, Eq v) => mk k v
emptyMK

--
-- Forget parts of 'TrackingMK'
--

rawTrackingDiffs :: TrackingMK k v -> DiffMK k v
rawTrackingDiffs :: forall k v. TrackingMK k v -> DiffMK k v
rawTrackingDiffs (TrackingMK Map k v
_vs Diff k v
d) = Diff k v -> DiffMK k v
forall k v. Diff k v -> DiffMK k v
DiffMK Diff k v
d

trackingToDiffs :: (HasLedgerTables l, LedgerTableConstraints l) => l TrackingMK -> l DiffMK
trackingToDiffs :: forall (l :: LedgerStateKind).
(HasLedgerTables l, LedgerTableConstraints l) =>
l TrackingMK -> l DiffMK
trackingToDiffs l TrackingMK
l = l TrackingMK -> LedgerTables l DiffMK -> l DiffMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l TrackingMK
l (LedgerTables l DiffMK -> l DiffMK)
-> LedgerTables l DiffMK -> l DiffMK
forall a b. (a -> b) -> a -> b
$ (forall k v.
 LedgerTableConstraints' l k v =>
 TrackingMK k v -> DiffMK k v)
-> LedgerTables l TrackingMK -> LedgerTables l DiffMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind).
LedgerTableConstraints l =>
(forall k v. LedgerTableConstraints' l k v => mk1 k v -> mk2 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2
ltmap TrackingMK k v -> DiffMK k v
forall k v.
LedgerTableConstraints' l k v =>
TrackingMK k v -> DiffMK k v
forall k v. TrackingMK k v -> DiffMK k v
rawTrackingDiffs (l TrackingMK -> LedgerTables l TrackingMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l TrackingMK
l)

--
-- Forget diffs
--

rawTrackingValues :: TrackingMK k v -> ValuesMK k v
rawTrackingValues :: forall k v. TrackingMK k v -> ValuesMK k v
rawTrackingValues (TrackingMK Map k v
vs Diff k v
_ds) = Map k v -> ValuesMK k v
forall k v. Map k v -> ValuesMK k v
ValuesMK Map k v
vs

trackingToValues :: (LedgerTableConstraints l, HasLedgerTables l) => l TrackingMK -> l ValuesMK
trackingToValues :: forall (l :: LedgerStateKind).
(LedgerTableConstraints l, HasLedgerTables l) =>
l TrackingMK -> l ValuesMK
trackingToValues l TrackingMK
l = l TrackingMK -> LedgerTables l ValuesMK -> l ValuesMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l TrackingMK
l (LedgerTables l ValuesMK -> l ValuesMK)
-> LedgerTables l ValuesMK -> l ValuesMK
forall a b. (a -> b) -> a -> b
$ (forall k v.
 LedgerTableConstraints' l k v =>
 TrackingMK k v -> ValuesMK k v)
-> LedgerTables l TrackingMK -> LedgerTables l ValuesMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind).
LedgerTableConstraints l =>
(forall k v. LedgerTableConstraints' l k v => mk1 k v -> mk2 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2
ltmap TrackingMK k v -> ValuesMK k v
forall k v.
LedgerTableConstraints' l k v =>
TrackingMK k v -> ValuesMK k v
forall k v. TrackingMK k v -> ValuesMK k v
rawTrackingValues (l TrackingMK -> LedgerTables l TrackingMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l TrackingMK
l)

--
-- Prepend diffs
--

rawPrependDiffs ::
     Ord k
  => DiffMK k v -- ^ Earlier differences
  -> DiffMK k v -- ^ Later differences
  -> DiffMK k v
rawPrependDiffs :: forall k v. Ord k => DiffMK k v -> DiffMK k v -> DiffMK k v
rawPrependDiffs (DiffMK Diff k v
d1) (DiffMK Diff k v
d2) = Diff k v -> DiffMK k v
forall k v. Diff k v -> DiffMK k v
DiffMK (Diff k v
d1 Diff k v -> Diff k v -> Diff k v
forall a. Semigroup a => a -> a -> a
<> Diff k v
d2)

-- | Prepend diffs from the first ledger state to the diffs from the second
-- ledger state. Returns ledger tables.
prependDiffs' ::
     (SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => l DiffMK -> l' DiffMK -> LedgerTables l'' DiffMK
prependDiffs' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l DiffMK -> l' DiffMK -> LedgerTables l'' DiffMK
prependDiffs' l DiffMK
l1 l' DiffMK
l2 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 DiffMK k v -> DiffMK k v -> DiffMK k v)
-> LedgerTables l'' DiffMK
-> LedgerTables l'' DiffMK
-> LedgerTables l'' DiffMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2 -> LedgerTables l mk3
ltliftA2 DiffMK k v -> DiffMK k v -> DiffMK k v
forall k v. Ord k => DiffMK k v -> DiffMK k v -> DiffMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
DiffMK k v -> DiffMK k v -> DiffMK k v
rawPrependDiffs (l DiffMK -> LedgerTables l'' DiffMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l DiffMK
l1) (l' DiffMK -> LedgerTables l'' DiffMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' DiffMK
l2)

-- | Prepend the diffs from @l1@ to @l2@. Returns @l2@.
prependDiffs ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => l DiffMK -> l' DiffMK -> l' DiffMK
prependDiffs :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
l DiffMK -> l' DiffMK -> l' DiffMK
prependDiffs l DiffMK
l1 l' DiffMK
l2 = l' DiffMK -> LedgerTables l' DiffMK -> l' DiffMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' DiffMK
l2 (LedgerTables l' DiffMK -> l' DiffMK)
-> LedgerTables l' DiffMK -> l' DiffMK
forall a b. (a -> b) -> a -> b
$ l DiffMK -> l' DiffMK -> LedgerTables l' DiffMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l DiffMK -> l' DiffMK -> LedgerTables l'' DiffMK
prependDiffs' l DiffMK
l1 l' DiffMK
l2

--
-- Apply diffs
--

applyDiffsMK ::
     Ord k
  => ValuesMK k v -- ^ Values to which differences are applied
  -> DiffMK   k v -- ^ Differences to apply
  -> ValuesMK k v
applyDiffsMK :: forall k v. Ord k => ValuesMK k v -> DiffMK k v -> ValuesMK k v
applyDiffsMK (ValuesMK Map k v
vals) (DiffMK Diff k v
diffs) = Map k v -> ValuesMK k v
forall k v. Map k v -> ValuesMK k v
ValuesMK (Map k v -> Diff k v -> Map k v
forall k v. Ord k => Map k v -> Diff k v -> Map k v
Diff.applyDiff Map k v
vals Diff k v
diffs)

-- | Apply diffs from the second ledger state to the values of the first ledger
-- state. Returns ledger tables.
applyDiffs' ::
     (SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => l ValuesMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffs' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l ValuesMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffs' l ValuesMK
l1 l' DiffMK
l2 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 ValuesMK k v -> DiffMK k v -> ValuesMK k v)
-> LedgerTables l'' ValuesMK
-> LedgerTables l'' DiffMK
-> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2 -> LedgerTables l mk3
ltliftA2 ValuesMK k v -> DiffMK k v -> ValuesMK k v
forall k v. Ord k => ValuesMK k v -> DiffMK k v -> ValuesMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
ValuesMK k v -> DiffMK k v -> ValuesMK k v
applyDiffsMK (l ValuesMK -> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l ValuesMK
l1) (l' DiffMK -> LedgerTables l'' DiffMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' DiffMK
l2)

-- | Apply diffs from @l2@ on values from @l1@. Returns @l2@.
applyDiffs ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => l ValuesMK -> l' DiffMK -> l' ValuesMK
applyDiffs :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
l ValuesMK -> l' DiffMK -> l' ValuesMK
applyDiffs l ValuesMK
l1 l' DiffMK
l2 = l' DiffMK -> LedgerTables l' ValuesMK -> l' ValuesMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' DiffMK
l2 (LedgerTables l' ValuesMK -> l' ValuesMK)
-> LedgerTables l' ValuesMK -> l' ValuesMK
forall a b. (a -> b) -> a -> b
$ l ValuesMK -> l' DiffMK -> LedgerTables l' ValuesMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l ValuesMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffs' l ValuesMK
l1 l' DiffMK
l2

rawApplyDiffForKeys ::
     Ord k
  => ValuesMK k v
  -> KeysMK k v
  -> DiffMK k v
  -> ValuesMK k v
rawApplyDiffForKeys :: forall k v.
Ord k =>
ValuesMK k v -> KeysMK k v -> DiffMK k v -> ValuesMK k v
rawApplyDiffForKeys (ValuesMK Map k v
vals) (KeysMK Set k
keys) (DiffMK Diff k v
diffs) =
  Map k v -> ValuesMK k v
forall k v. Map k v -> ValuesMK k v
ValuesMK (Map k v -> Set k -> Diff k v -> Map k v
forall k v. Ord k => Map k v -> Set k -> Diff k v -> Map k v
Diff.applyDiffForKeys Map k v
vals Set k
keys Diff k v
diffs)

-- | Apply diffs in @l3@ for keys in @l2@ and @l1@ on values from @l1@. Returns @l3@.
applyDiffForKeys ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => l ValuesMK -> LedgerTables l KeysMK -> l' DiffMK -> l' ValuesMK
applyDiffForKeys :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
l ValuesMK -> LedgerTables l KeysMK -> l' DiffMK -> l' ValuesMK
applyDiffForKeys l ValuesMK
l1 LedgerTables l KeysMK
l2 l' DiffMK
l3 = l' DiffMK -> LedgerTables l' ValuesMK -> l' ValuesMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' DiffMK
l3 (LedgerTables l' ValuesMK -> l' ValuesMK)
-> LedgerTables l' ValuesMK -> l' ValuesMK
forall a b. (a -> b) -> a -> b
$ LedgerTables l ValuesMK
-> LedgerTables l KeysMK -> l' DiffMK -> LedgerTables l' ValuesMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l l', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
LedgerTables l ValuesMK
-> LedgerTables l KeysMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffForKeys' (l ValuesMK -> LedgerTables l ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l ValuesMK
l1) LedgerTables l KeysMK
l2 l' DiffMK
l3

applyDiffForKeys' ::
     (SameUtxoTypes l l'', SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => LedgerTables l ValuesMK -> LedgerTables l KeysMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffForKeys' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l l', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
LedgerTables l ValuesMK
-> LedgerTables l KeysMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffForKeys' LedgerTables l ValuesMK
l1 LedgerTables l KeysMK
l2 l' DiffMK
l3 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 ValuesMK k v -> KeysMK k v -> DiffMK k v -> ValuesMK k v)
-> LedgerTables l'' ValuesMK
-> LedgerTables l'' KeysMK
-> LedgerTables l'' DiffMK
-> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind) (mk4 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v -> mk4 k v)
-> LedgerTables l mk1
-> LedgerTables l mk2
-> LedgerTables l mk3
-> LedgerTables l mk4
ltliftA3 ValuesMK k v -> KeysMK k v -> DiffMK k v -> ValuesMK k v
forall k v.
Ord k =>
ValuesMK k v -> KeysMK k v -> DiffMK k v -> ValuesMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
ValuesMK k v -> KeysMK k v -> DiffMK k v -> ValuesMK k v
rawApplyDiffForKeys (LedgerTables l ValuesMK -> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
SameUtxoTypes l l' =>
LedgerTables l mk -> LedgerTables l' mk
castLedgerTables LedgerTables l ValuesMK
l1) (LedgerTables l KeysMK -> LedgerTables l'' KeysMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
SameUtxoTypes l l' =>
LedgerTables l mk -> LedgerTables l' mk
castLedgerTables LedgerTables l KeysMK
l2) (l' DiffMK -> LedgerTables l'' DiffMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' DiffMK
l3)

-- | Apply diffs in @l3@ for keys in @l2@ and @l1@ on values from @l1@. Returns @l3@.
applyDiffForKeysOnTables ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => LedgerTables l ValuesMK -> LedgerTables l KeysMK -> l' DiffMK -> l' ValuesMK
applyDiffForKeysOnTables :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
LedgerTables l ValuesMK
-> LedgerTables l KeysMK -> l' DiffMK -> l' ValuesMK
applyDiffForKeysOnTables LedgerTables l ValuesMK
l1 LedgerTables l KeysMK
l2 l' DiffMK
l3 = l' DiffMK -> LedgerTables l' ValuesMK -> l' ValuesMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' DiffMK
l3 (LedgerTables l' ValuesMK -> l' ValuesMK)
-> LedgerTables l' ValuesMK -> l' ValuesMK
forall a b. (a -> b) -> a -> b
$ LedgerTables l ValuesMK
-> LedgerTables l KeysMK -> l' DiffMK -> LedgerTables l' ValuesMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l l', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
LedgerTables l ValuesMK
-> LedgerTables l KeysMK -> l' DiffMK -> LedgerTables l'' ValuesMK
applyDiffForKeys' LedgerTables l ValuesMK
l1 LedgerTables l KeysMK
l2 l' DiffMK
l3

--
-- Calculate differences
--

rawCalculateDifference ::
     (Ord k, Eq v)
  => ValuesMK   k v
  -> ValuesMK   k v
  -> TrackingMK k v
rawCalculateDifference :: forall k v.
(Ord k, Eq v) =>
ValuesMK k v -> ValuesMK k v -> TrackingMK k v
rawCalculateDifference (ValuesMK Map k v
before) (ValuesMK Map k v
after) = Map k v -> Diff k v -> TrackingMK k v
forall k v. Map k v -> Diff k v -> TrackingMK k v
TrackingMK Map k v
after (Map k v -> Map k v -> Diff k v
forall k v. (Ord k, Eq v) => Map k v -> Map k v -> Diff k v
Diff.diff Map k v
before Map k v
after)

-- | Promote values to diffs, for cases in which all existing values must be
-- considered diffs. In particular this is used when populating the ledger
-- tables for the first time.
valuesAsDiffs ::
     (LedgerTableConstraints l, HasLedgerTables l)
  => l ValuesMK -> l DiffMK
valuesAsDiffs :: forall (l :: LedgerStateKind).
(LedgerTableConstraints l, HasLedgerTables l) =>
l ValuesMK -> l DiffMK
valuesAsDiffs l ValuesMK
l = l TrackingMK -> l DiffMK
forall (l :: LedgerStateKind).
(HasLedgerTables l, LedgerTableConstraints l) =>
l TrackingMK -> l DiffMK
trackingToDiffs (l TrackingMK -> l DiffMK) -> l TrackingMK -> l DiffMK
forall a b. (a -> b) -> a -> b
$ l ValuesMK -> LedgerTables l TrackingMK -> l TrackingMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l ValuesMK
l (LedgerTables l TrackingMK -> l TrackingMK)
-> LedgerTables l TrackingMK -> l TrackingMK
forall a b. (a -> b) -> a -> b
$ (forall k v.
 LedgerTableConstraints' l k v =>
 ValuesMK k v -> TrackingMK k v)
-> LedgerTables l ValuesMK -> LedgerTables l TrackingMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind).
LedgerTableConstraints l =>
(forall k v. LedgerTableConstraints' l k v => mk1 k v -> mk2 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2
ltliftA (ValuesMK k v -> ValuesMK k v -> TrackingMK k v
forall k v.
(Ord k, Eq v) =>
ValuesMK k v -> ValuesMK k v -> TrackingMK k v
rawCalculateDifference ValuesMK k v
forall k v. (Ord k, Eq v) => ValuesMK k v
forall (mk :: MapKind) k v. (ZeroableMK mk, Ord k, Eq v) => mk k v
emptyMK) (l ValuesMK -> LedgerTables l ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l ValuesMK
l)

-- | Calculate the differences between two ledger states. The first ledger state
-- is considered /before/, the second ledger state is considered /after/.
-- Returns ledger tables.
calculateDifference' ::
     (SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => l ValuesMK -> l' ValuesMK -> LedgerTables l'' TrackingMK
calculateDifference' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l ValuesMK -> l' ValuesMK -> LedgerTables l'' TrackingMK
calculateDifference' l ValuesMK
l1 l' ValuesMK
l2 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 ValuesMK k v -> ValuesMK k v -> TrackingMK k v)
-> LedgerTables l'' ValuesMK
-> LedgerTables l'' ValuesMK
-> LedgerTables l'' TrackingMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2 -> LedgerTables l mk3
ltliftA2 ValuesMK k v -> ValuesMK k v -> TrackingMK k v
forall k v.
(Ord k, Eq v) =>
ValuesMK k v -> ValuesMK k v -> TrackingMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
ValuesMK k v -> ValuesMK k v -> TrackingMK k v
rawCalculateDifference (l ValuesMK -> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l ValuesMK
l1) (l' ValuesMK -> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' ValuesMK
l2)

-- | Calculate the differences between two ledger states. The first ledger state
-- is considered /before/, the second ledger state is considered /after/.
-- Returns the second ledger state.
calculateDifference ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => l ValuesMK -> l' ValuesMK -> l' TrackingMK
calculateDifference :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
l ValuesMK -> l' ValuesMK -> l' TrackingMK
calculateDifference l ValuesMK
l1 l' ValuesMK
l2 = l' ValuesMK -> LedgerTables l' TrackingMK -> l' TrackingMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' ValuesMK
l2 (LedgerTables l' TrackingMK -> l' TrackingMK)
-> LedgerTables l' TrackingMK -> l' TrackingMK
forall a b. (a -> b) -> a -> b
$ l ValuesMK -> l' ValuesMK -> LedgerTables l' TrackingMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l ValuesMK -> l' ValuesMK -> LedgerTables l'' TrackingMK
calculateDifference' l ValuesMK
l1 l' ValuesMK
l2

--
-- Attaching and/or applying diffs
--

rawAttachAndApplyDiffs ::
     Ord k
  => ValuesMK   k v
  -> DiffMK     k v
  -> TrackingMK k v
rawAttachAndApplyDiffs :: forall k v. Ord k => ValuesMK k v -> DiffMK k v -> TrackingMK k v
rawAttachAndApplyDiffs (ValuesMK Map k v
v) (DiffMK Diff k v
d) = Map k v -> Diff k v -> TrackingMK k v
forall k v. Map k v -> Diff k v -> TrackingMK k v
TrackingMK (Map k v -> Diff k v -> Map k v
forall k v. Ord k => Map k v -> Diff k v -> Map k v
Diff.applyDiff Map k v
v Diff k v
d) Diff k v
d

-- | Apply the differences from the first ledger state to the values of the
-- second ledger state, and returns the resulting values together with the
-- applied diff.
attachAndApplyDiffs' ::
     (SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => l' ValuesMK -> l DiffMK -> LedgerTables l'' TrackingMK
attachAndApplyDiffs' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l' ValuesMK -> l DiffMK -> LedgerTables l'' TrackingMK
attachAndApplyDiffs' l' ValuesMK
l1 l DiffMK
l2 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 ValuesMK k v -> DiffMK k v -> TrackingMK k v)
-> LedgerTables l'' ValuesMK
-> LedgerTables l'' DiffMK
-> LedgerTables l'' TrackingMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2 -> LedgerTables l mk3
ltliftA2 ValuesMK k v -> DiffMK k v -> TrackingMK k v
forall k v. Ord k => ValuesMK k v -> DiffMK k v -> TrackingMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
ValuesMK k v -> DiffMK k v -> TrackingMK k v
rawAttachAndApplyDiffs (l' ValuesMK -> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' ValuesMK
l1) (l DiffMK -> LedgerTables l'' DiffMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l DiffMK
l2)

-- | Apply the differences from the first ledger state to the values of the
-- second ledger state. Returns the second ledger state with a 'TrackingMK' of
-- the final values and all the diffs.
attachAndApplyDiffs ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => l ValuesMK -> l' DiffMK -> l' TrackingMK
attachAndApplyDiffs :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
l ValuesMK -> l' DiffMK -> l' TrackingMK
attachAndApplyDiffs l ValuesMK
l1 l' DiffMK
l2 = l' DiffMK -> LedgerTables l' TrackingMK -> l' TrackingMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' DiffMK
l2 (LedgerTables l' TrackingMK -> l' TrackingMK)
-> LedgerTables l' TrackingMK -> l' TrackingMK
forall a b. (a -> b) -> a -> b
$ l ValuesMK -> l' DiffMK -> LedgerTables l' TrackingMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l' ValuesMK -> l DiffMK -> LedgerTables l'' TrackingMK
attachAndApplyDiffs' l ValuesMK
l1 l' DiffMK
l2

rawAttachEmptyDiffs :: Ord k => ValuesMK k v -> TrackingMK k v
rawAttachEmptyDiffs :: forall k v. Ord k => ValuesMK k v -> TrackingMK k v
rawAttachEmptyDiffs (ValuesMK Map k v
v) = Map k v -> Diff k v -> TrackingMK k v
forall k v. Map k v -> Diff k v -> TrackingMK k v
TrackingMK Map k v
v Diff k v
forall a. Monoid a => a
mempty

-- | Make a 'TrackingMK' with empty diffs.
attachEmptyDiffs :: HasLedgerTables l => l ValuesMK -> l TrackingMK
attachEmptyDiffs :: forall (l :: LedgerStateKind).
HasLedgerTables l =>
l ValuesMK -> l TrackingMK
attachEmptyDiffs l ValuesMK
l1 = l ValuesMK -> LedgerTables l TrackingMK -> l TrackingMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l ValuesMK
l1 (LedgerTables l TrackingMK -> l TrackingMK)
-> LedgerTables l TrackingMK -> l TrackingMK
forall a b. (a -> b) -> a -> b
$ (forall k v.
 LedgerTableConstraints' l k v =>
 ValuesMK k v -> TrackingMK k v)
-> LedgerTables l ValuesMK -> LedgerTables l TrackingMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind).
LedgerTableConstraints l =>
(forall k v. LedgerTableConstraints' l k v => mk1 k v -> mk2 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2
ltmap ValuesMK k v -> TrackingMK k v
forall k v. Ord k => ValuesMK k v -> TrackingMK k v
forall k v.
LedgerTableConstraints' l k v =>
ValuesMK k v -> TrackingMK k v
rawAttachEmptyDiffs (l ValuesMK -> LedgerTables l ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l ValuesMK
l1)

--
-- Prepend tracking diffs
--

-- | Prepend the former tracking diffs to the latter tracking diffs. Keep the
-- second tracking values.
--
-- PRECONDITION: Given that the first argument is @TrackingMK v1 d1@, and the
-- second argument is @TrackingMK v2 d2@, it should be the case that @applyDiff
-- v1 d2 == v2@.
rawPrependTrackingDiffs ::
      Ord k
   => TrackingMK k v
   -> TrackingMK k v
   -> TrackingMK k v
rawPrependTrackingDiffs :: forall k v.
Ord k =>
TrackingMK k v -> TrackingMK k v -> TrackingMK k v
rawPrependTrackingDiffs (TrackingMK Map k v
_ Diff k v
d1) (TrackingMK Map k v
v Diff k v
d2) =
  Map k v -> Diff k v -> TrackingMK k v
forall k v. Map k v -> Diff k v -> TrackingMK k v
TrackingMK Map k v
v (Diff k v
d1 Diff k v -> Diff k v -> Diff k v
forall a. Semigroup a => a -> a -> a
<> Diff k v
d2)

-- | Prepend tracking diffs from the first ledger state to the tracking diffs
-- from the second ledger state. Keep the tracking values of the second ledger
-- state.
--
-- PRECONDITION:  See 'rawPrependTrackingDiffs'.
prependTrackingDiffs' ::
     (SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => l TrackingMK -> l' TrackingMK -> LedgerTables l'' TrackingMK
prependTrackingDiffs' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l TrackingMK -> l' TrackingMK -> LedgerTables l'' TrackingMK
prependTrackingDiffs' l TrackingMK
l1 l' TrackingMK
l2 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 TrackingMK k v -> TrackingMK k v -> TrackingMK k v)
-> LedgerTables l'' TrackingMK
-> LedgerTables l'' TrackingMK
-> LedgerTables l'' TrackingMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2 -> LedgerTables l mk3
ltliftA2 TrackingMK k v -> TrackingMK k v -> TrackingMK k v
forall k v.
Ord k =>
TrackingMK k v -> TrackingMK k v -> TrackingMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
TrackingMK k v -> TrackingMK k v -> TrackingMK k v
rawPrependTrackingDiffs (l TrackingMK -> LedgerTables l'' TrackingMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l TrackingMK
l1) (l' TrackingMK -> LedgerTables l'' TrackingMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' TrackingMK
l2)

-- | Prepend tracking diffs from the first ledger state to the tracking diffs
-- from the second ledger state. Keep the tracking values of the second ledger
-- state. Returns the second ledger state.
--
-- PRECONDITION:  See 'rawPrependTrackingDiffs'.
prependTrackingDiffs ::
     (SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l')
  => l TrackingMK -> l' TrackingMK -> l' TrackingMK
prependTrackingDiffs :: forall (l :: LedgerStateKind) (l' :: LedgerStateKind).
(SameUtxoTypes l l', HasLedgerTables l, HasLedgerTables l') =>
l TrackingMK -> l' TrackingMK -> l' TrackingMK
prependTrackingDiffs l TrackingMK
l1 l' TrackingMK
l2 = l' TrackingMK -> LedgerTables l' TrackingMK -> l' TrackingMK
forall (l :: LedgerStateKind) (mk' :: MapKind) (mk :: MapKind).
(HasLedgerTables l, CanMapMK mk', CanMapKeysMK mk',
 ZeroableMK mk') =>
l mk -> LedgerTables l mk' -> l mk'
ltwith l' TrackingMK
l2 (LedgerTables l' TrackingMK -> l' TrackingMK)
-> LedgerTables l' TrackingMK -> l' TrackingMK
forall a b. (a -> b) -> a -> b
$ l TrackingMK -> l' TrackingMK -> LedgerTables l' TrackingMK
forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l TrackingMK -> l' TrackingMK -> LedgerTables l'' TrackingMK
prependTrackingDiffs' l TrackingMK
l1 l' TrackingMK
l2

-- Restrict values

restrictValuesMK ::
     Ord k
  => ValuesMK k v
  -> KeysMK k v
  -> ValuesMK k v
restrictValuesMK :: forall k v. Ord k => ValuesMK k v -> KeysMK k v -> ValuesMK k v
restrictValuesMK (ValuesMK Map k v
v) (KeysMK Set k
k) = Map k v -> ValuesMK k v
forall k v. Map k v -> ValuesMK k v
ValuesMK (Map k v -> ValuesMK k v) -> Map k v -> ValuesMK k v
forall a b. (a -> b) -> a -> b
$ Map k v
v Map k v -> Set k -> Map k v
forall k a. Ord k => Map k a -> Set k -> Map k a
`Map.restrictKeys` Set k
k

restrictValues' ::
     (SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l, HasLedgerTables l', HasLedgerTables l'')
  => l ValuesMK -> l' KeysMK -> LedgerTables l'' ValuesMK
restrictValues' :: forall (l :: LedgerStateKind) (l'' :: LedgerStateKind)
       (l' :: LedgerStateKind).
(SameUtxoTypes l l'', SameUtxoTypes l' l'', HasLedgerTables l,
 HasLedgerTables l', HasLedgerTables l'') =>
l ValuesMK -> l' KeysMK -> LedgerTables l'' ValuesMK
restrictValues' l ValuesMK
l1 l' KeysMK
l2 = (forall k v.
 LedgerTableConstraints' l'' k v =>
 ValuesMK k v -> KeysMK k v -> ValuesMK k v)
-> LedgerTables l'' ValuesMK
-> LedgerTables l'' KeysMK
-> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (mk1 :: MapKind) (mk2 :: MapKind)
       (mk3 :: MapKind).
LedgerTableConstraints l =>
(forall k v.
 LedgerTableConstraints' l k v =>
 mk1 k v -> mk2 k v -> mk3 k v)
-> LedgerTables l mk1 -> LedgerTables l mk2 -> LedgerTables l mk3
ltliftA2 ValuesMK k v -> KeysMK k v -> ValuesMK k v
forall k v. Ord k => ValuesMK k v -> KeysMK k v -> ValuesMK k v
forall k v.
LedgerTableConstraints' l'' k v =>
ValuesMK k v -> KeysMK k v -> ValuesMK k v
restrictValuesMK (l ValuesMK -> LedgerTables l'' ValuesMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l ValuesMK
l1) (l' KeysMK -> LedgerTables l'' KeysMK
forall (l :: LedgerStateKind) (l' :: LedgerStateKind)
       (mk :: MapKind).
(HasLedgerTables l, SameUtxoTypes l l', CanMapMK mk,
 CanMapKeysMK mk, ZeroableMK mk) =>
l mk -> LedgerTables l' mk
ltprj l' KeysMK
l2)

---

-- | For this first UTxO-HD iteration, there can't be two keys with
-- different values on the tables, thus there will never be
-- conflicting collisions.
unionValues ::
     Ord k
  => ValuesMK k v
  -> ValuesMK k v
  -> ValuesMK k v
unionValues :: forall k v. Ord k => ValuesMK k v -> ValuesMK k v -> ValuesMK k v
unionValues (ValuesMK Map k v
m1) (ValuesMK Map k v
m2) = Map k v -> ValuesMK k v
forall k v. Map k v -> ValuesMK k v
ValuesMK (Map k v -> ValuesMK k v) -> Map k v -> ValuesMK k v
forall a b. (a -> b) -> a -> b
$ Map k v -> Map k v -> Map k v
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union Map k v
m1 Map k v
m2