module Plutarch.Api.V1.Tuple (PTuple, ptuple, ptupleFromBuiltin, pbuiltinPairFromTuple) where

import Plutarch.Builtin (pconstrBuiltin, pforgetData)
import Plutarch.Prelude
import Plutarch.Unsafe (punsafeCoerce)

type PTuple a b =
  PDataSum
    '[ '[ "_0" ':= a
        , "_1" ':= b
        ]
     ]

ptuple :: Term s (PAsData a :--> PAsData b :--> PTuple a b)
ptuple :: forall (s :: S) (a :: PType) (b :: PType).
Term s (PAsData a :--> (PAsData b :--> PTuple a b))
ptuple = 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 a)
x Term s (PAsData b)
y ->
    let target :: Term _ (PAsData (PBuiltinPair PInteger (PBuiltinList PData)))
        target :: Term s (PAsData (PBuiltinPair PInteger (PBuiltinList PData)))
target = forall (s :: S).
Term
  s
  (PInteger
   :--> (PBuiltinList PData
         :--> PAsData (PBuiltinPair PInteger (PBuiltinList PData))))
pconstrBuiltin 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
#$ forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (a :--> (list a :--> list a))
pcons 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 (PAsData a) -> Term s PData
pforgetData Term s (PAsData a)
x 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 (a :--> (list a :--> list a))
pcons 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 (PAsData a) -> Term s PData
pforgetData Term s (PAsData b)
y 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)
pnil
     in forall (s :: S) (a :: PType) (b :: PType). Term s a -> Term s b
punsafeCoerce Term s (PAsData (PBuiltinPair PInteger (PBuiltinList PData)))
target

ptupleFromBuiltin :: Term s (PAsData (PBuiltinPair (PAsData a) (PAsData b))) -> Term s (PAsData (PTuple a b))
ptupleFromBuiltin :: forall (s :: S) (a :: PType) (b :: PType).
Term s (PAsData (PBuiltinPair (PAsData a) (PAsData b)))
-> Term s (PAsData (PTuple a b))
ptupleFromBuiltin = forall (s :: S) (a :: PType) (b :: PType). Term s a -> Term s b
punsafeCoerce

pbuiltinPairFromTuple :: Term s (PAsData (PTuple a b)) -> Term s (PAsData (PBuiltinPair (PAsData a) (PAsData b)))
pbuiltinPairFromTuple :: forall (s :: S) (a :: PType) (b :: PType).
Term s (PAsData (PTuple a b))
-> Term s (PAsData (PBuiltinPair (PAsData a) (PAsData b)))
pbuiltinPairFromTuple = forall (s :: S) (a :: PType) (b :: PType). Term s a -> Term s b
punsafeCoerce