{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE QualifiedDo #-}
{-# LANGUAGE RankNTypes #-}

module Plutarch.LedgerApi.AssocMap.Zip (
  BothPresentHandler (..),
  MergeHandler (..),
  OnePresentHandler (..),
  differenceMergeHandler,
  intersectionMergeHandler,
  leftBiasedUnionMergeHandler,
  mergeHandlerOnData,
  unionMergeHandler,
  zipMergeHandler,
  zipWorker,
) where

import Data.Kind (Type)
import Plutarch.Maybe (pmapDropNothing, pmapMaybe, pmaybe)
import Plutarch.Monadic qualified as P
import Plutarch.Prelude hiding (pmap)
import Plutarch.Prelude qualified as PPrelude (pmap)

--------------------------------------------------------------------------------
-- Types

data MergeHandler (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type) = MergeHandler
  { forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
MergeHandler s k a b c -> BothPresentHandler s k a b c
mhBothPresent :: BothPresentHandler s k a b c
  , forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
MergeHandler s k a b c -> OnePresentHandler s k a c
mhLeftPresent :: OnePresentHandler s k a c
  , forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
MergeHandler s k a b c -> OnePresentHandler s k b c
mhRightPresent :: OnePresentHandler s k b c
  }

data BothPresentHandler (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type)
  = DropBoth
  | HandleBoth (Term s (k :--> a :--> b :--> c))
  | HandleOrDropBoth (Term s (k :--> a :--> b :--> PMaybe c))

data OnePresentHandler (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
  = DropOne
  | HandleOne (Term s (k :--> a :--> b))
  | HandleOrDropOne (Term s (k :--> a :--> PMaybe b))

--------------------------------------------------------------------------------
-- Handler Conversion

mergeHandlerOnData ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type).
  ( PIsData k
  , PIsData a
  , PIsData b
  , PIsData c
  ) =>
  MergeHandler s k a b c ->
  MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandlerOnData :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
(PIsData k, PIsData a, PIsData b, PIsData c) =>
MergeHandler s k a b c
-> MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandlerOnData MergeHandler s k a b c
mergeHandler =
  MergeHandler
    { mhBothPresent :: BothPresentHandler
  s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mhBothPresent = BothPresentHandler s k a b c
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
(PIsData k, PIsData a, PIsData b, PIsData c) =>
BothPresentHandler s k a b c
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
bothPresentHandlerOnData MergeHandler s k a b c
mergeHandler.mhBothPresent
    , mhLeftPresent :: OnePresentHandler s (PAsData k) (PAsData a) (PAsData c)
mhLeftPresent = OnePresentHandler s k a c
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData c)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
(PIsData k, PIsData a, PIsData b) =>
OnePresentHandler s k a b
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
onePresentHandlerOnData MergeHandler s k a b c
mergeHandler.mhLeftPresent
    , mhRightPresent :: OnePresentHandler s (PAsData k) (PAsData b) (PAsData c)
mhRightPresent = OnePresentHandler s k b c
-> OnePresentHandler s (PAsData k) (PAsData b) (PAsData c)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
(PIsData k, PIsData a, PIsData b) =>
OnePresentHandler s k a b
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
onePresentHandlerOnData MergeHandler s k a b c
mergeHandler.mhRightPresent
    }

bothPresentHandlerOnData ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type).
  ( PIsData k
  , PIsData a
  , PIsData b
  , PIsData c
  ) =>
  BothPresentHandler s k a b c ->
  BothPresentHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
bothPresentHandlerOnData :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
(PIsData k, PIsData a, PIsData b, PIsData c) =>
BothPresentHandler s k a b c
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
bothPresentHandlerOnData = \case
  BothPresentHandler s k a b c
DropBoth -> BothPresentHandler
  s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
BothPresentHandler s k a b c
DropBoth
  HandleBoth Term s (k :--> (a :--> (b :--> c)))
f ->
    Term s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s (k :--> (a :--> (b :--> c))) -> BothPresentHandler s k a b c
HandleBoth (Term
   s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
 -> BothPresentHandler
      s (PAsData k) (PAsData a) (PAsData b) (PAsData c))
-> Term
     s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
forall a b. (a -> b) -> a -> b
$ (Term s (PAsData k)
 -> Term s (PAsData a) -> Term s (PAsData b) -> Term s (PAsData c))
-> Term
     s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c
 -> Term s (PAsData a) -> Term s (PAsData b) -> Term s (PAsData c))
-> Term s (c :--> (PAsData a :--> (PAsData b :--> PAsData c)))
plam \Term s (PAsData k)
k Term s (PAsData a)
valL Term s (PAsData b)
valR ->
      Term s c -> Term s (PAsData c)
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata (Term s c -> Term s (PAsData c)) -> Term s c -> Term s (PAsData c)
forall a b. (a -> b) -> a -> b
$ Term s (k :--> (a :--> (b :--> c)))
f Term s (k :--> (a :--> (b :--> c)))
-> Term s k -> Term s (a :--> (b :--> c))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData k) -> Term s k
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData k)
k Term s (a :--> (b :--> c)) -> Term s a -> Term s (b :--> c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData a) -> Term s a
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData a)
valL Term s (b :--> c) -> Term s b -> Term s c
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData b) -> Term s b
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData b)
valR
  HandleOrDropBoth Term s (k :--> (a :--> (b :--> PMaybe c)))
f ->
    Term
  s
  (PAsData k
   :--> (PAsData a :--> (PAsData b :--> PMaybe (PAsData c))))
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s (k :--> (a :--> (b :--> PMaybe c)))
-> BothPresentHandler s k a b c
HandleOrDropBoth (Term
   s
   (PAsData k
    :--> (PAsData a :--> (PAsData b :--> PMaybe (PAsData c))))
 -> BothPresentHandler
      s (PAsData k) (PAsData a) (PAsData b) (PAsData c))
-> Term
     s
     (PAsData k
      :--> (PAsData a :--> (PAsData b :--> PMaybe (PAsData c))))
-> BothPresentHandler
     s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
forall a b. (a -> b) -> a -> b
$ (Term s (PAsData k)
 -> Term s (PAsData a)
 -> Term s (PAsData b)
 -> Term s (PMaybe (PAsData c)))
-> Term
     s
     (PAsData k
      :--> (PAsData a :--> (PAsData b :--> PMaybe (PAsData c))))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c
 -> Term s (PAsData a)
 -> Term s (PAsData b)
 -> Term s (PMaybe (PAsData c)))
-> Term
     s (c :--> (PAsData a :--> (PAsData b :--> PMaybe (PAsData c))))
plam \Term s (PAsData k)
k Term s (PAsData a)
valL Term s (PAsData b)
valR ->
      Term s ((c :--> PAsData c) :--> (PMaybe c :--> PMaybe (PAsData c)))
forall (a :: S -> Type) (b :: S -> Type) (s :: S).
Term s ((a :--> b) :--> (PMaybe a :--> PMaybe b))
pmapMaybe
        # plam pdata
        # (f # pfromData k # pfromData valL # pfromData valR)

onePresentHandlerOnData ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
  ( PIsData k
  , PIsData a
  , PIsData b
  ) =>
  OnePresentHandler s k a b ->
  OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
onePresentHandlerOnData :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
(PIsData k, PIsData a, PIsData b) =>
OnePresentHandler s k a b
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
onePresentHandlerOnData = \case
  OnePresentHandler s k a b
DropOne -> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
OnePresentHandler s k a b
DropOne
  HandleOne Term s (k :--> (a :--> b))
f ->
    Term s (PAsData k :--> (PAsData a :--> PAsData b))
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> b)) -> OnePresentHandler s k a b
HandleOne (Term s (PAsData k :--> (PAsData a :--> PAsData b))
 -> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b))
-> Term s (PAsData k :--> (PAsData a :--> PAsData b))
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
forall a b. (a -> b) -> a -> b
$ (Term s (PAsData k) -> Term s (PAsData a) -> Term s (PAsData b))
-> Term s (PAsData k :--> (PAsData a :--> PAsData b))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s (PAsData a) -> Term s (PAsData b))
-> Term s (c :--> (PAsData a :--> PAsData b))
plam \Term s (PAsData k)
k Term s (PAsData a)
v ->
      Term s b -> Term s (PAsData b)
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata (Term s b -> Term s (PAsData b)) -> Term s b -> Term s (PAsData b)
forall a b. (a -> b) -> a -> b
$ Term s (k :--> (a :--> b))
f Term s (k :--> (a :--> b)) -> Term s k -> Term s (a :--> b)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData k) -> Term s k
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData k)
k Term s (a :--> b) -> Term s a -> Term s b
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData a) -> Term s a
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData a)
v
  HandleOrDropOne Term s (k :--> (a :--> PMaybe b))
f ->
    Term s (PAsData k :--> (PAsData a :--> PMaybe (PAsData b)))
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> PMaybe b)) -> OnePresentHandler s k a b
HandleOrDropOne (Term s (PAsData k :--> (PAsData a :--> PMaybe (PAsData b)))
 -> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b))
-> Term s (PAsData k :--> (PAsData a :--> PMaybe (PAsData b)))
-> OnePresentHandler s (PAsData k) (PAsData a) (PAsData b)
forall a b. (a -> b) -> a -> b
$ (Term s (PAsData k)
 -> Term s (PAsData a) -> Term s (PMaybe (PAsData b)))
-> Term s (PAsData k :--> (PAsData a :--> PMaybe (PAsData b)))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s (PAsData a) -> Term s (PMaybe (PAsData b)))
-> Term s (c :--> (PAsData a :--> PMaybe (PAsData b)))
plam \Term s (PAsData k)
k Term s (PAsData a)
v ->
      Term s ((b :--> PAsData b) :--> (PMaybe b :--> PMaybe (PAsData b)))
forall (a :: S -> Type) (b :: S -> Type) (s :: S).
Term s ((a :--> b) :--> (PMaybe a :--> PMaybe b))
pmapMaybe Term s ((b :--> PAsData b) :--> (PMaybe b :--> PMaybe (PAsData b)))
-> Term s (b :--> PAsData b)
-> Term s (PMaybe b :--> PMaybe (PAsData b))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# (Term s b -> Term s (PAsData b)) -> Term s (b :--> PAsData b)
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s (PAsData b)) -> Term s (c :--> PAsData b)
plam Term s b -> Term s (PAsData b)
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s a -> Term s (PAsData a)
pdata Term s (PMaybe b :--> PMaybe (PAsData b))
-> Term s (PMaybe b) -> Term s (PMaybe (PAsData b))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# (Term s (k :--> (a :--> PMaybe b))
f Term s (k :--> (a :--> PMaybe b))
-> Term s k -> Term s (a :--> PMaybe b)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData k) -> Term s k
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData k)
k Term s (a :--> PMaybe b) -> Term s a -> Term s (PMaybe b)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData a) -> Term s a
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData a)
v)

--------------------------------------------------------------------------------
-- Handlers

zipMergeHandler ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type).
  Term s a ->
  Term s b ->
  Term s (a :--> b :--> c) ->
  MergeHandler s k a b c
zipMergeHandler :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s a
-> Term s b -> Term s (a :--> (b :--> c)) -> MergeHandler s k a b c
zipMergeHandler Term s a
defL Term s b
defR Term s (a :--> (b :--> c))
combine =
  MergeHandler
    { mhBothPresent :: BothPresentHandler s k a b c
mhBothPresent = Term s (k :--> (a :--> (b :--> c))) -> BothPresentHandler s k a b c
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s (k :--> (a :--> (b :--> c))) -> BothPresentHandler s k a b c
HandleBoth (Term s (k :--> (a :--> (b :--> c)))
 -> BothPresentHandler s k a b c)
-> Term s (k :--> (a :--> (b :--> c)))
-> BothPresentHandler s k a b c
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s a -> Term s b -> Term s c)
-> Term s (k :--> (a :--> (b :--> c)))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s a -> Term s b -> Term s c)
-> Term s (c :--> (a :--> (b :--> c)))
plam (\Term s k
_ Term s a
valL Term s b
valR -> Term s (a :--> (b :--> c))
combine Term s (a :--> (b :--> c)) -> Term s a -> Term s (b :--> c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s a
valL Term s (b :--> c) -> Term s b -> Term s c
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s b
valR)
    , mhLeftPresent :: OnePresentHandler s k a c
mhLeftPresent = Term s (k :--> (a :--> c)) -> OnePresentHandler s k a c
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> b)) -> OnePresentHandler s k a b
HandleOne (Term s (k :--> (a :--> c)) -> OnePresentHandler s k a c)
-> Term s (k :--> (a :--> c)) -> OnePresentHandler s k a c
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s a -> Term s c) -> Term s (k :--> (a :--> c))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s a -> Term s c) -> Term s (c :--> (a :--> c))
plam (\Term s k
_ Term s a
valL -> Term s (a :--> (b :--> c))
combine Term s (a :--> (b :--> c)) -> Term s a -> Term s (b :--> c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s a
valL Term s (b :--> c) -> Term s b -> Term s c
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s b
defR)
    , mhRightPresent :: OnePresentHandler s k b c
mhRightPresent = Term s (k :--> (b :--> c)) -> OnePresentHandler s k b c
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> b)) -> OnePresentHandler s k a b
HandleOne (Term s (k :--> (b :--> c)) -> OnePresentHandler s k b c)
-> Term s (k :--> (b :--> c)) -> OnePresentHandler s k b c
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s b -> Term s c) -> Term s (k :--> (b :--> c))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s b -> Term s c) -> Term s (c :--> (b :--> c))
plam (\Term s k
_ Term s b
valR -> Term s (a :--> (b :--> c))
combine Term s (a :--> (b :--> c)) -> Term s a -> Term s (b :--> c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s a
defL Term s (b :--> c) -> Term s b -> Term s c
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s b
valR)
    }

intersectionMergeHandler ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type).
  Term s (a :--> b :--> c) ->
  MergeHandler s k a b c
intersectionMergeHandler :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s (a :--> (b :--> c)) -> MergeHandler s k a b c
intersectionMergeHandler Term s (a :--> (b :--> c))
merge =
  MergeHandler
    { mhBothPresent :: BothPresentHandler s k a b c
mhBothPresent = Term s (k :--> (a :--> (b :--> c))) -> BothPresentHandler s k a b c
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s (k :--> (a :--> (b :--> c))) -> BothPresentHandler s k a b c
HandleBoth (Term s (k :--> (a :--> (b :--> c)))
 -> BothPresentHandler s k a b c)
-> Term s (k :--> (a :--> (b :--> c)))
-> BothPresentHandler s k a b c
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s a -> Term s b -> Term s c)
-> Term s (k :--> (a :--> (b :--> c)))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s a -> Term s b -> Term s c)
-> Term s (c :--> (a :--> (b :--> c)))
plam (\Term s k
_ Term s a
valL Term s b
valR -> Term s (a :--> (b :--> c))
merge Term s (a :--> (b :--> c)) -> Term s a -> Term s (b :--> c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s a
valL Term s (b :--> c) -> Term s b -> Term s c
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s b
valR)
    , mhLeftPresent :: OnePresentHandler s k a c
mhLeftPresent = OnePresentHandler s k a c
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
OnePresentHandler s k a b
DropOne
    , mhRightPresent :: OnePresentHandler s k b c
mhRightPresent = OnePresentHandler s k b c
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
OnePresentHandler s k a b
DropOne
    }

differenceMergeHandler ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
  MergeHandler s k a b a
differenceMergeHandler :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
MergeHandler s k a b a
differenceMergeHandler =
  MergeHandler
    { mhBothPresent :: BothPresentHandler s k a b a
mhBothPresent = BothPresentHandler s k a b a
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
BothPresentHandler s k a b c
DropBoth
    , mhLeftPresent :: OnePresentHandler s k a a
mhLeftPresent = Term s (k :--> (a :--> a)) -> OnePresentHandler s k a a
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> b)) -> OnePresentHandler s k a b
HandleOne (Term s (k :--> (a :--> a)) -> OnePresentHandler s k a a)
-> Term s (k :--> (a :--> a)) -> OnePresentHandler s k a a
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s a -> Term s a) -> Term s (k :--> (a :--> a))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s a -> Term s a) -> Term s (c :--> (a :--> a))
plam (\Term s k
_ Term s a
valL -> Term s a
valL)
    , mhRightPresent :: OnePresentHandler s k b a
mhRightPresent = OnePresentHandler s k b a
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
OnePresentHandler s k a b
DropOne
    }

unionMergeHandler ::
  forall (s :: S) (k :: S -> Type) (v :: S -> Type).
  Term s (v :--> v :--> v) ->
  MergeHandler s k v v v
unionMergeHandler :: forall (s :: S) (k :: S -> Type) (v :: S -> Type).
Term s (v :--> (v :--> v)) -> MergeHandler s k v v v
unionMergeHandler Term s (v :--> (v :--> v))
merge =
  MergeHandler
    { mhBothPresent :: BothPresentHandler s k v v v
mhBothPresent = Term s (k :--> (v :--> (v :--> v))) -> BothPresentHandler s k v v v
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
Term s (k :--> (a :--> (b :--> c))) -> BothPresentHandler s k a b c
HandleBoth (Term s (k :--> (v :--> (v :--> v)))
 -> BothPresentHandler s k v v v)
-> Term s (k :--> (v :--> (v :--> v)))
-> BothPresentHandler s k v v v
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s v -> Term s v -> Term s v)
-> Term s (k :--> (v :--> (v :--> v)))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s v -> Term s v -> Term s v)
-> Term s (c :--> (v :--> (v :--> v)))
plam (\Term s k
_ Term s v
valL Term s v
valR -> Term s (v :--> (v :--> v))
merge Term s (v :--> (v :--> v)) -> Term s v -> Term s (v :--> v)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s v
valL Term s (v :--> v) -> Term s v -> Term s v
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s v
valR)
    , mhLeftPresent :: OnePresentHandler s k v v
mhLeftPresent = Term s (k :--> (v :--> v)) -> OnePresentHandler s k v v
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> b)) -> OnePresentHandler s k a b
HandleOne (Term s (k :--> (v :--> v)) -> OnePresentHandler s k v v)
-> Term s (k :--> (v :--> v)) -> OnePresentHandler s k v v
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s v -> Term s v) -> Term s (k :--> (v :--> v))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s v -> Term s v) -> Term s (c :--> (v :--> v))
plam (\Term s k
_ Term s v
valL -> Term s v
valL)
    , mhRightPresent :: OnePresentHandler s k v v
mhRightPresent = Term s (k :--> (v :--> v)) -> OnePresentHandler s k v v
forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type).
Term s (k :--> (a :--> b)) -> OnePresentHandler s k a b
HandleOne (Term s (k :--> (v :--> v)) -> OnePresentHandler s k v v)
-> Term s (k :--> (v :--> v)) -> OnePresentHandler s k v v
forall a b. (a -> b) -> a -> b
$ (Term s k -> Term s v -> Term s v) -> Term s (k :--> (v :--> v))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s v -> Term s v) -> Term s (c :--> (v :--> v))
plam (\Term s k
_ Term s v
valR -> Term s v
valR)
    }

leftBiasedUnionMergeHandler ::
  forall (s :: S) (k :: S -> Type) (v :: S -> Type).
  MergeHandler s k v v v
leftBiasedUnionMergeHandler :: forall (s :: S) (k :: S -> Type) (v :: S -> Type).
MergeHandler s k v v v
leftBiasedUnionMergeHandler = Term s (v :--> (v :--> v)) -> MergeHandler s k v v v
forall (s :: S) (k :: S -> Type) (v :: S -> Type).
Term s (v :--> (v :--> v)) -> MergeHandler s k v v v
unionMergeHandler (Term s (v :--> (v :--> v)) -> MergeHandler s k v v v)
-> Term s (v :--> (v :--> v)) -> MergeHandler s k v v v
forall a b. (a -> b) -> a -> b
$ (Term s v -> Term s v -> Term s v) -> Term s (v :--> (v :--> v))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c -> Term s v -> Term s v) -> Term s (c :--> (v :--> v))
plam Term s v -> Term s v -> Term s v
forall a b. a -> b -> a
const

--------------------------------------------------------------------------------
-- Logic

zipWorker ::
  forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type) (c :: S -> Type).
  ( POrd k
  , PIsData k
  ) =>
  MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c) ->
  Term
    s
    ( PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
        :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
        :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
    )
zipWorker :: forall (s :: S) (k :: S -> Type) (a :: S -> Type) (b :: S -> Type)
       (c :: S -> Type).
(POrd k, PIsData k) =>
MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
      :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
            :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
zipWorker MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandler =
  (Term
   s
   (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
    :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
          :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
 -> Term
      s
      (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
       :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
             :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
      :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
            :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (a :: S -> Type) (b :: S -> Type) (s :: S).
(Term s (a :--> b) -> Term s (a :--> b)) -> Term s (a :--> b)
pfix ((Term
    s
    (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
     :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
           :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
  -> Term
       s
       (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
        :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
              :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
 -> Term
      s
      (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
       :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
             :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
-> (Term
      s
      (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
       :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
             :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
    -> Term
         s
         (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
          :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
                :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
      :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
            :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall a b. (a -> b) -> a -> b
$ \Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
self -> (Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
      :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
            :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall a (b :: S -> Type) (s :: S) (c :: S -> Type).
(PLamN a b s, HasCallStack) =>
(Term s c -> a) -> Term s (c :--> b)
forall (c :: S -> Type).
HasCallStack =>
(Term s c
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term
     s
     (c
      :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
            :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
plam ((Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
  -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
  -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
 -> Term
      s
      (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
       :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
             :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
-> (Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
      :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
            :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall a b. (a -> b) -> a -> b
$ \Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
mapL Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
mapR ->
    Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
-> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)) s
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S) (b :: S -> Type).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
mapL ((PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)) s
  -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)) s
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall a b. (a -> b) -> a -> b
$ \case
      PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)) s
PNil ->
        case MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandler.mhRightPresent of
          OnePresentHandler s (PAsData k) (PAsData b) (PAsData c)
DropOne -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S).
PElemConstraint PBuiltinList a =>
Term s (PBuiltinList a)
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a)
pnil
          HandleOne Term s (PAsData k :--> (PAsData b :--> PAsData c))
handler ->
            Term
  s
  ((PBuiltinPair (PAsData k) (PAsData b)
    :--> PBuiltinPair (PAsData k) (PAsData c))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (b :: S -> Type) (s :: S).
(PListLike list, PElemConstraint list a, PElemConstraint list b) =>
Term s ((a :--> b) :--> (list a :--> list b))
PPrelude.pmap
              # plam
                ( \entry -> P.do
                    PBuiltinPair k v <- pmatch entry
                    ppairDataBuiltin # k #$ handler # k # v
                )
              # mapR
          HandleOrDropOne Term s (PAsData k :--> (PAsData b :--> PMaybe (PAsData c)))
handler ->
            Term
  s
  ((PBuiltinPair (PAsData k) (PAsData b)
    :--> PMaybe (PBuiltinPair (PAsData k) (PAsData c)))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (b :: S -> Type) (a :: S -> Type)
       (list :: (S -> Type) -> S -> Type) (s :: S).
(PListLike list, PElemConstraint list a, PElemConstraint list b) =>
Term s ((a :--> PMaybe b) :--> (list a :--> list b))
pmapDropNothing
              # plam
                ( \entry -> P.do
                    PBuiltinPair k v <- pmatch entry
                    pmapMaybe # plam (\z -> ppairDataBuiltin # k # z) # (handler # k # v)
                )
              # mapR
      PCons Term s (PBuiltinPair (PAsData k) (PAsData a))
entryL Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
restL ->
        Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
-> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)) s
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S) (b :: S -> Type).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
mapR ((PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)) s
  -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)) s
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall a b. (a -> b) -> a -> b
$ \case
          PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)) s
PNil ->
            case MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandler.mhLeftPresent of
              OnePresentHandler s (PAsData k) (PAsData a) (PAsData c)
DropOne -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S).
PElemConstraint PBuiltinList a =>
Term s (PBuiltinList a)
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a)
pnil
              HandleOne Term s (PAsData k :--> (PAsData a :--> PAsData c))
handler ->
                Term
  s
  ((PBuiltinPair (PAsData k) (PAsData a)
    :--> PBuiltinPair (PAsData k) (PAsData c))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (b :: S -> Type) (s :: S).
(PListLike list, PElemConstraint list a, PElemConstraint list b) =>
Term s ((a :--> b) :--> (list a :--> list b))
PPrelude.pmap
                  # plam
                    ( \entry -> P.do
                        PBuiltinPair k v <- pmatch entry
                        ppairDataBuiltin # k #$ handler # k # v
                    )
                  # mapL
              HandleOrDropOne Term s (PAsData k :--> (PAsData a :--> PMaybe (PAsData c)))
handler ->
                Term
  s
  ((PBuiltinPair (PAsData k) (PAsData a)
    :--> PMaybe (PBuiltinPair (PAsData k) (PAsData c)))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (b :: S -> Type) (a :: S -> Type)
       (list :: (S -> Type) -> S -> Type) (s :: S).
(PListLike list, PElemConstraint list a, PElemConstraint list b) =>
Term s ((a :--> PMaybe b) :--> (list a :--> list b))
pmapDropNothing
                  # plam
                    ( \entry -> P.do
                        PBuiltinPair k v <- pmatch entry
                        pmapMaybe # plam (\z -> ppairDataBuiltin # k # z) # (handler # k # v)
                    )
                  # mapL
          PCons Term s (PBuiltinPair (PAsData k) (PAsData b))
entryR Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
restR -> P.do
            PBuiltinPair Term s (PAsData k)
keyDataL Term s (PAsData a)
valL <- Term s (PBuiltinPair (PAsData k) (PAsData a))
-> (PBuiltinPair (PAsData k) (PAsData a) s
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S) (b :: S -> Type).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s (PBuiltinPair (PAsData k) (PAsData a))
entryL
            PBuiltinPair Term s (PAsData k)
keyDataR Term s (PAsData b)
valR <- Term s (PBuiltinPair (PAsData k) (PAsData b))
-> (PBuiltinPair (PAsData k) (PAsData b) s
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S) (b :: S -> Type).
PlutusType a =>
Term s a -> (a s -> Term s b) -> Term s b
pmatch Term s (PBuiltinPair (PAsData k) (PAsData b))
entryR
            Term s k
keyL <- Term s k
-> (Term s k
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s a -> (Term s a -> Term s b) -> Term s b
plet (Term s k
 -> (Term s k
     -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s k
-> (Term s k
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall a b. (a -> b) -> a -> b
$ Term s (PAsData k) -> Term s k
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData k)
keyDataL
            Term s k
keyR <- Term s k
-> (Term s k
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s a -> (Term s a -> Term s b) -> Term s b
plet (Term s k
 -> (Term s k
     -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
 -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s k
-> (Term s k
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall a b. (a -> b) -> a -> b
$ Term s (PAsData k) -> Term s k
forall (a :: S -> Type) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData Term s (PAsData k)
keyDataR
            Term s PBool
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
              (Term s k
keyL Term s k -> Term s k -> Term s PBool
forall (s :: S). Term s k -> Term s k -> Term s PBool
forall (t :: S -> Type) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s k
keyR)
              ( let
                  xs :: Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs = Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
self Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
      :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
restL Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
   :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
restR
                  k :: Term s (PAsData k)
k = Term s (PAsData k)
keyDataL
                 in
                  case MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandler.mhBothPresent of
                    BothPresentHandler
  s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
DropBoth ->
                      Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                    HandleBoth Term s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
handler ->
                      Term
  s
  (PBuiltinPair (PAsData k) (PAsData c)
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (a :: S -> Type) (s :: S).
PElemConstraint PBuiltinList a =>
Term s (a :--> (PBuiltinList a :--> PBuiltinList a))
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (a :--> (list a :--> list a))
pcons Term
  s
  (PBuiltinPair (PAsData k) (PAsData c)
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinPair (PAsData k) (PAsData c))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
      :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# (Term
  s
  (PAsData k
   :--> (PAsData c :--> PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term
  s
  (PAsData a
   :--> (PAsData b :--> PBuiltinPair (PAsData a) (PAsData b)))
ppairDataBuiltin Term
  s
  (PAsData k
   :--> (PAsData c :--> PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PAsData k)
-> Term s (PAsData c :--> PBuiltinPair (PAsData k) (PAsData c))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData k)
k Term s (PAsData c :--> PBuiltinPair (PAsData k) (PAsData c))
-> Term s (PAsData c)
-> Term s (PBuiltinPair (PAsData k) (PAsData c))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
#$ Term s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
handler Term s (PAsData k :--> (PAsData a :--> (PAsData b :--> PAsData c)))
-> Term s (PAsData k)
-> Term s (PAsData a :--> (PAsData b :--> PAsData c))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData k)
k Term s (PAsData a :--> (PAsData b :--> PAsData c))
-> Term s (PAsData a) -> Term s (PAsData b :--> PAsData c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData a)
valL Term s (PAsData b :--> PAsData c)
-> Term s (PAsData b) -> Term s (PAsData c)
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData b)
valR) Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
   :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                    HandleOrDropBoth Term
  s
  (PAsData k
   :--> (PAsData a :--> (PAsData b :--> PMaybe (PAsData c))))
handler -> P.do
                      Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
zipped <- Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> (Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s a -> (Term s a -> Term s b) -> Term s b
plet Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                      Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
   :--> ((PAsData c
          :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
         :--> (PMaybe (PAsData c)
               :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s (b :--> ((a :--> b) :--> (PMaybe a :--> b)))
pmaybe
                        # zipped
                        # plam (\v -> pcons # (ppairDataBuiltin # k # v) # zipped)
                        # (handler # k # valL # valR)
              )
              ( Term s PBool
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (a :: S -> Type) (s :: S).
Term s PBool -> Term s a -> Term s a -> Term s a
pif
                  (Term s k
keyL Term s k -> Term s k -> Term s PBool
forall (s :: S). Term s k -> Term s k -> Term s PBool
forall (t :: S -> Type) (s :: S).
POrd t =>
Term s t -> Term s t -> Term s PBool
#< Term s k
keyR)
                  ( let
                      xs :: Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs = Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
self Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
      :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
restL Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
   :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
mapR
                     in
                      case MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandler.mhLeftPresent of
                        OnePresentHandler s (PAsData k) (PAsData a) (PAsData c)
DropOne -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                        HandleOne Term s (PAsData k :--> (PAsData a :--> PAsData c))
handler ->
                          Term
  s
  (PBuiltinPair (PAsData k) (PAsData c)
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (a :: S -> Type) (s :: S).
PElemConstraint PBuiltinList a =>
Term s (a :--> (PBuiltinList a :--> PBuiltinList a))
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (a :--> (list a :--> list a))
pcons
                            # (ppairDataBuiltin # keyDataL #$ handler # keyDataL # valL)
                            # xs
                        HandleOrDropOne Term s (PAsData k :--> (PAsData a :--> PMaybe (PAsData c)))
handler -> P.do
                          Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
zipped <- Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> (Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s a -> (Term s a -> Term s b) -> Term s b
plet Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                          Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
   :--> ((PAsData c
          :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
         :--> (PMaybe (PAsData c)
               :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s (b :--> ((a :--> b) :--> (PMaybe a :--> b)))
pmaybe
                            # zipped
                            # plam (\v -> pcons # (ppairDataBuiltin # keyDataL # v) # zipped)
                            # (handler # keyDataL # valL)
                  )
                  ( let
                      xs :: Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs = Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
self Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a))
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
-> Term
     s
     (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
      :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData a)))
mapL Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b))
   :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData b)))
restR
                     in
                      case MergeHandler s (PAsData k) (PAsData a) (PAsData b) (PAsData c)
mergeHandler.mhRightPresent of
                        OnePresentHandler s (PAsData k) (PAsData b) (PAsData c)
DropOne -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                        HandleOne Term s (PAsData k :--> (PAsData b :--> PAsData c))
handler ->
                          Term
  s
  (PBuiltinPair (PAsData k) (PAsData c)
   :--> (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
         :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
forall (a :: S -> Type) (s :: S).
PElemConstraint PBuiltinList a =>
Term s (a :--> (PBuiltinList a :--> PBuiltinList a))
forall (list :: (S -> Type) -> S -> Type) (a :: S -> Type)
       (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (a :--> (list a :--> list a))
pcons
                            # (ppairDataBuiltin # keyDataR #$ handler # keyDataR # valR)
                            # xs
                        HandleOrDropOne Term s (PAsData k :--> (PAsData b :--> PMaybe (PAsData c)))
handler -> P.do
                          Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
zipped <- Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
-> (Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
    -> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))))
-> Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s a -> (Term s a -> Term s b) -> Term s b
plet Term s (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
xs
                          Term
  s
  (PBuiltinList (PBuiltinPair (PAsData k) (PAsData c))
   :--> ((PAsData c
          :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))
         :--> (PMaybe (PAsData c)
               :--> PBuiltinList (PBuiltinPair (PAsData k) (PAsData c)))))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s (b :--> ((a :--> b) :--> (PMaybe a :--> b)))
pmaybe
                            # zipped
                            # plam (\v -> pcons # (ppairDataBuiltin # keyDataR # v) # zipped)
                            # (handler # keyDataR # valR)
                  )
              )