module Plutarch.Internal.Fix (pfixHoisted, pfix, pfixInline) where
import Data.Kind (Type)
import Plutarch.Builtin.Opaque (POpaque)
import Plutarch.Internal.PLam (plam)
import Plutarch.Internal.Term (
S,
Term,
phoistAcyclic,
plam',
punsafeCoerce,
(#),
(:-->),
)
pfixHoisted :: Term s (((a :--> b) :--> a :--> b) :--> a :--> b)
pfixHoisted :: forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (((a :--> b) :--> (a :--> b)) :--> (a :--> b))
pfixHoisted = (forall (s' :: S).
Term s' (((a :--> b) :--> (a :--> b)) :--> (a :--> b)))
-> Term s (((a :--> b) :--> (a :--> b)) :--> (a :--> b))
forall (a :: S -> Type) (s :: S).
HasCallStack =>
(forall (s' :: S). Term s' a) -> Term s a
phoistAcyclic ((forall (s' :: S).
Term s' (((a :--> b) :--> (a :--> b)) :--> (a :--> b)))
-> Term s (((a :--> b) :--> (a :--> b)) :--> (a :--> b)))
-> (forall (s' :: S).
Term s' (((a :--> b) :--> (a :--> b)) :--> (a :--> b)))
-> Term s (((a :--> b) :--> (a :--> b)) :--> (a :--> b))
forall a b. (a -> b) -> a -> b
$
Term
s'
(((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
:--> Any @(S -> Type))
-> Term s' (((a :--> b) :--> (a :--> b)) :--> (a :--> b))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s a -> Term s b
punsafeCoerce (Term
s'
(((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
:--> Any @(S -> Type))
-> Term s' (((a :--> b) :--> (a :--> b)) :--> (a :--> b)))
-> Term
s'
(((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
:--> Any @(S -> Type))
-> Term s' (((a :--> b) :--> (a :--> b)) :--> (a :--> b))
forall a b. (a -> b) -> a -> b
$
(Term s' ((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
-> Term s' (Any @(S -> Type)))
-> Term
s'
(((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
:--> Any @(S -> Type))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
(Term s a -> Term s b) -> Term s (a :--> b)
plam' ((Term s' ((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
-> Term s' (Any @(S -> Type)))
-> Term
s'
(((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
:--> Any @(S -> Type)))
-> (Term s' ((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
-> Term s' (Any @(S -> Type)))
-> Term
s'
(((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
:--> Any @(S -> Type))
forall a b. (a -> b) -> a -> b
$ \Term s' ((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
f ->
(Term s' POpaque -> Term s' (Any @(S -> Type)))
-> Term s' (POpaque :--> Any @(S -> Type))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
(Term s a -> Term s b) -> Term s (a :--> b)
plam' (\(Term s' POpaque
x :: Term s POpaque) -> Term s' ((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
f Term s' ((POpaque :--> Any @(S -> Type)) :--> Any @(S -> Type))
-> Term s' (POpaque :--> Any @(S -> Type))
-> Term s' (Any @(S -> Type))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# (Term s' POpaque -> Term s' (Any @(S -> Type)))
-> Term s' (POpaque :--> Any @(S -> Type))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
(Term s a -> Term s b) -> Term s (a :--> b)
plam' (\(Term s' POpaque
v :: Term s POpaque) -> Term s' POpaque
-> Term s' (POpaque :--> (POpaque :--> Any @(S -> Type)))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s a -> Term s b
punsafeCoerce Term s' POpaque
x Term s' (POpaque :--> (POpaque :--> Any @(S -> Type)))
-> Term s' POpaque -> Term s' (POpaque :--> Any @(S -> Type))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s' POpaque
x Term s' (POpaque :--> Any @(S -> Type))
-> Term s' POpaque -> Term s' (Any @(S -> Type))
forall (s :: S) (a :: S -> Type) (b :: S -> Type).
Term s (a :--> b) -> Term s a -> Term s b
# Term s' POpaque
v))
# punsafeCoerce (plam' $ \(x :: Term s POpaque) -> f # plam' (\(v :: Term s POpaque) -> punsafeCoerce x # x # v))
pfix ::
forall (a :: S -> Type) (b :: S -> Type) (s :: S).
(Term s (a :--> b) -> Term s (a :--> b)) ->
Term s (a :--> b)
pfix :: forall (a :: S -> Type) (b :: S -> Type) (s :: S).
(Term s (a :--> b) -> Term s (a :--> b)) -> Term s (a :--> b)
pfix Term s (a :--> b) -> Term s (a :--> b)
f =
(Term s (Any @(S -> Type) :--> (a :--> b)) -> Term s (a :--> b))
-> Term s ((Any @(S -> Type) :--> (a :--> b)) :--> (a :--> 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 (a :--> b)) -> Term s (c :--> (a :--> b))
plam (\Term s (Any @(S -> Type) :--> (a :--> b))
r -> Term s (Any @(S -> Type) :--> (a :--> b))
-> Term s ((Any @(S -> Type) :--> (a :--> b)) :--> (a :--> b))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s a -> Term s b
punsafeCoerce Term s (Any @(S -> Type) :--> (a :--> b))
r Term s ((Any @(S -> Type) :--> (a :--> b)) :--> (a :--> b))
-> Term s (Any @(S -> Type) :--> (a :--> b)) -> 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 (Any @(S -> Type) :--> (a :--> b))
r)
# plam (\r -> f (punsafeCoerce r # r))
pfixInline ::
forall (a :: S -> Type) (b :: S -> Type) (s :: S).
(Term s (a :--> b) -> Term s (a :--> b)) ->
Term s (a :--> b)
pfixInline :: forall (a :: S -> Type) (b :: S -> Type) (s :: S).
(Term s (a :--> b) -> Term s (a :--> b)) -> Term s (a :--> b)
pfixInline Term s (a :--> b) -> Term s (a :--> b)
f =
(Term s (Any @(S -> Type) :--> (a :--> b)) -> Term s (a :--> b))
-> Term s ((Any @(S -> Type) :--> (a :--> b)) :--> (a :--> 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 (a :--> b)) -> Term s (c :--> (a :--> b))
plam (\Term s (Any @(S -> Type) :--> (a :--> b))
r -> Term s (a :--> b) -> Term s (a :--> b)
f (Term s (Any @(S -> Type) :--> (a :--> b))
-> Term s ((Any @(S -> Type) :--> (a :--> b)) :--> (a :--> b))
forall (b :: S -> Type) (a :: S -> Type) (s :: S).
Term s a -> Term s b
punsafeCoerce Term s (Any @(S -> Type) :--> (a :--> b))
r Term s ((Any @(S -> Type) :--> (a :--> b)) :--> (a :--> b))
-> Term s (Any @(S -> Type) :--> (a :--> b)) -> 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 (Any @(S -> Type) :--> (a :--> b))
r))
# plam (\r -> f (punsafeCoerce r # r))