{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ViewPatterns #-}

module Plutarch.Extra.Value (
  -- * Creation
  passetClassDataValue,
  passetClassDataValueT,
  psingleValue,
  psingleValue',
  psingleValueT',
  pvalue,
  pvaluePositive,

  -- * Queries
  padaOf,
  passetClassValueOf',
  passetClassValueOf,
  passetClassValueOfT',
  passetClassValueOfT,
  passetClassDataValueOf,
  passetClassDataValueOfT,
  pmatchValueAssets,
  psplitValue,

  -- * Aggregation and elimination
  psymbolValueOf,
  psymbolValueOf',
  precValue,
  pelimValue,

  -- * Comparison
  pbyClassComparator,
  pbySymbolComparator,
  pbyClassComparator',

  -- * Miscellaneous
  AddGuarantees,
  phasOnlyOneTokenOfCurrencySymbol,
  phasOneTokenOfCurrencySymbol,
  phasOneTokenOfAssetClass,
  phasOneTokenOfAssetClassData,
  pcountNonZeroes,
) where

import Data.List (nub, sort)
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Tagged (Tagged (Tagged))
import GHC.TypeLits (Symbol)
import Optics.Getter (A_Getter, view)
import Optics.Internal.Optic (Is)
import Optics.Label (LabelOptic')
import Plutarch.Api.V1 (
  AmountGuarantees (NonZero),
  PCurrencySymbol,
  PMap (PMap),
  PTokenName,
  PValue (PValue),
 )
import Plutarch.Api.V1.AssocMap (plookup)
import Plutarch.Api.V1.AssocMap qualified as AssocMap
import Plutarch.Api.V1.Value (padaSymbol)
import Plutarch.Api.V1.Value qualified as Value
import Plutarch.Api.V2 (
  AmountGuarantees (NoGuarantees, Positive),
  KeyGuarantees (Sorted),
 )
import Plutarch.Builtin (pforgetData, ppairDataBuiltin)
import Plutarch.DataRepr.Internal.Field (HRec (HCons, HNil), Labeled (Labeled))
import Plutarch.Extra.Applicative (ppure)
import Plutarch.Extra.AssetClass (
  AssetClass (AssetClass),
  PAssetClass (PAssetClass),
  PAssetClassData,
 )
import Plutarch.Extra.Comonad (pextract)
import Plutarch.Extra.Functor (PFunctor (pfmap))
import Plutarch.Extra.IsData (PlutusTypeEnumData)
import Plutarch.Extra.List (pfromList, pfromSingleton, plookupAssoc, ptryElimSingle, ptryFromSingleton)
import Plutarch.Extra.Map (phandleMin)
import Plutarch.Extra.Maybe (pexpectJustC)
import Plutarch.Extra.Ord (PComparator, pfromOrdBy)
import Plutarch.Extra.Tagged (PTagged (PTagged))
import Plutarch.Extra.TermCont (pmatchC)
import PlutusLedgerApi.V2 (CurrencySymbol, TokenName)

--------------------------------------------------------------------------------

----------------------------------------
-- Value Creation

{- | Create a 'PValue' that only contains a specific amount of tokens, described
 by a 'PAssetClassData'.

 @since 3.10.0
-}
passetClassDataValue ::
  forall (s :: S).
  Term s (PAssetClassData :--> PInteger :--> PValue 'Sorted 'NonZero)
passetClassDataValue :: forall (s :: S).
Term
  s (PAssetClassData :--> (PInteger :--> PValue 'Sorted 'NonZero))
passetClassDataValue = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PAssetClassData
ac Term s PInteger
i ->
    forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
      (Term s PInteger
i forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PInteger
0)
      (forall (s :: S) (a :: PType). Term s PString -> Term s a
ptraceError Term s PString
"passetClassDataValue: given zero argument, expecting nonzero.")
      ( let cs :: Term s (PAsData PCurrencySymbol)
cs = forall (name :: Symbol) (b :: PType) (p :: PType) (s :: S)
       (a :: PType) (as :: [PLabeledType]) (n :: Nat).
(PDataFields p, as ~ PFields p, n ~ PLabelIndex name as,
 KnownNat n, a ~ PUnLabel (IndexList n as), PFromDataable a b) =>
Term s (p :--> b)
pfield @"symbol" forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAssetClassData
ac
            tn :: Term s (PAsData PTokenName)
tn = forall (name :: Symbol) (b :: PType) (p :: PType) (s :: S)
       (a :: PType) (as :: [PLabeledType]) (n :: Nat).
(PDataFields p, as ~ PFields p, n ~ PLabelIndex name as,
 KnownNat n, a ~ PUnLabel (IndexList n as), PFromDataable a b) =>
Term s (p :--> b)
pfield @"name" forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAssetClassData
ac
         in forall (s :: S).
Term
  s
  (PCurrencySymbol
   :--> (PTokenName :--> (PInteger :--> PValue 'Sorted 'NonZero)))
Value.psingleton forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData PCurrencySymbol)
cs forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData PTokenName)
tn forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PInteger
i
      )

{- | Tagged version of `passetClassDataValue`.

 @since 3.14.1
-}
passetClassDataValueT ::
  forall {k :: Type} (unit :: k) (s :: S).
  Term
    s
    ( PTagged unit PAssetClassData
        :--> PTagged unit PInteger
        :--> PValue 'Sorted 'NonZero
    )
passetClassDataValueT :: forall {k} (unit :: k) (s :: S).
Term
  s
  (PTagged unit PAssetClassData
   :--> (PTagged unit PInteger :--> PValue 'Sorted 'NonZero))
passetClassDataValueT = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PTagged unit PAssetClassData)
ac Term s (PTagged unit PInteger)
i ->
    forall (s :: S).
Term
  s (PAssetClassData :--> (PInteger :--> PValue 'Sorted 'NonZero))
passetClassDataValue forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# (forall (w :: PType -> PType) (a :: PType) (s :: S).
(PComonad w, PSubcategory w a) =>
Term s (w a :--> a)
pextract forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PTagged unit PAssetClassData)
ac) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# (forall (w :: PType -> PType) (a :: PType) (s :: S).
(PComonad w, PSubcategory w a) =>
Term s (w a :--> a)
pextract forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PTagged unit PInteger)
i)

{- | Helper to construct the \'inner mapping\' of a 'PValue'.

 @since 3.9.0
-}
psingleValue ::
  forall (key :: KeyGuarantees) (s :: S).
  Term
    s
    ( PAsData PCurrencySymbol
        :--> PAsData PTokenName
        :--> PInteger
        :--> PBuiltinPair
              (PAsData PCurrencySymbol)
              (PAsData (PMap key PTokenName PInteger))
    )
psingleValue :: forall (key :: KeyGuarantees) (s :: S).
Term
  s
  (PAsData PCurrencySymbol
   :--> (PAsData PTokenName
         :--> (PInteger
               :--> PBuiltinPair
                      (PAsData PCurrencySymbol)
                      (PAsData (PMap key PTokenName PInteger)))))
psingleValue = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PAsData PCurrencySymbol)
sym Term s (PAsData PTokenName)
tk Term s PInteger
q ->
    forall (s :: S) (a :: PType) (b :: PType).
Term
  s
  (PAsData a
   :--> (PAsData b :--> PBuiltinPair (PAsData a) (PAsData b)))
ppairDataBuiltin
      # sym
      # pdata (pcon $ PMap $ pfromList [ppairDataBuiltin # tk # pdata q])

{- | As 'psingleValue', but using a Haskell-level 'AssetClass'.

 @since 3.10.0
-}
psingleValue' ::
  forall (keys :: KeyGuarantees) (a :: Type) (k :: Type) (s :: S).
  ( Is k A_Getter
  , LabelOptic' "symbol" k a CurrencySymbol
  , LabelOptic' "name" k a TokenName
  ) =>
  a ->
  Term
    s
    ( PInteger
        :--> PBuiltinPair
              (PAsData PCurrencySymbol)
              (PAsData (PMap keys PTokenName PInteger))
    )
psingleValue' :: forall (keys :: KeyGuarantees) a k (s :: S).
(Is k A_Getter, LabelOptic' "symbol" k a CurrencySymbol,
 LabelOptic' "name" k a TokenName) =>
a
-> Term
     s
     (PInteger
      :--> PBuiltinPair
             (PAsData PCurrencySymbol)
             (PAsData (PMap keys PTokenName PInteger)))
psingleValue' a
ac =
  forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
    forall (key :: KeyGuarantees) (s :: S).
Term
  s
  (PAsData PCurrencySymbol
   :--> (PAsData PTokenName
         :--> (PInteger
               :--> PBuiltinPair
                      (PAsData PCurrencySymbol)
                      (PAsData (PMap key PTokenName PInteger)))))
psingleValue
      # pconstantData (view #symbol ac)
      # pconstantData (view #name ac)

{- | Tagged version of `psingleValue'`.

 @since 3.14.1
-}
psingleValueT' ::
  forall {k :: Type} (keys :: KeyGuarantees) (unit :: k) (s :: S).
  Tagged unit AssetClass ->
  Term
    s
    ( PTagged unit PInteger
        :--> PBuiltinPair
              (PAsData PCurrencySymbol)
              (PAsData (PMap keys PTokenName PInteger))
    )
psingleValueT' :: forall {k} (keys :: KeyGuarantees) (unit :: k) (s :: S).
Tagged unit AssetClass
-> Term
     s
     (PTagged unit PInteger
      :--> PBuiltinPair
             (PAsData PCurrencySymbol)
             (PAsData (PMap keys PTokenName PInteger)))
psingleValueT' (Tagged (AssetClass CurrencySymbol
sym TokenName
tk)) =
  forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
    forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PTagged unit PInteger)
q ->
      forall (key :: KeyGuarantees) (s :: S).
Term
  s
  (PAsData PCurrencySymbol
   :--> (PAsData PTokenName
         :--> (PInteger
               :--> PBuiltinPair
                      (PAsData PCurrencySymbol)
                      (PAsData (PMap key PTokenName PInteger)))))
psingleValue forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) h (s :: S).
(ToData h, PLifted p ~ h, PConstanted h ~ p) =>
h -> Term s (PAsData p)
pconstantData CurrencySymbol
sym forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) h (s :: S).
(ToData h, PLifted p ~ h, PConstanted h ~ p) =>
h -> Term s (PAsData p)
pconstantData TokenName
tk forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (w :: PType -> PType) (a :: PType) (s :: S).
(PComonad w, PSubcategory w a) =>
Term s (w a :--> a)
pextract forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PTagged unit PInteger)
q

{- | Construct a 'PValue' from its underlying representation.
 There are "NoGuarantees" on the amounts.

 @since 3.10.0
-}
pvalue ::
  forall (k :: KeyGuarantees) (s :: S).
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
        :--> PAsData (PValue k 'NoGuarantees)
    )
pvalue :: forall (k :: KeyGuarantees) (s :: S).
Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> PAsData (PValue k 'NoGuarantees))
pvalue = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$ forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PMap keys PCurrencySymbol (PMap keys PTokenName PInteger))
-> PValue keys amounts s
PValue forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (keysort :: KeyGuarantees) (k :: PType) (v :: PType)
       (s :: S).
Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData v)))
-> PMap keysort k v s
PMap

{- | Construct a 'PValue' from its underlying representation.
 The amounts are guaranteed to be "Positive", so this is suitable for
 construction of "PTxOut"s.

 @since 3.9.0
-}
pvaluePositive ::
  forall (k :: KeyGuarantees) (s :: S).
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
        :--> PAsData (PValue k 'Positive)
    )
pvaluePositive :: forall (k :: KeyGuarantees) (s :: S).
Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> PAsData (PValue k 'Positive))
pvaluePositive =
  forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
    forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
x ->
      forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata forall a b. (a -> b) -> a -> b
$
        forall (kg :: KeyGuarantees) (ag :: AmountGuarantees) (s :: S).
Term s (PValue kg ag :--> PValue kg 'Positive)
Value.passertPositive
          # (pcon . PValue . pcon . PMap $ x)

----------------------------------------
-- Value Querying, Extraction, and Matching

{- | Get the amount of ada of a 'PValue'.

   @since 3.9.0
-}
padaOf ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  Term s (PValue keys amounts :--> PInteger)
padaOf :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PValue keys amounts :--> PInteger)
padaOf = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PValue keys amounts)
v ->
    forall (s :: S) (anyKey :: KeyGuarantees)
       (anyAmount :: AmountGuarantees).
Term
  s
  (PValue anyKey anyAmount
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger)))
Value.pvalueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
v forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant CurrencySymbol
"" forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant TokenName
""

{- | As 'passetClassValueOf', but using a Haskell-level 'AssetClass'.

 @since 3.9.0
-}
passetClassValueOf' ::
  forall
    (keys :: KeyGuarantees)
    (amounts :: AmountGuarantees)
    (a :: Type)
    (k :: Type)
    (s :: S).
  ( Is k A_Getter
  , LabelOptic' "symbol" k a CurrencySymbol
  , LabelOptic' "name" k a TokenName
  ) =>
  a ->
  Term s (PValue keys amounts :--> PInteger)
passetClassValueOf' :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) a k
       (s :: S).
(Is k A_Getter, LabelOptic' "symbol" k a CurrencySymbol,
 LabelOptic' "name" k a TokenName) =>
a -> Term s (PValue keys amounts :--> PInteger)
passetClassValueOf' a
ac =
  forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
    forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PValue keys amounts)
value ->
      forall (s :: S) (anyKey :: KeyGuarantees)
       (anyAmount :: AmountGuarantees).
Term
  s
  (PValue anyKey anyAmount
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger)))
Value.pvalueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
value forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant (forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall a. IsLabel "symbol" a => a
#symbol a
ac) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant (forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall a. IsLabel "name" a => a
#name a
ac)

{- | Tagged version of `passetClassValueOf'`.

 @since 3.14.1
-}
passetClassValueOfT' ::
  forall {k :: Type} (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (unit :: k) (s :: S).
  Tagged unit AssetClass ->
  Term s (PValue keys amounts :--> PTagged unit PInteger)
passetClassValueOfT' :: forall {k} (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (unit :: k) (s :: S).
Tagged unit AssetClass
-> Term s (PValue keys amounts :--> PTagged unit PInteger)
passetClassValueOfT' (Tagged (AssetClass CurrencySymbol
sym TokenName
token)) =
  forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
    forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PValue keys amounts)
value ->
      forall (f :: PType -> PType) (a :: PType) (s :: S).
(PApplicative f, PSubcategory f a) =>
Term s (a :--> f a)
ppure forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (s :: S) (anyKey :: KeyGuarantees)
       (anyAmount :: AmountGuarantees).
Term
  s
  (PValue anyKey anyAmount
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger)))
Value.pvalueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
value forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant CurrencySymbol
sym forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant TokenName
token

{- | Given a 'PAssetClass' and a 'PValue', look up the amount corresponding to
 that 'PAssetClass'.

 @since 3.9.0
-}
passetClassValueOf ::
  forall
    (key :: KeyGuarantees)
    (amount :: AmountGuarantees)
    (s :: S).
  Term s (PAssetClass :--> PValue key amount :--> PInteger)
passetClassValueOf :: forall (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (s :: S).
Term s (PAssetClass :--> (PValue key amount :--> PInteger))
passetClassValueOf = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PAssetClass
cls Term s (PValue key amount)
val -> forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s PAssetClass
cls forall a b. (a -> b) -> a -> b
$ \(PAssetClass Term s (PAsData PCurrencySymbol)
sym Term s (PAsData PTokenName)
tk) ->
    forall (list :: PType -> PType) (a :: PType) (s :: S) (r :: PType).
PIsListLike list a =>
(Term s (list a :--> r) -> Term s a -> Term s (list a) -> Term s r)
-> (Term s (list a :--> r) -> Term s r) -> Term s (list a :--> r)
precList (forall (k :: KeyGuarantees) (s :: S).
Term s (PAsData PCurrencySymbol)
-> Term s (PAsData PTokenName)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> PInteger)
-> Term
     s
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> Term s PInteger
findValue Term s (PAsData PCurrencySymbol)
sym Term s (PAsData PTokenName)
tk) (forall a b. a -> b -> a
const Term s PInteger
0) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue key amount)
val

{- | Tagged version of `passetClassValueOf`.

 @since 3.9.0
-}
passetClassValueOfT ::
  forall
    {k :: Type}
    (key :: KeyGuarantees)
    (amount :: AmountGuarantees)
    (unit :: k)
    (s :: S).
  Term s (PTagged unit PAssetClass :--> PValue key amount :--> PTagged unit PInteger)
passetClassValueOfT :: forall {k} (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (unit :: k) (s :: S).
Term
  s
  (PTagged unit PAssetClass
   :--> (PValue key amount :--> PTagged unit PInteger))
passetClassValueOfT = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PTagged unit PAssetClass)
cls Term s (PValue key amount)
val -> forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch (forall (w :: PType -> PType) (a :: PType) (s :: S).
(PComonad w, PSubcategory w a) =>
Term s (w a :--> a)
pextract forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PTagged unit PAssetClass)
cls) forall a b. (a -> b) -> a -> b
$ \(PAssetClass Term s (PAsData PCurrencySymbol)
sym Term s (PAsData PTokenName)
tk) ->
    forall (f :: PType -> PType) (a :: PType) (s :: S).
(PApplicative f, PSubcategory f a) =>
Term s (a :--> f a)
ppure forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (list :: PType -> PType) (a :: PType) (s :: S) (r :: PType).
PIsListLike list a =>
(Term s (list a :--> r) -> Term s a -> Term s (list a) -> Term s r)
-> (Term s (list a :--> r) -> Term s r) -> Term s (list a :--> r)
precList (forall (k :: KeyGuarantees) (s :: S).
Term s (PAsData PCurrencySymbol)
-> Term s (PAsData PTokenName)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> PInteger)
-> Term
     s
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> Term s PInteger
findValue Term s (PAsData PCurrencySymbol)
sym Term s (PAsData PTokenName)
tk) (forall a b. a -> b -> a
const Term s PInteger
0) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue key amount)
val

{- | Given a 'PAssetClassData' and a 'PValue', look up the amount corresponding
 to that 'PAssetClassData'.

 @since 3.21.4
-}
passetClassDataValueOf ::
  forall
    (key :: KeyGuarantees)
    (amount :: AmountGuarantees)
    (s :: S).
  Term s (PAssetClassData :--> PValue key amount :--> PInteger)
passetClassDataValueOf :: forall (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (s :: S).
Term s (PAssetClassData :--> (PValue key amount :--> PInteger))
passetClassDataValueOf = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PAssetClassData
cls Term s (PValue key amount)
val ->
    let cs :: Term s (PAsData PCurrencySymbol)
cs = forall (name :: Symbol) (b :: PType) (p :: PType) (s :: S)
       (a :: PType) (as :: [PLabeledType]) (n :: Nat).
(PDataFields p, as ~ PFields p, n ~ PLabelIndex name as,
 KnownNat n, a ~ PUnLabel (IndexList n as), PFromDataable a b) =>
Term s (p :--> b)
pfield @"symbol" forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAssetClassData
cls
        tn :: Term s (PAsData PTokenName)
tn = forall (name :: Symbol) (b :: PType) (p :: PType) (s :: S)
       (a :: PType) (as :: [PLabeledType]) (n :: Nat).
(PDataFields p, as ~ PFields p, n ~ PLabelIndex name as,
 KnownNat n, a ~ PUnLabel (IndexList n as), PFromDataable a b) =>
Term s (p :--> b)
pfield @"name" forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAssetClassData
cls
     in forall (list :: PType -> PType) (a :: PType) (s :: S) (r :: PType).
PIsListLike list a =>
(Term s (list a :--> r) -> Term s a -> Term s (list a) -> Term s r)
-> (Term s (list a :--> r) -> Term s r) -> Term s (list a :--> r)
precList (forall (k :: KeyGuarantees) (s :: S).
Term s (PAsData PCurrencySymbol)
-> Term s (PAsData PTokenName)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> PInteger)
-> Term
     s
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> Term s PInteger
findValue Term s (PAsData PCurrencySymbol)
cs Term s (PAsData PTokenName)
tn) (forall a b. a -> b -> a
const Term s PInteger
0) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue key amount)
val

{- | Tagged version of `passetClassDataValueOf`.

 @since 3.21.4
-}
passetClassDataValueOfT ::
  forall
    {k :: Type}
    (key :: KeyGuarantees)
    (amount :: AmountGuarantees)
    (unit :: k)
    (s :: S).
  Term s (PTagged unit PAssetClassData :--> PValue key amount :--> PTagged unit PInteger)
passetClassDataValueOfT :: forall {k} (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (unit :: k) (s :: S).
Term
  s
  (PTagged unit PAssetClassData
   :--> (PValue key amount :--> PTagged unit PInteger))
passetClassDataValueOfT = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PTagged unit PAssetClassData)
cls Term s (PValue key amount)
val ->
    forall (f :: PType -> PType) (a :: PType) (s :: S).
(PApplicative f, PSubcategory f a) =>
Term s (a :--> f a)
ppure forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (s :: S).
Term s (PAssetClassData :--> (PValue key amount :--> PInteger))
passetClassDataValueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# (forall (w :: PType -> PType) (a :: PType) (s :: S).
(PComonad w, PSubcategory w a) =>
Term s (w a :--> a)
pextract forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PTagged unit PAssetClassData)
cls) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue key amount)
val

{- | Extracts the amount given by the 'PAssetClass' from (the internal
 representation of) a 'PValue'.

 Intuitively, this acts as a \'pattern match\' on 'PValue'. You don't have to
 provide every asset class, only the ones you are interested in.

 = Example

 > example :: forall (s :: S) .
 >    Term s (PBuiltinList (
 >      PBuiltinPair (PAsData PCurrencySymbol)
 >                   (PAsData (PMap 'Sorted PTokenName PInteger))
 >      ) -> TermConst s ()
 > example rep = do
 >    rec <- matchValueAssets @'['("ada", AssetClass "Ada")]
 >              rep
 >              (HCons (Labeled adaClass) HNil)
 >    -- Or using operators
 >    rec2 <- matchValueAssets rep $ (Proxy @"ada" .|== adaClass) HNIl
 >    let adaFromRep = rec.ada

 @since 3.9.0
-}
pmatchValueAssets ::
  forall (input :: [(Symbol, Type)]) (s :: S).
  ( MatchValueAssetReferences input s
  , HRecToList input AssetClass
  ) =>
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap 'Sorted PTokenName PInteger))
        )
    ) ->
  HRec input ->
  TermCont s (HRec (OutputMatchValueAssets input s))
pmatchValueAssets :: forall {r :: PType} (input :: [(Symbol, Type)]) (s :: S).
(MatchValueAssetReferences input s, HRecToList input AssetClass) =>
Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName PInteger))))
-> HRec input -> TermCont s (HRec (OutputMatchValueAssets input s))
pmatchValueAssets Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName PInteger))))
pvaluemap HRec input
inputs = do
  -- nub reduces case Underlying being Ada also
  let sortedInputs :: [AssetClass]
sortedInputs = forall a. Ord a => [a] -> [a]
sort forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => [a] -> [a]
nub forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (xs :: [(Symbol, Type)]) x.
HRecToList xs x =>
HRec xs -> [x]
hrecToList forall a b. (a -> b) -> a -> b
$ HRec input
inputs
  -- perform actuall pattern match and save references to Haskell's Map
  Map AssetClass (Term s (PAsData PInteger))
matchedMap <- forall {r :: PType} (k :: KeyGuarantees) (s :: S).
Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> [AssetClass]
-> TermCont s (Map AssetClass (Term s (PAsData PInteger)))
unsafeMatchValueAssetsInternal Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName PInteger))))
pvaluemap [AssetClass]
sortedInputs
  -- reconstruct HRec with references saved on the matchedMap
  forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (input :: [(Symbol, Type)]) (s :: S).
MatchValueAssetReferences input s =>
Map AssetClass (Term s (PAsData PInteger))
-> HRec input -> HRec (OutputMatchValueAssets input s)
matchValueAssetReferences @input Map AssetClass (Term s (PAsData PInteger))
matchedMap HRec input
inputs

{- |
  Gets the first entry in the first item of the 'PValue' mapping & returns the
  rest of the 'PValue'.

  Fails if the 'PValue' is empty. In cases where we know that a 'PValue' contains
  Ada, such as in a 'PScriptContext', then this will function will split the
  Ada value - since the Ada entry comes first.

  NOTE: All properly normalized values will contain an Ada entry, even if
  that entry is 0.

  @since 3.9.0
-}
psplitValue ::
  forall (v :: AmountGuarantees) (s :: S).
  Term
    s
    ( PValue 'Sorted v
        :--> PPair
              (PAsData PInteger)
              (PValue 'Sorted v)
    )
psplitValue :: forall (v :: AmountGuarantees) (s :: S).
Term
  s
  (PValue 'Sorted v :--> PPair (PAsData PInteger) (PValue 'Sorted v))
psplitValue = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PValue 'Sorted v)
v ->
    let vList :: Term
  s
  (PInner
     (PMap 'Sorted PCurrencySymbol (PMap 'Sorted PTokenName PInteger)))
vList = forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue 'Sorted v)
v
     in forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall a b. (a -> b) -> a -> b
$
          forall (a :: PType) (b :: PType) (s :: S).
Term s a -> Term s b -> PPair a b s
PPair
            ( forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a :--> a)
phead forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$
                forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$
                  forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData
                    (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# (forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a :--> a)
phead forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PInner
     (PMap 'Sorted PCurrencySymbol (PMap 'Sorted PTokenName PInteger)))
vList))
            )
            (forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall a b. (a -> b) -> a -> b
$ forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PMap keys PCurrencySymbol (PMap keys PTokenName PInteger))
-> PValue keys amounts s
PValue forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall a b. (a -> b) -> a -> b
$ forall (keysort :: KeyGuarantees) (k :: PType) (v :: PType)
       (s :: S).
Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData v)))
-> PMap keysort k v s
PMap forall a b. (a -> b) -> a -> b
$ forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a :--> list a)
ptail forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PInner
     (PMap 'Sorted PCurrencySymbol (PMap 'Sorted PTokenName PInteger)))
vList)

----------------------------------------
-- Value Aggregation and Elimination

{- | Get the sum of all values belonging to a particular CurrencySymbol.

   @since 1.1.0
-}
psymbolValueOf ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  Term s (PCurrencySymbol :--> PValue keys amounts :--> PInteger)
psymbolValueOf :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PCurrencySymbol :--> (PValue keys amounts :--> PInteger))
psymbolValueOf =
  forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
    forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
sym Term s (PValue keys amounts)
value'' -> forall (a :: PType) (s :: S). TermCont s (Term s a) -> Term s a
unTermCont forall a b. (a -> b) -> a -> b
$ do
      PValue Term s (PMap keys PCurrencySymbol (PMap keys PTokenName PInteger))
value' <- forall {r :: PType} (a :: PType) (s :: S).
PlutusType a =>
Term s a -> TermCont s (a s)
pmatchC Term s (PValue keys amounts)
value''
      PMap Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap keys PTokenName PInteger))))
value <- forall {r :: PType} (a :: PType) (s :: S).
PlutusType a =>
Term s a -> TermCont s (a s)
pmatchC Term s (PMap keys PCurrencySymbol (PMap keys PTokenName PInteger))
value'
      Term s (PAsData (PMap keys PTokenName PInteger))
m' <- forall (a :: PType) (r :: PType) (s :: S).
Term s r -> Term s (PMaybe a) -> TermCont s (Term s a)
pexpectJustC Term s PInteger
0 (forall (k :: PType) (v :: PType) (kv :: PType)
       (ell :: PType -> PType) (s :: S).
(PElemConstraint ell kv, PListLike ell, PEq k) =>
Term
  s
  ((kv :--> k)
   :--> ((kv :--> v) :--> (k :--> (ell kv :--> PMaybe v))))
plookupAssoc forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata Term s PCurrencySymbol
sym forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap keys PTokenName PInteger))))
value)
      PMap Term
  s
  (PBuiltinList
     (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)))
m <- forall {r :: PType} (a :: PType) (s :: S).
PlutusType a =>
Term s a -> TermCont s (a s)
pmatchC (forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData (PMap keys PTokenName PInteger))
m')
      forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (list :: PType -> PType) (a :: PType) (s :: S) (b :: PType).
PIsListLike list a =>
Term s ((a :--> (b :--> b)) :--> (b :--> (list a :--> b)))
pfoldr forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam (\Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
x Term s PInteger
v -> forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
x) forall a. Num a => a -> a -> a
+ Term s PInteger
v) forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PInteger
0 forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)))
m

{- | Eliminator for a sorted 'PValue'. The function argument will receive:

 * The smallest 'PCurrencySymbol' for which we have a mapping;
 * The smallest 'PTokenName' for which the corresponding \'inner map\' has a
 mapping;
 * The 'PInteger' associated with the above 'PTokenName'; and
 * The \'rest\'.

 If the \'inner map\' corresponding to the 'PCurrencySymbol' above contains
 only a single mapping, the \'rest\' will not contain a mapping for that
 'PCurrencySymbol'; otherwise, it will contain the rest of the \'inner map\'.

 = Note

 The \'nil case\' will be invoked in two situations:

 * When the 'PValue' has no entries; and
 * When the \'inner map\' corresponding to the first 'PCurrencySymbol' key has
 no entries.

 @since 3.9.0
-}
pelimValue ::
  forall (amounts :: AmountGuarantees) (r :: S -> Type) (s :: S).
  ( Term s PCurrencySymbol ->
    Term s PTokenName ->
    Term s PInteger ->
    Term s (PValue 'Sorted amounts) ->
    Term s r
  ) ->
  Term s r ->
  Term s (PValue 'Sorted amounts) ->
  Term s r
pelimValue :: forall (amounts :: AmountGuarantees) (r :: PType) (s :: S).
(Term s PCurrencySymbol
 -> Term s PTokenName
 -> Term s PInteger
 -> Term s (PValue 'Sorted amounts)
 -> Term s r)
-> Term s r -> Term s (PValue 'Sorted amounts) -> Term s r
pelimValue Term s PCurrencySymbol
-> Term s PTokenName
-> Term s PInteger
-> Term s (PValue 'Sorted amounts)
-> Term s r
whenCons Term s r
whenNil Term s (PValue 'Sorted amounts)
xs = forall (r :: PType) (k :: PType) (v :: PType) (s :: S).
(PIsData k, PIsData v) =>
Term s (PMap 'Sorted k v)
-> Term s r
-> (Term s k -> Term s v -> Term s (PMap 'Sorted k v) -> Term s r)
-> Term s r
phandleMin (forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue 'Sorted amounts)
xs) Term s r
whenNil forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
k Term s (PMap 'Sorted PTokenName PInteger)
v Term
  s (PMap 'Sorted PCurrencySymbol (PMap 'Sorted PTokenName PInteger))
kvs ->
  forall (r :: PType) (k :: PType) (v :: PType) (s :: S).
(PIsData k, PIsData v) =>
Term s (PMap 'Sorted k v)
-> Term s r
-> (Term s k -> Term s v -> Term s (PMap 'Sorted k v) -> Term s r)
-> Term s r
phandleMin Term s (PMap 'Sorted PTokenName PInteger)
v Term s r
whenNil forall a b. (a -> b) -> a -> b
$ \Term s PTokenName
vk Term s PInteger
vv Term s (PMap 'Sorted PTokenName PInteger)
rest ->
    Term s PCurrencySymbol
-> Term s PTokenName
-> Term s PInteger
-> Term s (PValue 'Sorted amounts)
-> Term s r
whenCons Term s PCurrencySymbol
k Term s PTokenName
vk Term s PInteger
vv forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PMap keys PCurrencySymbol (PMap keys PTokenName PInteger))
-> PValue keys amounts s
PValue forall a b. (a -> b) -> a -> b
$
      forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
        (forall (s :: S) (any :: KeyGuarantees) (k :: PType) (v :: PType).
Term s (PMap any k v :--> PBool)
AssocMap.pnull forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PMap 'Sorted PTokenName PInteger)
rest)
        Term
  s (PMap 'Sorted PCurrencySymbol (PMap 'Sorted PTokenName PInteger))
kvs
        (forall (k :: PType) (v :: PType) (s :: S).
(POrd k, PIsData k, PIsData v) =>
Term s (k :--> (v :--> (PMap 'Sorted k v :--> PMap 'Sorted k v)))
AssocMap.pinsert forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PCurrencySymbol
k forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PMap 'Sorted PTokenName PInteger)
rest forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s (PMap 'Sorted PCurrencySymbol (PMap 'Sorted PTokenName PInteger))
kvs)

{- | Eliminator for the inner type of a 'PValue'.

 @since 3.9.0
-}
precValue ::
  forall r (k :: KeyGuarantees) s.
  ( Term
      s
      ( PBuiltinList
          ( PBuiltinPair
              (PAsData PCurrencySymbol)
              (PAsData (PMap k PTokenName PInteger))
          )
          :--> r
      ) ->
    Term s (PAsData PCurrencySymbol) ->
    Term s (PAsData PTokenName) ->
    Term s (PAsData PInteger) ->
    Term
      s
      ( PBuiltinList
          ( PBuiltinPair
              (PAsData PCurrencySymbol)
              (PAsData (PMap k PTokenName PInteger))
          )
      ) ->
    Term s r
  ) ->
  ( Term
      s
      ( PBuiltinList
          ( PBuiltinPair
              (PAsData PCurrencySymbol)
              (PAsData (PMap k PTokenName PInteger))
          )
          :--> r
      ) ->
    Term s r
  ) ->
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
        :--> r
    )
precValue :: forall (r :: PType) (k :: KeyGuarantees) (s :: S).
(Term
   s
   (PBuiltinList
      (PBuiltinPair
         (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
    :--> r)
 -> Term s (PAsData PCurrencySymbol)
 -> Term s (PAsData PTokenName)
 -> Term s (PAsData PInteger)
 -> Term
      s
      (PBuiltinList
         (PBuiltinPair
            (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
 -> Term s r)
-> (Term
      s
      (PBuiltinList
         (PBuiltinPair
            (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
       :--> r)
    -> Term s r)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> r)
precValue Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> r)
-> Term s (PAsData PCurrencySymbol)
-> Term s (PAsData PTokenName)
-> Term s (PAsData PInteger)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> Term s r
mcons =
  forall (list :: PType -> PType) (a :: PType) (s :: S) (r :: PType).
PIsListLike list a =>
(Term s (list a :--> r) -> Term s a -> Term s (list a) -> Term s r)
-> (Term s (list a :--> r) -> Term s r) -> Term s (list a :--> r)
precList
    ( \Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> r)
self Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
symbolMap Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
symbolMaps ->
        forall (list :: PType -> PType) (a :: PType) (s :: S) (r :: PType).
(PListLike list, PElemConstraint list a) =>
(Term s a -> Term s (list a) -> Term s r)
-> Term s r -> Term s (list a) -> Term s r
pelimList
          ( \Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
tokenMap Term
  s
  (PBuiltinList
     (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)))
tokenMaps ->
              Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> r)
-> Term s (PAsData PCurrencySymbol)
-> Term s (PAsData PTokenName)
-> Term s (PAsData PInteger)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> Term s r
mcons
                Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> r)
self
                (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
symbolMap)
                (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
tokenMap)
                (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
tokenMap)
                ( forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
                    (forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a :--> PBool)
pnull forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)))
tokenMaps)
                    Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
symbolMaps
                    ( forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (a :--> (list a :--> list a))
pcons
                        # ( ppairDataBuiltin
                              # (pfstBuiltin # symbolMap)
                              # pdata (pcon (PMap tokenMaps))
                          )
                        # symbolMaps
                    )
                )
          )
          (Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> r)
self forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
symbolMaps)
          (forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
symbolMap)
    )

----------------------------------------
-- Value Comparison

{- | Compare only on the basis of a particular 'PCurrencySymbol' and
 'PTokenName' entry.

 @since 3.9.0
-}
pbyClassComparator ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  Term s (PCurrencySymbol :--> PTokenName :--> PComparator (PValue keys amounts))
pbyClassComparator :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term
  s
  (PCurrencySymbol
   :--> (PTokenName :--> PComparator (PValue keys amounts)))
pbyClassComparator = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
cs Term s PTokenName
tn ->
    forall (a :: PType) (b :: PType) (s :: S).
POrd a =>
Term s ((b :--> a) :--> PComparator b)
pfromOrdBy forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam (\Term s (PValue keys amounts)
pval -> forall (s :: S) (anyKey :: KeyGuarantees)
       (anyAmount :: AmountGuarantees).
Term
  s
  (PValue anyKey anyAmount
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger)))
Value.pvalueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
pval forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PCurrencySymbol
cs forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PTokenName
tn)

{- | Compare only the entries corresponding to a particular 'PCurrencySymbol'.

 @since 3.9.0
-}
pbySymbolComparator ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  Term s (PCurrencySymbol :--> PComparator (PValue keys amounts))
pbySymbolComparator :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PCurrencySymbol :--> PComparator (PValue keys amounts))
pbySymbolComparator = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
cs ->
    forall (a :: PType) (b :: PType) (s :: S).
POrd a =>
Term s ((b :--> a) :--> PComparator b)
pfromOrdBy forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam (forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PCurrencySymbol :--> (PValue keys amounts :--> PInteger))
psymbolValueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PCurrencySymbol
cs forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#)

{- | As 'pbyClassComparator', but using a Haskell-level 'AssetClass' instead.

 @since 3.9.0
-}
pbyClassComparator' ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  AssetClass ->
  Term s (PComparator (PValue keys amounts))
pbyClassComparator' :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
AssetClass -> Term s (PComparator (PValue keys amounts))
pbyClassComparator' AssetClass
ac = forall (a :: PType) (b :: PType) (s :: S).
POrd a =>
Term s ((b :--> a) :--> PComparator b)
pfromOrdBy forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam (forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) a k
       (s :: S).
(Is k A_Getter, LabelOptic' "symbol" k a CurrencySymbol,
 LabelOptic' "name" k a TokenName) =>
a -> Term s (PValue keys amounts :--> PInteger)
passetClassValueOf' AssetClass
ac forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#)

----------------------------------------
-- Miscellaneous
-- TODO: Peter, 2022-09-21: There's a lot of typeclasses and instances that I
-- haven't looked at yet. I don't know how many of these belong in this module vs
-- should be factored out.

{- | Compute the guarantees known after adding two 'PValue's.

   @since 1.1.0
-}
type family AddGuarantees (a :: AmountGuarantees) (b :: AmountGuarantees) where
  AddGuarantees 'Positive 'Positive = 'Positive
  AddGuarantees _ _ = 'NoGuarantees

-- Used internally only in 'phasOnlyOneTokenOfCurrencySymbol'
data PState (s :: S)
  = PInitial
  | PFound
  | PFailed
  deriving stock
    ( forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x. Rep (PState s) x -> PState s
forall (s :: S) x. PState s -> Rep (PState s) x
$cto :: forall (s :: S) x. Rep (PState s) x -> PState s
$cfrom :: forall (s :: S) x. PState s -> Rep (PState s) x
Generic
    , Int -> PState s
PState s -> Int
PState s -> [PState s]
PState s -> PState s
PState s -> PState s -> [PState s]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
forall (s :: S). Int -> PState s
forall (s :: S). PState s -> Int
forall (s :: S). PState s -> [PState s]
forall (s :: S). PState s -> PState s
forall (s :: S). PState s -> PState s -> [PState s]
forall (s :: S). PState s -> PState s -> PState s -> [PState s]
enumFromThenTo :: PState s -> PState s -> PState s -> [PState s]
$cenumFromThenTo :: forall (s :: S). PState s -> PState s -> PState s -> [PState s]
enumFromTo :: PState s -> PState s -> [PState s]
$cenumFromTo :: forall (s :: S). PState s -> PState s -> [PState s]
enumFromThen :: PState s -> PState s -> [PState s]
$cenumFromThen :: forall (s :: S). PState s -> PState s -> [PState s]
enumFrom :: PState s -> [PState s]
$cenumFrom :: forall (s :: S). PState s -> [PState s]
fromEnum :: PState s -> Int
$cfromEnum :: forall (s :: S). PState s -> Int
toEnum :: Int -> PState s
$ctoEnum :: forall (s :: S). Int -> PState s
pred :: PState s -> PState s
$cpred :: forall (s :: S). PState s -> PState s
succ :: PState s -> PState s
$csucc :: forall (s :: S). PState s -> PState s
Enum
    , PState s
forall a. a -> a -> Bounded a
forall (s :: S). PState s
maxBound :: PState s
$cmaxBound :: forall (s :: S). PState s
minBound :: PState s
$cminBound :: forall (s :: S). PState s
Bounded
    )
  deriving anyclass
    ( forall (s :: S). PState s -> Term s (PInner PState)
forall (s :: S) (b :: PType).
Term s (PInner PState) -> (PState s -> Term s b) -> Term s b
forall (a :: PType).
(forall (s :: S). a s -> Term s (PInner a))
-> (forall (s :: S) (b :: PType).
    Term s (PInner a) -> (a s -> Term s b) -> Term s b)
-> PlutusType a
pmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PState) -> (PState s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PState) -> (PState s -> Term s b) -> Term s b
pcon' :: forall (s :: S). PState s -> Term s (PInner PState)
$cpcon' :: forall (s :: S). PState s -> Term s (PInner PState)
PlutusType
    )

instance DerivePlutusType PState where
  type DPTStrat _ = PlutusTypeEnumData

{- | Returns 'PTrue' if the entire argument 'PValue' contains /exactly/ one
     token of the argument 'PCurrencySymbol' (and contains no other assets).

     This implementation makes a special case for ADA, where it allows
     zero-ada entries in the given 'PValue'.

     @since 3.21.0
-}
phasOnlyOneTokenOfCurrencySymbol ::
  forall (kg :: KeyGuarantees) (ag :: AmountGuarantees) (s :: S).
  Term s (PCurrencySymbol :--> PValue kg ag :--> PBool)
phasOnlyOneTokenOfCurrencySymbol :: forall (kg :: KeyGuarantees) (ag :: AmountGuarantees) (s :: S).
Term s (PCurrencySymbol :--> (PValue kg ag :--> PBool))
phasOnlyOneTokenOfCurrencySymbol =
  {- Implementation notes:

      This is implemented using a state machine with three states: 'PInitial', 'PFound', 'PFailed'.

      See this comment for the state transition graph:
      https://gist.github.com/chfanghr/c3ef2f0ed1561e7b17dd11c1df609479?permalink_comment_id=4443620#gistcomment-4443620

      This implementation makes a special case for ADA, where it allows zero-ada entries in the 'PValue'.
  -}
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$
    \Term s PCurrencySymbol
cs
     ( (forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto) ->
        Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))))
l
      ) ->
        let isZeroAdaEntry ::
              Term
                s
                ( PBuiltinPair (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
                    :--> PBool
                )
            isZeroAdaEntry :: Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
   :--> PBool)
isZeroAdaEntry = forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
pair ->
              let cs' :: Term s PCurrencySymbol
cs' = forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
pair
                  isAda :: Term s PBool
isAda = forall (s :: S). Term s PString -> Term s PBool -> Term s PBool
ptraceIfFalse Term s PString
"Not ada" forall a b. (a -> b) -> a -> b
$ Term s PCurrencySymbol
cs' forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== forall (s :: S). Term s PCurrencySymbol
padaSymbol

                  tnMap :: Term s (PMap kg PTokenName PInteger)
tnMap = forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
pair
                  count :: Term s PInteger
count = forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# (forall (a :: PType) (list :: PType -> PType) (s :: S).
PIsListLike list a =>
Term s (list a :--> a)
ptryFromSingleton forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PMap kg PTokenName PInteger)
tnMap)
                  zeroAda :: Term s PBool
zeroAda = forall (s :: S). Term s PString -> Term s PBool -> Term s PBool
ptraceIfFalse Term s PString
"Non zero ada" forall a b. (a -> b) -> a -> b
$ Term s PInteger
count forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PInteger
0
               in Term s PBool
isAda forall (s :: S). Term s PBool -> Term s PBool -> Term s PBool
#&& Term s PBool
zeroAda

            isNonAdaEntryValid ::
              Term
                s
                ( PBuiltinPair (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
                    :--> PBool
                )
            isNonAdaEntryValid :: Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
   :--> PBool)
isNonAdaEntryValid = forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
pair ->
              let cs' :: Term s PCurrencySymbol
cs' = forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
pair
                  validCs :: Term s PBool
validCs = forall (s :: S). Term s PString -> Term s PBool -> Term s PBool
ptraceIfFalse Term s PString
"Unknown symbol" forall a b. (a -> b) -> a -> b
$ Term s PCurrencySymbol
cs' forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PCurrencySymbol
cs

                  tnMap :: Term s (PMap kg PTokenName PInteger)
tnMap = forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
pair
                  validTnMap :: Term s PBool
validTnMap = forall (s :: S). Term s PString -> Term s PBool -> Term s PBool
ptraceIfFalse Term s PString
"More than one token names or tokens" forall a b. (a -> b) -> a -> b
$
                    forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch (forall (a :: PType) (list :: PType -> PType) (s :: S).
PIsListLike list a =>
Term s (list a :--> PMaybe a)
pfromSingleton forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PMap kg PTokenName PInteger)
tnMap) forall a b. (a -> b) -> a -> b
$ \case
                      PMaybe (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)) s
PNothing -> forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PBool s
PFalse
                      PJust ((forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#)) -> Term s PInteger
tokenCount) ->
                        Term s PInteger
tokenCount forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PInteger
1
               in Term s PBool
validCs forall (s :: S). Term s PBool -> Term s PBool -> Term s PBool
#&& Term s PBool
validTnMap

            go ::
              Term
                s
                ( ( PState
                      :--> PBuiltinList
                            ( PBuiltinPair
                                (PAsData PCurrencySymbol)
                                (PAsData (PMap kg PTokenName PInteger))
                            )
                      :--> PState
                  )
                    :--> PState
                    :--> PBuiltinList
                          ( PBuiltinPair
                              (PAsData PCurrencySymbol)
                              (PAsData (PMap kg PTokenName PInteger))
                          )
                    :--> PState
                )
            go :: Term
  s
  ((PState
    :--> (PBuiltinList
            (PBuiltinPair
               (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
          :--> PState))
   :--> (PState
         :--> (PBuiltinList
                 (PBuiltinPair
                    (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
               :--> PState)))
go =
              forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PState
   :--> (PBuiltinList
           (PBuiltinPair
              (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
         :--> PState))
self Term s PState
lastState ->
                forall (list :: PType -> PType) (a :: PType) (s :: S) (r :: PType).
(PListLike list, PElemConstraint list a) =>
(Term s a -> Term s (list a) -> Term s r)
-> Term s r -> Term s (list a) -> Term s r
pelimList
                  ( \Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
x Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))))
xs -> forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
                      (Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
   :--> PBool)
isZeroAdaEntry forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
x)
                      (Term
  s
  (PState
   :--> (PBuiltinList
           (PBuiltinPair
              (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
         :--> PState))
self forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PState
lastState forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))))
xs)
                      forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s PState
lastState
                      forall a b. (a -> b) -> a -> b
$ \case
                        PState s
PInitial ->
                          forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
                            (Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
   :--> PBool)
isNonAdaEntryValid forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
x)
                            (Term
  s
  (PState
   :--> (PBuiltinList
           (PBuiltinPair
              (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
         :--> PState))
self forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PState s
PFound forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))))
xs)
                            (forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PState s
PFailed)
                        PState s
PFound -> forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PState s
PFailed
                        PState s
PFailed -> forall (s :: S) (a :: PType). Term s PString -> Term s a
ptraceError Term s PString
"unreachable"
                  )
                  ( forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s PState
lastState forall a b. (a -> b) -> a -> b
$ \case
                      PState s
PFound -> Term s PState
lastState
                      PState s
_ -> forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PState s
PFailed
                  )
         in forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch (forall (s :: S) (a :: PType) (b :: PType).
Term s (((a :--> b) :--> (a :--> b)) :--> (a :--> b))
pfix forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  ((PState
    :--> (PBuiltinList
            (PBuiltinPair
               (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
          :--> PState))
   :--> (PState
         :--> (PBuiltinList
                 (PBuiltinPair
                    (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
               :--> PState)))
go forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PState s
PInitial forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))))
l) forall a b. (a -> b) -> a -> b
$
              \case
                PState s
PFound -> forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PBool s
PTrue
                PState s
_ -> forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall (s :: S). PBool s
PFalse

{- | Returns the count of non-zero currency symbols in a 'PValue'.

     So, for a value of the following shape:

     @
       [("", [("", 0)]), ("feed", [("foo", 7)]), ("deed", [("bar", 1)])]
     @

     We get the result @2@.

     @since 3.21.0
-}
pcountNonZeroes :: forall (kg :: KeyGuarantees) (ag :: AmountGuarantees) (s :: S). Term s (PValue kg ag :--> PInteger)
pcountNonZeroes :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PValue keys amounts :--> PInteger)
pcountNonZeroes = forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s (PValue kg ag)
value ->
  let
    nonZero :: Term s ((PBuiltinPair (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))) :--> PBool)
    nonZero :: Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
   :--> PBool)
nonZero = forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
currencySymbolPair ->
      forall (s :: S) (a :: PType) (b :: PType).
Term s a -> (Term s a -> Term s b) -> Term s b
plet (forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger)))
currencySymbolPair) forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinList
     (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)))
tokens ->
        forall (list :: PType -> PType) (a :: PType) (s :: S).
PIsListLike list a =>
Term s ((a :--> PBool) :--> (list a :--> PBool))
pall
          # plam (\tokenNamePair -> pnot #$ (pfromData $ psndBuiltin # tokenNamePair) #== 0)
          # tokens
            #&& pnot
          # (pnull # tokens)
   in
    forall (list :: PType -> PType) (a :: PType) (s :: S).
PIsListLike list a =>
Term s (list a :--> PInteger)
plength forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (list :: PType -> PType) (a :: PType) (s :: S).
PIsListLike list a =>
Term s ((a :--> PBool) :--> (list a :--> list a))
pfilter forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap kg PTokenName PInteger))
   :--> PBool)
nonZero forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
#$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue kg ag)
value

{- | Returns 'PTrue' if the argument 'PValue' contains /exactly/
  one token of the argument 'PAssetClassData'.

 Note: unlike `phasOnlyOneTokenOfCurrencySymbol` this may
 still return 'PTrue' if there are other assets in the 'PValue'.

 @since 3.21.4
-}
phasOneTokenOfAssetClassData ::
  forall
    (keys :: KeyGuarantees)
    (amounts :: AmountGuarantees)
    (s :: S).
  Term s (PAssetClassData :--> PValue keys amounts :--> PBool)
phasOneTokenOfAssetClassData :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PAssetClassData :--> (PValue keys amounts :--> PBool))
phasOneTokenOfAssetClassData = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PAssetClassData
cls Term s (PValue keys amounts)
v ->
    forall (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (s :: S).
Term s (PAssetClassData :--> (PValue key amount :--> PInteger))
passetClassDataValueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAssetClassData
cls forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
v forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PInteger
1

{- | Returns 'PTrue' if the argument 'PValue' contains /exactly/
  one token of the argument 'PAssetClass'.

 Note: unlike `phasOnlyOneTokenOfCurrencySymbol` this may
 still return 'PTrue' if there are other assets in the 'PValue'.

 @since 3.9.1
-}
phasOneTokenOfAssetClass ::
  forall
    (keys :: KeyGuarantees)
    (amounts :: AmountGuarantees)
    (s :: S).
  Term s (PAssetClass :--> PValue keys amounts :--> PBool)
phasOneTokenOfAssetClass :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PAssetClass :--> (PValue keys amounts :--> PBool))
phasOneTokenOfAssetClass = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PAssetClass
cls Term s (PValue keys amounts)
v ->
    forall (key :: KeyGuarantees) (amount :: AmountGuarantees)
       (s :: S).
Term s (PAssetClass :--> (PValue key amount :--> PInteger))
passetClassValueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PAssetClass
cls forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
v forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PInteger
1

{- | Returns 'PTrue' if the argument 'PValue' contains /exactly/ one
 token of the argument 'PCurrencySymbol'.

 Note: unlike `phasOnlyOneTokenOfCurrencySymbol` this may
 still return 'PTrue' if there are other assets in the 'PValue'.

 @since 3.9.1
-}
phasOneTokenOfCurrencySymbol ::
  forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
  Term s (PCurrencySymbol :--> PValue keys amounts :--> PBool)
phasOneTokenOfCurrencySymbol :: forall (kg :: KeyGuarantees) (ag :: AmountGuarantees) (s :: S).
Term s (PCurrencySymbol :--> (PValue kg ag :--> PBool))
phasOneTokenOfCurrencySymbol = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
cs Term s (PValue keys amounts)
vs ->
    forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term s (PCurrencySymbol :--> (PValue keys amounts :--> PInteger))
psymbolValueOf forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PCurrencySymbol
cs forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue keys amounts)
vs forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PInteger
1

-- Helpers

-- Cons case for QTokenValue, with recursive fixpoint
findValue ::
  forall (k :: KeyGuarantees) (s :: S).
  Term s (PAsData PCurrencySymbol) ->
  Term s (PAsData PTokenName) ->
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
        :--> PInteger
    ) ->
  Term
    s
    ( PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap k PTokenName PInteger))
    ) ->
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
    ) ->
  Term s PInteger
findValue :: forall (k :: KeyGuarantees) (s :: S).
Term s (PAsData PCurrencySymbol)
-> Term s (PAsData PTokenName)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> PInteger)
-> Term
     s
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> Term s PInteger
findValue Term s (PAsData PCurrencySymbol)
sym Term s (PAsData PTokenName)
tk Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> PInteger)
self Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
x Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
xs = forall (s :: S) (a :: PType) (b :: PType).
Term s a -> (Term s a -> Term s b) -> Term s b
plet Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
x forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
pair ->
  forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
    (forall (s :: S) (a :: PType). Term s (PAsData a) -> Term s PData
pforgetData (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
pair) forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== forall (s :: S) (a :: PType). Term s (PAsData a) -> Term s PData
pforgetData Term s (PAsData PCurrencySymbol)
sym)
    (forall (ell :: PType -> PType) (a :: PType) (r :: PType) (s :: S).
(PElemConstraint ell a, PListLike ell) =>
(Term s a -> Term s r) -> Term s (ell a) -> Term s r
ptryElimSingle Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
-> Term s PInteger
go forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinPair
     (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
pair)
    (Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> PInteger)
self forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
xs)
  where
    go ::
      Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger)) ->
      Term s PInteger
    go :: Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
-> Term s PInteger
go Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
kv =
      forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
        (forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> a)
pfstBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
kv forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s (PAsData PTokenName)
tk)
        (forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData forall a b. (a -> b) -> a -> b
$ forall (s :: S) (a :: PType) (b :: PType).
Term s (PBuiltinPair a b :--> b)
psndBuiltin forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinPair (PAsData PTokenName) (PAsData PInteger))
kv)
        (forall (s :: S) (a :: PType). Term s PString -> Term s a
ptraceError Term s PString
"findValue: Unexpectedly missing result.")

unsafeMatchValueAssetsInternal ::
  forall (k :: KeyGuarantees) (s :: S).
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
    ) ->
  [AssetClass] ->
  TermCont s (Map AssetClass (Term s (PAsData PInteger)))
unsafeMatchValueAssetsInternal :: forall {r :: PType} (k :: KeyGuarantees) (s :: S).
Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> [AssetClass]
-> TermCont s (Map AssetClass (Term s (PAsData PInteger)))
unsafeMatchValueAssetsInternal Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
_ [] = forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall k a. Map k a
Map.empty
unsafeMatchValueAssetsInternal
  Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
inputpvalue
  (sa :: AssetClass
sa@AssetClass
someAsset : [AssetClass]
rest) = do
    (PPair Term s (PAsData PInteger)
pint Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
newValueMap) <-
      forall (r :: PType) (a :: S) b.
((b -> Term a r) -> Term a r) -> TermCont a b
TermCont forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (a :: PType) (s :: S) (b :: PType).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch forall a b. (a -> b) -> a -> b
$
        forall (k :: KeyGuarantees) (s :: S).
AssetClass
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> PPair
             (PAsData PInteger)
             (PBuiltinList
                (PBuiltinPair
                   (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))))
matchOrTryRec AssetClass
someAsset
          # inputpvalue
    Map AssetClass (Term s (PAsData PInteger))
remaining <- forall {r :: PType} (k :: KeyGuarantees) (s :: S).
Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
-> [AssetClass]
-> TermCont s (Map AssetClass (Term s (PAsData PInteger)))
unsafeMatchValueAssetsInternal Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
newValueMap [AssetClass]
rest
    forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert AssetClass
sa Term s (PAsData PInteger)
pint Map AssetClass (Term s (PAsData PInteger))
remaining

-- This function does not check if keys are duplicated or are in different
-- order
class HRecToList (xs :: [(Symbol, Type)]) (x :: Type) where
  hrecToList :: HRec xs -> [x]

instance HRecToList '[] (x :: Type) where
  hrecToList :: HRec '[] -> [x]
hrecToList HRec '[]
_ = []

-- Converts type level lists of tagged assets back to dynamic-typed assets
instance
  forall (rest :: [(Symbol, Type)]) (name :: Symbol) (unit :: Symbol).
  HRecToList rest AssetClass =>
  HRecToList
    ('(name, Tagged unit AssetClass) ': rest)
    AssetClass
  where
  hrecToList :: HRec ('(name, Tagged unit AssetClass) : rest) -> [AssetClass]
hrecToList (HCons (Labeled (Tagged AssetClass
x)) HRec as1
xs) = AssetClass
x forall a. a -> [a] -> [a]
: forall (xs :: [(Symbol, Type)]) x.
HRecToList xs x =>
HRec xs -> [x]
hrecToList HRec as1
xs

-- | Associates given Symbol of AssetClass to PTagged tag PInteger
type family OutputMatchValueAssets (ps :: [(Symbol, Type)]) (s :: S) where
  OutputMatchValueAssets '[] _ = '[]
  OutputMatchValueAssets ('(name, Tagged unit AssetClass) ': rest) s =
    '( name
     , Term
        s
        (PAsData (PTagged unit PInteger))
     )
      ': OutputMatchValueAssets rest s

class MatchValueAssetReferences (input :: [(Symbol, Type)]) (s :: S) where
  matchValueAssetReferences ::
    Map AssetClass (Term s (PAsData PInteger)) ->
    HRec input ->
    HRec (OutputMatchValueAssets input s)

instance MatchValueAssetReferences '[] (s :: S) where
  matchValueAssetReferences :: Map AssetClass (Term s (PAsData PInteger))
-> HRec '[] -> HRec (OutputMatchValueAssets '[] s)
matchValueAssetReferences Map AssetClass (Term s (PAsData PInteger))
_ HRec '[]
_ = HRec '[]
HNil

instance
  forall
    (name :: Symbol)
    (classSymbol :: Symbol)
    (is :: [(Symbol, Type)])
    (s :: S).
  MatchValueAssetReferences is s =>
  MatchValueAssetReferences
    ('(name, Tagged classSymbol AssetClass) ': is)
    s
  where
  matchValueAssetReferences :: Map AssetClass (Term s (PAsData PInteger))
-> HRec ('(name, Tagged classSymbol AssetClass) : is)
-> HRec
     (OutputMatchValueAssets
        ('(name, Tagged classSymbol AssetClass) : is) s)
matchValueAssetReferences Map AssetClass (Term s (PAsData PInteger))
valueMap (HCons (Labeled (Tagged AssetClass
cls)) HRec as1
rest) =
    forall (name :: Symbol) a (as1 :: [(Symbol, Type)]).
Labeled name a -> HRec as1 -> HRec ('(name, a) : as1)
HCons
      ( forall {k} (sym :: k) a. a -> Labeled sym a
Labeled @name
          ( forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata forall a b. (a -> b) -> a -> b
$
              forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall a b. (a -> b) -> a -> b
$
                forall k (tag :: k) (underlying :: PType) (s :: S).
Term s underlying -> PTagged tag underlying s
PTagged forall a b. (a -> b) -> a -> b
$
                  forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData (Map AssetClass (Term s (PAsData PInteger))
valueMap forall k a. Ord k => Map k a -> k -> a
Map.! AssetClass
cls)
          )
      )
      (forall (input :: [(Symbol, Type)]) (s :: S).
MatchValueAssetReferences input s =>
Map AssetClass (Term s (PAsData PInteger))
-> HRec input -> HRec (OutputMatchValueAssets input s)
matchValueAssetReferences Map AssetClass (Term s (PAsData PInteger))
valueMap HRec as1
rest)

matchOrTryRec ::
  forall (k :: KeyGuarantees) (s :: S).
  AssetClass ->
  Term
    s
    ( PBuiltinList
        ( PBuiltinPair
            (PAsData PCurrencySymbol)
            (PAsData (PMap k PTokenName PInteger))
        )
        :--> PPair
              (PAsData PInteger)
              ( PBuiltinList
                  ( PBuiltinPair
                      (PAsData PCurrencySymbol)
                      (PAsData (PMap k PTokenName PInteger))
                  )
              )
    )
matchOrTryRec :: forall (k :: KeyGuarantees) (s :: S).
AssetClass
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> PPair
             (PAsData PInteger)
             (PBuiltinList
                (PBuiltinPair
                   (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))))
matchOrTryRec AssetClass
requiredAsset = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
inputpvalue -> forall (s :: S) (a :: PType) (b :: PType).
Term s a -> (Term s a -> Term s b) -> Term s b
plet (forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (b :: PType) (s :: S).
Term s a -> Term s b -> PPair a b s
PPair (forall (a :: PType) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata Term s PInteger
0) Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
inputpvalue) forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PPair
     (PAsData PInteger)
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))))
def ->
    forall (r :: PType) (k :: KeyGuarantees) (s :: S).
(Term
   s
   (PBuiltinList
      (PBuiltinPair
         (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
    :--> r)
 -> Term s (PAsData PCurrencySymbol)
 -> Term s (PAsData PTokenName)
 -> Term s (PAsData PInteger)
 -> Term
      s
      (PBuiltinList
         (PBuiltinPair
            (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
 -> Term s r)
-> (Term
      s
      (PBuiltinList
         (PBuiltinPair
            (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
       :--> r)
    -> Term s r)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
      :--> r)
precValue
      ( \Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> PPair
          (PAsData PInteger)
          (PBuiltinList
             (PBuiltinPair
                (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))))
self Term s (PAsData PCurrencySymbol)
pcurrencySymbol Term s (PAsData PTokenName)
pTokenName Term s (PAsData PInteger)
pint Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
rest ->
          forall (s :: S) (a :: PType).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
            ( forall (p :: PType) h (s :: S).
(ToData h, PLifted p ~ h, PConstanted h ~ p) =>
h -> Term s (PAsData p)
pconstantData (forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view forall a. IsLabel "symbol" a => a
#symbol AssetClass
requiredAsset)
                #== pcurrencySymbol
                #&& pconstantData (view #name requiredAsset)
                #== pTokenName
            )
            -- assetClass found - return its quantity and tail of PValueMap
            (forall (a :: PType) (s :: S). PlutusType a => a s -> Term s a
pcon forall a b. (a -> b) -> a -> b
$ forall (a :: PType) (b :: PType) (s :: S).
Term s a -> Term s b -> PPair a b s
PPair Term s (PAsData PInteger)
pint Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
rest)
            -- assetClass not found - skipping current position
            (Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))
   :--> PPair
          (PAsData PInteger)
          (PBuiltinList
             (PBuiltinPair
                (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))))
self forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger))))
rest)
      )
      (forall a b. a -> b -> a
const Term
  s
  (PPair
     (PAsData PInteger)
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol) (PAsData (PMap k PTokenName PInteger)))))
def)
      # inputpvalue

{- | Get the negative and positive amount of a particular 'CurrencySymbol', and
     return nothing if it doesn't exist in the value.

     @since 3.14.1
-}
psymbolValueOf' ::
  forall
    (keys :: KeyGuarantees)
    (amounts :: AmountGuarantees)
    (s :: S).
  Term
    s
    ( PCurrencySymbol
        :--> PValue keys amounts
        :--> PMaybe
              ( PPair
                  -- Positive amount
                  PInteger
                  -- Negative amount
                  PInteger
              )
    )
psymbolValueOf' :: forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees)
       (s :: S).
Term
  s
  (PCurrencySymbol
   :--> (PValue keys amounts :--> PMaybe (PPair PInteger PInteger)))
psymbolValueOf' = forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic forall a b. (a -> b) -> a -> b
$
  forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$ \Term s PCurrencySymbol
sym Term s (PValue keys amounts)
value ->
    let tnMap :: Term s (PMaybe (PMap keys PTokenName PInteger))
tnMap = forall (k :: PType) (v :: PType) (s :: S) (any :: KeyGuarantees).
(PIsData k, PIsData v) =>
Term s (k :--> (PMap any k v :--> PMaybe v))
plookup forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s PCurrencySymbol
sym forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto Term s (PValue keys amounts)
value
        f :: Term s (PMap keys PTokenName PInteger :--> PPair PInteger PInteger)
f =
          forall a (b :: PType) (s :: S) (c :: PType).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
plam forall a b. (a -> b) -> a -> b
$
            ( forall (list :: PType -> PType) (a :: PType) (s :: S) (b :: PType).
PIsListLike list a =>
Term s ((a :--> (b :--> b)) :--> (b :--> (list a :--> b)))
pfoldr
                # plam
                  ( \x r ->
                      let q = pfromData $ psndBuiltin # x
                       in pmatch r $ \(PPair p n) ->
                            pif
                              (0 #< q)
                              (pcon $ PPair (p + q) n)
                              (pcon $ PPair p (n + q))
                  )
                # pcon (PPair 0 0)
                #
            )
              forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (s :: S) (a :: PType). Term s a -> Term s (PInner a)
pto
     in forall (f :: PType -> PType) (a :: PType) (b :: PType) (s :: S).
(PFunctor f, PSubcategory f a, PSubcategory f b) =>
Term s ((a :--> b) :--> (f a :--> f b))
pfmap forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# forall {s :: S}.
Term s (PMap keys PTokenName PInteger :--> PPair PInteger PInteger)
f forall (s :: S) (a :: PType) (b :: PType).
HasCallStack =>
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PMaybe (PMap keys PTokenName PInteger))
tnMap