{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module Ouroboros.Consensus.Ledger.Tables.Basics
  ( -- * Kinds

    -- | For convenience' sake, we define these kinds which convey the intended
    -- instantiation for the type variables.
    LedgerStateKind
  , MapKind
  , StateKind

    -- * Ledger tables
  , LedgerTables (..)
  , TxIn
  , TxOut
  ) where

import Data.Kind (Type)
import GHC.Generics (Generic)
import NoThunks.Class (NoThunks)
import Ouroboros.Consensus.Ledger.Tables.Kinds

{-------------------------------------------------------------------------------
  Ledger tables
-------------------------------------------------------------------------------}

-- | The Ledger Tables represent the portion of the data on disk that has been
-- pulled from disk and attached to the in-memory Ledger State or that will
-- eventually be written to disk.
--
-- With UTxO-HD and the split of the Ledger /ledger state/ into the in-memory
-- part and the on-disk part, this splitting was reflected in the new type
-- parameter added to the (Consensus)
-- 'Ouroboros.Consensus.Ledger.Basics.LedgerState', to which we refer as "the
-- MapKind" or @mk@.
--
-- Every 'Ouroboros.Consensus.Ledger.Basics.LedgerState' (or @LedgerState@-like
-- type, such as the 'Ouroboros.Consensus.Ledger.Extended.ExtLedgerState') is
-- associated with a 'LedgerTables' and they both share the @mk@. They both are
-- of kind 'LedgerStateKind'. 'LedgerTables' is just a way to refer /only/ to a
-- partial view of the on-disk data without having the rest of the in-memory
-- 'LedgerState' in scope.
--
-- The @mk@ can be instantiated to anything that is map-like, i.e. that expects
-- two type parameters, the key and the value.
type LedgerTables :: Type -> MapKind -> Type
newtype LedgerTables blk mk = LedgerTables
  { forall blk (mk :: MapKind).
LedgerTables blk mk -> mk (TxIn blk) (TxOut blk)
getLedgerTables :: mk (TxIn blk) (TxOut blk)
  }
  deriving stock (forall x. LedgerTables blk mk -> Rep (LedgerTables blk mk) x)
-> (forall x. Rep (LedgerTables blk mk) x -> LedgerTables blk mk)
-> Generic (LedgerTables blk mk)
forall x. Rep (LedgerTables blk mk) x -> LedgerTables blk mk
forall x. LedgerTables blk mk -> Rep (LedgerTables blk mk) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall blk (mk :: MapKind) x.
Rep (LedgerTables blk mk) x -> LedgerTables blk mk
forall blk (mk :: MapKind) x.
LedgerTables blk mk -> Rep (LedgerTables blk mk) x
$cfrom :: forall blk (mk :: MapKind) x.
LedgerTables blk mk -> Rep (LedgerTables blk mk) x
from :: forall x. LedgerTables blk mk -> Rep (LedgerTables blk mk) x
$cto :: forall blk (mk :: MapKind) x.
Rep (LedgerTables blk mk) x -> LedgerTables blk mk
to :: forall x. Rep (LedgerTables blk mk) x -> LedgerTables blk mk
Generic

deriving stock instance
  Show (mk (TxIn blk) (TxOut blk)) =>
  Show (LedgerTables blk mk)
deriving stock instance
  Eq (mk (TxIn blk) (TxOut blk)) =>
  Eq (LedgerTables blk mk)
deriving newtype instance
  NoThunks (mk (TxIn blk) (TxOut blk)) =>
  NoThunks (LedgerTables blk mk)

-- | Each @LedgerState@ instance will have the notion of a @TxIn@ for the tables.
--
-- This will change once there is more than one table.
type TxIn :: Type -> Type
type family TxIn blk

-- | Each @LedgerState@ instance will have the notion of a @TxOut@ for the
-- tables.
--
-- This will change once there is more than one table.
type TxOut :: Type -> Type
type family TxOut blk