Skip to main content

oxilean_std/functional_programming/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8    AffineTraversal, ApplicativeData, Arrow, ArrowData, Coerce, ComonadExtend, ConsoleEffect,
9    ConsoleProg, CpsTransform, DefunctClosure, DependentTypeExample, Effect, EffectHandler,
10    EffectSystem, FreeApplicative, FreeMonad, FreeMonadInfo, FreeMonadInterpreter, Futumorphism,
11    HList, HMap, Histomorphism, HomotopyEquivalence, Hylomorphism, Iso, Lens, LensComposer,
12    Paramorphism, Prism, ProfunctorData, ProfunctorOptic, RecursionSchemeEval, RoseTree, Singleton,
13    TraversableData, Traversal, TypeConstructorFunctor, TypeEquality, Zipper,
14};
15
16pub fn app(f: Expr, a: Expr) -> Expr {
17    Expr::App(Box::new(f), Box::new(a))
18}
19pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
20    app(app(f, a), b)
21}
22pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
23    app(app2(f, a, b), c)
24}
25pub fn cst(s: &str) -> Expr {
26    Expr::Const(Name::str(s), vec![])
27}
28pub fn prop() -> Expr {
29    Expr::Sort(Level::zero())
30}
31pub fn type0() -> Expr {
32    Expr::Sort(Level::succ(Level::zero()))
33}
34pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
35    Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
36}
37pub fn arrow(a: Expr, b: Expr) -> Expr {
38    pi(BinderInfo::Default, "_", a, b)
39}
40pub fn bvar(n: u32) -> Expr {
41    Expr::BVar(n)
42}
43pub fn fn_ty(dom: Expr, cod: Expr) -> Expr {
44    arrow(dom, cod)
45}
46/// `FreeMonad : (Type → Type) → Type → Type`
47///
48/// Free monad: Free(F, A) = Pure A | Free (F (Free F A)).
49pub fn free_monad_ty() -> Expr {
50    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
51}
52/// `Cofree : (Type → Type) → Type → Type`
53///
54/// Cofree comonad: Cofree F A = { extract: A, unwrap: F (Cofree F A) }.
55pub fn cofree_ty() -> Expr {
56    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
57}
58/// `FixPoint : (Type → Type) → Type`
59///
60/// Least/greatest fixed point Fix F = F (Fix F).
61pub fn fixpoint_ty() -> Expr {
62    arrow(fn_ty(type0(), type0()), type0())
63}
64/// `Mu : (Type → Type) → Type`
65///
66/// Least fixed point (initial algebra / inductive type).
67pub fn mu_ty() -> Expr {
68    arrow(fn_ty(type0(), type0()), type0())
69}
70/// `Nu : (Type → Type) → Type`
71///
72/// Greatest fixed point (terminal coalgebra / coinductive type).
73pub fn nu_ty() -> Expr {
74    arrow(fn_ty(type0(), type0()), type0())
75}
76/// `Cata : (F A → A) → Fix F → A`  (catamorphism type template)
77///
78/// Represented as: (Type → Type) → Type → Type → Type.
79pub fn cata_ty() -> Expr {
80    pi(
81        BinderInfo::Default,
82        "F",
83        fn_ty(type0(), type0()),
84        pi(
85            BinderInfo::Default,
86            "A",
87            type0(),
88            arrow(
89                fn_ty(app(bvar(1), bvar(0)), bvar(0)),
90                arrow(app(cst("FixPoint"), bvar(2)), bvar(1)),
91            ),
92        ),
93    )
94}
95/// `Ana : (A → F A) → A → Fix F`  (anamorphism type template)
96pub fn ana_ty() -> Expr {
97    pi(
98        BinderInfo::Default,
99        "F",
100        fn_ty(type0(), type0()),
101        pi(
102            BinderInfo::Default,
103            "A",
104            type0(),
105            arrow(
106                fn_ty(bvar(0), app(bvar(1), bvar(0))),
107                arrow(bvar(0), app(cst("FixPoint"), bvar(2))),
108            ),
109        ),
110    )
111}
112/// `Hylo : (F B → B) → (A → F A) → A → B`  (hylomorphism)
113pub fn hylo_ty() -> Expr {
114    pi(
115        BinderInfo::Default,
116        "F",
117        fn_ty(type0(), type0()),
118        pi(
119            BinderInfo::Default,
120            "A",
121            type0(),
122            pi(
123                BinderInfo::Default,
124                "B",
125                type0(),
126                arrow(
127                    fn_ty(app(bvar(2), bvar(0)), bvar(0)),
128                    arrow(
129                        fn_ty(bvar(1), app(bvar(2), bvar(1))),
130                        arrow(bvar(1), bvar(0)),
131                    ),
132                ),
133            ),
134        ),
135    )
136}
137/// `Catamorphism : (Type → Type) → Type → Type`
138///
139/// Fold over a recursive data type (Fix F).
140pub fn catamorphism_ty() -> Expr {
141    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
142}
143/// `Paramorphism : (Type → Type) → Type → Type`
144///
145/// Extended fold with access to the original sub-structure.
146pub fn paramorphism_ty() -> Expr {
147    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
148}
149/// `Histomorphism : (Type → Type) → Type → Type`
150///
151/// Fold with access to the computation history (course-of-values recursion).
152pub fn histomorphism_ty() -> Expr {
153    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
154}
155/// `Futumorphism : (Type → Type) → Type → Type`
156///
157/// Unfold with lookahead via the Cofree comonad.
158pub fn futumorphism_ty() -> Expr {
159    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
160}
161/// `Hylomorphism : (Type → Type) → Type → Type → Type`
162///
163/// Virtual data structure: fold ∘ unfold without materialising the intermediate Fix F.
164pub fn hylomorphism_ty() -> Expr {
165    arrow(
166        fn_ty(type0(), type0()),
167        arrow(type0(), fn_ty(type0(), type0())),
168    )
169}
170/// `Chronomorphism : (Type → Type) → Type → Type`
171///
172/// Combined histomorphism + futumorphism.
173pub fn chronomorphism_ty() -> Expr {
174    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
175}
176/// `Lens : Type → Type → Type`
177///
178/// (get: S → A, set: A → S → S) — lawful focus on a single A inside S.
179pub fn lens_ty() -> Expr {
180    arrow(type0(), fn_ty(type0(), type0()))
181}
182/// `Prism : Type → Type → Type`
183///
184/// (preview: S → Option A, review: A → S) — partial / sum type focus.
185pub fn prism_ty() -> Expr {
186    arrow(type0(), fn_ty(type0(), type0()))
187}
188/// `Traversal : Type → Type → Type`
189///
190/// Focus on zero or more As inside S.
191pub fn traversal_ty() -> Expr {
192    arrow(type0(), fn_ty(type0(), type0()))
193}
194/// `Iso : Type → Type → Type`
195///
196/// Isomorphism S ≅ A: (to: S → A, from: A → S).
197pub fn iso_ty() -> Expr {
198    arrow(type0(), fn_ty(type0(), type0()))
199}
200/// `AffineTraversal : Type → Type → Type`
201///
202/// Focus on 0 or 1 A inside S (between Lens and Traversal).
203pub fn affine_traversal_ty() -> Expr {
204    arrow(type0(), fn_ty(type0(), type0()))
205}
206/// `Effect : Type → Type → Type`
207///
208/// Computation with effect row E producing A.
209pub fn effect_ty() -> Expr {
210    arrow(type0(), fn_ty(type0(), type0()))
211}
212/// `EffectHandler : Type → Type → Type → Type`
213///
214/// Handles effect E in a computation, delegating remaining effects R.
215pub fn effect_handler_ty() -> Expr {
216    arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
217}
218/// `AlgebraicEffect : Type → Type → Type`
219///
220/// Effect type + operation + continuation.
221pub fn algebraic_effect_ty() -> Expr {
222    arrow(type0(), fn_ty(type0(), type0()))
223}
224/// `FreeSelective : (Type → Type) → Type → Type`
225///
226/// Free selective applicative functor.
227pub fn free_selective_ty() -> Expr {
228    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
229}
230/// `Arrow : Type → Type → Type`
231///
232/// Generalized function f a b with arr / >>> / *** / first.
233pub fn arrow_ty() -> Expr {
234    arrow(type0(), fn_ty(type0(), type0()))
235}
236/// `HList : Type`
237///
238/// Heterogeneous list: HNil | HCons H Tail.
239pub fn hlist_ty() -> Expr {
240    type0()
241}
242/// `HMap : Type → Type → Type`
243///
244/// Type-level map from keys to values.
245pub fn hmap_ty() -> Expr {
246    arrow(type0(), fn_ty(type0(), type0()))
247}
248/// `Singleton : Type → Type`
249///
250/// Value reflected at the type level.
251pub fn singleton_ty() -> Expr {
252    arrow(type0(), type0())
253}
254/// `TypeEquality : Type → Type → Prop`
255///
256/// Propositional evidence that S ~ T.
257pub fn type_equality_ty() -> Expr {
258    arrow(type0(), fn_ty(type0(), prop()))
259}
260/// `Coerce : Type → Type → Prop`
261///
262/// Coercion with proof obligation (safe reinterpretation).
263pub fn coerce_ty() -> Expr {
264    arrow(type0(), fn_ty(type0(), prop()))
265}
266/// `FreeMonadLeftUnit : ∀ (F : Type → Type) (A : Type), Prop`
267///
268/// Left unit law: bind (pure a) f = f a.
269pub fn free_monad_left_unit_ty() -> Expr {
270    pi(
271        BinderInfo::Default,
272        "F",
273        fn_ty(type0(), type0()),
274        arrow(type0(), prop()),
275    )
276}
277/// `FreeMonadRightUnit : ∀ (F : Type → Type) (A : Type), Prop`
278///
279/// Right unit law: bind m pure = m.
280pub fn free_monad_right_unit_ty() -> Expr {
281    pi(
282        BinderInfo::Default,
283        "F",
284        fn_ty(type0(), type0()),
285        arrow(type0(), prop()),
286    )
287}
288/// `LensGetSet : ∀ (S A : Type), Lens S A → Prop`
289///
290/// GetSet law: set (get s) s = s.
291pub fn lens_get_set_ty() -> Expr {
292    pi(
293        BinderInfo::Default,
294        "S",
295        type0(),
296        pi(
297            BinderInfo::Default,
298            "A",
299            type0(),
300            arrow(app2(cst("Lens"), bvar(1), bvar(0)), prop()),
301        ),
302    )
303}
304/// `LensSetGet : ∀ (S A : Type), Lens S A → Prop`
305///
306/// SetGet law: get (set a s) = a.
307pub fn lens_set_get_ty() -> Expr {
308    pi(
309        BinderInfo::Default,
310        "S",
311        type0(),
312        pi(
313            BinderInfo::Default,
314            "A",
315            type0(),
316            arrow(app2(cst("Lens"), bvar(1), bvar(0)), prop()),
317        ),
318    )
319}
320/// `IsoRoundtrip : ∀ (S A : Type), Iso S A → Prop`
321///
322/// from (to s) = s  ∧  to (from a) = a.
323pub fn iso_roundtrip_ty() -> Expr {
324    pi(
325        BinderInfo::Default,
326        "S",
327        type0(),
328        pi(
329            BinderInfo::Default,
330            "A",
331            type0(),
332            arrow(app2(cst("Iso"), bvar(1), bvar(0)), prop()),
333        ),
334    )
335}
336/// `CatamorphismFusion : ∀ (F : Type → Type) (A B : Type), Prop`
337///
338/// cata g ∘ cata f = cata (g ∘ fmap (cata f)).
339pub fn catamorphism_fusion_ty() -> Expr {
340    pi(
341        BinderInfo::Default,
342        "F",
343        fn_ty(type0(), type0()),
344        pi(BinderInfo::Default, "A", type0(), arrow(type0(), prop())),
345    )
346}
347/// `HyloFusion : ∀ (F : Type → Type) (A B : Type), Prop`
348///
349/// hylo alg coalg = cata alg ∘ ana coalg (deforestation).
350pub fn hylo_fusion_ty() -> Expr {
351    pi(
352        BinderInfo::Default,
353        "F",
354        fn_ty(type0(), type0()),
355        pi(BinderInfo::Default, "A", type0(), arrow(type0(), prop())),
356    )
357}
358/// A catamorphism (fold) over a list as a stand-in for Fix F.
359///
360/// `cata(alg, list)` = right-fold using `alg`.
361pub fn list_cata<A, B>(alg: impl Fn(Option<(A, B)>) -> B, list: Vec<A>) -> B {
362    list.into_iter()
363        .rev()
364        .fold(alg(None), |acc, a| alg(Some((a, acc))))
365}
366/// An anamorphism (unfold) producing a list from a seed.
367pub fn list_ana<A, S>(coalg: impl Fn(S) -> Option<(A, S)>, seed: S) -> Vec<A> {
368    let mut result = Vec::new();
369    let mut state = seed;
370    loop {
371        match coalg(state) {
372            None => break,
373            Some((a, next)) => {
374                result.push(a);
375                state = next;
376            }
377        }
378    }
379    result
380}
381/// A hylomorphism (fold ∘ unfold) without materialising the intermediate structure.
382pub fn list_hylo<A, B, S>(
383    alg: &dyn Fn(Option<(A, B)>) -> B,
384    coalg: &dyn Fn(S) -> Option<(A, S)>,
385    seed: S,
386) -> B {
387    match coalg(seed) {
388        None => alg(None),
389        Some((a, next)) => {
390            let rec = list_hylo(alg, coalg, next);
391            alg(Some((a, rec)))
392        }
393    }
394}
395/// A paramorphism over a list (extended fold with original tail access).
396pub fn list_para<A: Clone, B>(alg: impl Fn(Option<(A, Vec<A>, B)>) -> B, list: Vec<A>) -> B {
397    fn go<A: Clone, B>(alg: &dyn Fn(Option<(A, Vec<A>, B)>) -> B, slice: &[A]) -> B {
398        if slice.is_empty() {
399            alg(None)
400        } else {
401            let head = slice[0].clone();
402            let tail = slice[1..].to_vec();
403            let rec = go(alg, &slice[1..]);
404            alg(Some((head, tail, rec)))
405        }
406    }
407    go(&alg, &list)
408}
409/// `ScottDomain : Type`
410///
411/// A Scott domain: a dcpo (directed-complete partial order) used as denotational
412/// semantic domains for programming languages.
413pub fn scott_domain_ty() -> Expr {
414    type0()
415}
416/// `ScottContinuous : Type → Type → Prop`
417///
418/// Continuous function between Scott domains (preserves directed sups).
419pub fn scott_continuous_ty() -> Expr {
420    arrow(type0(), fn_ty(type0(), prop()))
421}
422/// `FixedPointSemantics : (Type → Type) → Type → Prop`
423///
424/// Kleene fixed-point: the least fixed point of a monotone endofunctor on a
425/// Scott domain, providing denotational semantics for recursive definitions.
426pub fn fixed_point_semantics_ty() -> Expr {
427    pi(
428        BinderInfo::Default,
429        "F",
430        fn_ty(type0(), type0()),
431        arrow(type0(), prop()),
432    )
433}
434/// `FullAbstraction : Type → Type → Prop`
435///
436/// Full abstraction: contextual equivalence = denotational equality.
437pub fn full_abstraction_ty() -> Expr {
438    arrow(type0(), fn_ty(type0(), prop()))
439}
440/// `LeastUpperBound : Type → Type → Prop`
441///
442/// Least upper bound (lub) of a directed set in a dcpo.
443pub fn least_upper_bound_ty() -> Expr {
444    arrow(type0(), fn_ty(type0(), prop()))
445}
446/// `ApproximationOrder : Type → Type → Prop`
447///
448/// Information ordering (⊑) in Scott domain theory.
449pub fn approximation_order_ty() -> Expr {
450    arrow(type0(), fn_ty(type0(), prop()))
451}
452/// `EffectRow : Type`
453///
454/// An effect row: a (possibly empty) collection of effect labels and their
455/// operation signatures.
456pub fn effect_row_ty() -> Expr {
457    type0()
458}
459/// `ScopedEffect : Type → Type → Type`
460///
461/// A scoped algebraic effect: effects that delimit their own scope (e.g., catch).
462pub fn scoped_effect_ty() -> Expr {
463    arrow(type0(), fn_ty(type0(), type0()))
464}
465/// `DeepHandler : Type → Type → Type → Type`
466///
467/// A deep handler for algebraic effects, handling the entire computation tree.
468/// Signature: EffectRow → ResultType → HandledType → Type.
469pub fn deep_handler_ty() -> Expr {
470    arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
471}
472/// `ShallowHandler : Type → Type → Type → Type`
473///
474/// A shallow handler for algebraic effects, handling only the first effect operation.
475pub fn shallow_handler_ty() -> Expr {
476    arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
477}
478/// `EffectSubrow : Type → Type → Prop`
479///
480/// Subrow relation: E ⊆ E', used for effect polymorphism.
481pub fn effect_subrow_ty() -> Expr {
482    arrow(type0(), fn_ty(type0(), prop()))
483}
484/// `FreerMonad : (Type → Type) → Type → Type`
485///
486/// Freer monad (extensible effects): Free(IFunctor, A).
487/// Avoids the Functor constraint using the Yoneda embedding trick.
488pub fn freer_monad_ty() -> Expr {
489    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
490}
491/// `FreeApplicative : (Type → Type) → Type → Type`
492///
493/// Free applicative functor: the free construction for applicatives.
494pub fn free_applicative_ty() -> Expr {
495    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
496}
497/// `FreeMonadBind : ∀ (F : Type → Type) (A B : Type), Prop`
498///
499/// Monadic bind for the free monad satisfies associativity.
500pub fn free_monad_bind_ty() -> Expr {
501    pi(
502        BinderInfo::Default,
503        "F",
504        fn_ty(type0(), type0()),
505        pi(BinderInfo::Default, "A", type0(), arrow(type0(), prop())),
506    )
507}
508/// `FreerLift : ∀ (F : Type → Type) (A : Type), F A → FreerMonad F A`
509///
510/// The canonical lift of a functor effect into the Freer monad.
511pub fn freer_lift_ty() -> Expr {
512    pi(
513        BinderInfo::Default,
514        "F",
515        fn_ty(type0(), type0()),
516        pi(
517            BinderInfo::Default,
518            "A",
519            type0(),
520            arrow(
521                app(bvar(1), bvar(0)),
522                app2(cst("FreerMonad"), bvar(2), bvar(1)),
523            ),
524        ),
525    )
526}
527/// `Profunctor : Type → Type → Type`
528///
529/// A profunctor P : Type^op × Type → Type with dimap.
530pub fn profunctor_ty() -> Expr {
531    arrow(type0(), fn_ty(type0(), type0()))
532}
533/// `StrongProfunctor : Type → Type → Type`
534///
535/// A strong profunctor: profunctor with first' and second' (for lens encoding).
536pub fn strong_profunctor_ty() -> Expr {
537    arrow(type0(), fn_ty(type0(), type0()))
538}
539/// `TambaraModule : Type → Type → Type`
540///
541/// A Tambara module: a profunctor with an action of monoidal categories,
542/// used as the categorical foundation for optics.
543pub fn tambara_module_ty() -> Expr {
544    arrow(type0(), fn_ty(type0(), type0()))
545}
546/// `ProfunctorOpticTy : Type → Type → Type → Type → Type`
547///
548/// Profunctor-encoded optic: ∀ P, P A B → P S T.
549/// Type: (S T A B : Type) → Type.
550pub fn profunctor_optic_ty() -> Expr {
551    pi(
552        BinderInfo::Default,
553        "S",
554        type0(),
555        pi(
556            BinderInfo::Default,
557            "T",
558            type0(),
559            pi(BinderInfo::Default, "A", type0(), arrow(type0(), type0())),
560        ),
561    )
562}
563/// `Dimap : ∀ (P : Type → Type → Type) (A B C D : Type), Prop`
564///
565/// The dimap law: functorial mapping in both contravariant and covariant positions.
566pub fn dimap_ty() -> Expr {
567    pi(
568        BinderInfo::Default,
569        "P",
570        fn_ty(type0(), fn_ty(type0(), type0())),
571        pi(
572            BinderInfo::Default,
573            "A",
574            type0(),
575            pi(
576                BinderInfo::Default,
577                "B",
578                type0(),
579                pi(BinderInfo::Default, "C", type0(), arrow(type0(), prop())),
580            ),
581        ),
582    )
583}
584/// `LensSetSet : ∀ (S A : Type), Lens S A → Prop`
585///
586/// SetSet law: set a' (set a s) = set a' s.
587pub fn lens_set_set_ty() -> Expr {
588    pi(
589        BinderInfo::Default,
590        "S",
591        type0(),
592        pi(
593            BinderInfo::Default,
594            "A",
595            type0(),
596            arrow(app2(cst("Lens"), bvar(1), bvar(0)), prop()),
597        ),
598    )
599}
600/// `VanLaarhovenLens : Type → Type → Type`
601///
602/// van Laarhoven encoding: ∀ (F : Type → Type), Functor F → (A → F A) → S → F S.
603pub fn van_laarhoven_lens_ty() -> Expr {
604    arrow(type0(), fn_ty(type0(), type0()))
605}
606/// `PrismLaw : ∀ (S A : Type), Prism S A → Prop`
607///
608/// Prism law: review (preview s) = s (when preview s = Some a, review a = s).
609pub fn prism_law_ty() -> Expr {
610    pi(
611        BinderInfo::Default,
612        "S",
613        type0(),
614        pi(
615            BinderInfo::Default,
616            "A",
617            type0(),
618            arrow(app2(cst("Prism"), bvar(1), bvar(0)), prop()),
619        ),
620    )
621}
622/// `TraversalCompose : ∀ (S A : Type), Traversal S A → Prop`
623///
624/// Traversal composition law (purity + fusion).
625pub fn traversal_compose_ty() -> Expr {
626    pi(
627        BinderInfo::Default,
628        "S",
629        type0(),
630        pi(
631            BinderInfo::Default,
632            "A",
633            type0(),
634            arrow(app2(cst("Traversal"), bvar(1), bvar(0)), prop()),
635        ),
636    )
637}
638/// `Comonad : (Type → Type) → Type`
639///
640/// A comonad W with extract : W A → A and extend : (W A → B) → W A → W B.
641pub fn comonad_ty() -> Expr {
642    arrow(fn_ty(type0(), type0()), type0())
643}
644/// `ComonadLaw : (Type → Type) → Type → Prop`
645///
646/// Comonad laws: extract . extend f = f, extend extract = id,
647/// extend f . extend g = extend (f . extend g).
648pub fn comonad_law_ty() -> Expr {
649    pi(
650        BinderInfo::Default,
651        "W",
652        fn_ty(type0(), type0()),
653        arrow(type0(), prop()),
654    )
655}
656/// `CellularAutomataComonad : Type → Type`
657///
658/// Comonad for 1D cellular automata: focused streams with neighborhood access.
659pub fn cellular_automata_comonad_ty() -> Expr {
660    arrow(type0(), type0())
661}
662/// `StreamComonad : Type → Type`
663///
664/// The stream comonad: infinite sequences with extract (head) and extend.
665pub fn stream_comonad_ty() -> Expr {
666    arrow(type0(), type0())
667}
668/// `CofreeComonadUnfold : ∀ (F : Type → Type) (A : Type), Prop`
669///
670/// Cofree comonad via terminal coalgebra: Nu (A × F -).
671pub fn cofree_comonad_unfold_ty() -> Expr {
672    pi(
673        BinderInfo::Default,
674        "F",
675        fn_ty(type0(), type0()),
676        arrow(type0(), prop()),
677    )
678}
679/// `Applicative : (Type → Type) → Type`
680///
681/// An applicative functor with pure and <*>.
682pub fn applicative_ty() -> Expr {
683    arrow(fn_ty(type0(), type0()), type0())
684}
685/// `ApplicativeLaw : (Type → Type) → Type → Prop`
686///
687/// Applicative laws: identity, composition, homomorphism, interchange.
688pub fn applicative_law_ty() -> Expr {
689    pi(
690        BinderInfo::Default,
691        "F",
692        fn_ty(type0(), type0()),
693        arrow(type0(), prop()),
694    )
695}
696/// `DayConvolution : (Type → Type) → (Type → Type) → Type → Type`
697///
698/// Day convolution of two functors: (Day F G) A = ∃ X Y, F X × G Y × (X × Y → A).
699pub fn day_convolution_ty() -> Expr {
700    arrow(
701        fn_ty(type0(), type0()),
702        arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0())),
703    )
704}
705/// `IdiomBracket : (Type → Type) → Type → Type`
706///
707/// Idiom bracket notation for applicative expressions: [| f x y |].
708pub fn idiom_bracket_ty() -> Expr {
709    arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
710}
711/// `ArrowChoice : Type → Type → Type`
712///
713/// ArrowChoice: arrows with (+++) and left/right for sum types.
714pub fn arrow_choice_ty() -> Expr {
715    arrow(type0(), fn_ty(type0(), type0()))
716}
717/// `ArrowApply : Type → Type → Type`
718///
719/// ArrowApply (ArrowMonad): arrows that support application (app :: arr (arr a b, a) b).
720pub fn arrow_apply_ty() -> Expr {
721    arrow(type0(), fn_ty(type0(), type0()))
722}
723/// `ArrowLaw : Type → Type → Prop`
724///
725/// Hughes arrow laws: arr id = id, arr (f . g) = arr f >>> arr g, etc.
726pub fn arrow_law_ty() -> Expr {
727    arrow(type0(), fn_ty(type0(), prop()))
728}
729/// `ArrowFirst : Type → Type → Type → Type`
730///
731/// The `first` combinator for arrows: first f = f *** id.
732pub fn arrow_first_ty() -> Expr {
733    arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
734}
735/// `InitialAlgebra : (Type → Type) → Type → Prop`
736///
737/// Lambek's lemma: the initial algebra of F is a fixed point F(Mu F) ≅ Mu F.
738pub fn initial_algebra_ty() -> Expr {
739    pi(
740        BinderInfo::Default,
741        "F",
742        fn_ty(type0(), type0()),
743        arrow(type0(), prop()),
744    )
745}
746/// `FinalCoalgebra : (Type → Type) → Type → Prop`
747///
748/// The final coalgebra: Nu F is a fixed point with Nu F ≅ F(Nu F).
749pub fn final_coalgebra_ty() -> Expr {
750    pi(
751        BinderInfo::Default,
752        "F",
753        fn_ty(type0(), type0()),
754        arrow(type0(), prop()),
755    )
756}
757/// `BanachFixedPoint : Type → Type → Prop`
758///
759/// Banach's theorem in cpo: any contractive map has a unique fixed point.
760pub fn banach_fixed_point_ty() -> Expr {
761    arrow(type0(), fn_ty(type0(), prop()))
762}
763/// `FixpointType : (Type → Type) → Type`
764///
765/// The generic fixpoint type (equi-recursive types) for both Mu and Nu.
766pub fn fixpoint_type_ty() -> Expr {
767    arrow(fn_ty(type0(), type0()), type0())
768}
769/// `ContT : Type → (Type → Type) → Type → Type`
770///
771/// Continuation monad transformer: ContT r m a = (a → m r) → m r.
772pub fn cont_t_ty() -> Expr {
773    arrow(
774        type0(),
775        arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0())),
776    )
777}
778/// `Shift : Type → Type → Type`
779///
780/// Delimited continuation shift operator: (a → m b) → m a.
781pub fn shift_ty() -> Expr {
782    arrow(type0(), fn_ty(type0(), type0()))
783}
784/// `Reset : Type → Type → Type`
785///
786/// Delimited continuation reset (prompt): delimits the scope of a continuation.
787pub fn reset_ty() -> Expr {
788    arrow(type0(), fn_ty(type0(), type0()))
789}
790/// `CpsTransform : Type → Type → Type`
791///
792/// CPS transform: A → ((A → R) → R).
793pub fn cps_transform_ty() -> Expr {
794    arrow(type0(), fn_ty(type0(), type0()))
795}
796/// `DoubleNegationTranslation : Type → Prop`
797///
798/// Gödel-Gentzen: P is provable classically iff ¬¬P is provable constructively.
799pub fn double_negation_translation_ty() -> Expr {
800    arrow(type0(), prop())
801}
802/// `UniqueType : Type → Type`
803///
804/// A uniqueness type annotation (Clean language): value with guaranteed unique reference.
805pub fn unique_type_ty() -> Expr {
806    arrow(type0(), type0())
807}
808/// `LinearType : Type → Type`
809///
810/// A linear type: must be used exactly once (related to uniqueness types).
811pub fn linear_type_ty() -> Expr {
812    arrow(type0(), type0())
813}
814/// `UniquenessLaw : Type → Prop`
815///
816/// Uniqueness property: a unique value cannot be shared or copied.
817pub fn uniqueness_law_ty() -> Expr {
818    arrow(type0(), prop())
819}
820/// `LinearityLaw : Type → Prop`
821///
822/// Linearity property: a linear resource is consumed exactly once.
823pub fn linearity_law_ty() -> Expr {
824    arrow(type0(), prop())
825}
826/// Build the functional programming foundations environment: register all axioms.
827pub fn build_env(env: &mut Environment) {
828    let axioms: &[(&str, Expr)] = &[
829        ("FreeMonad", free_monad_ty()),
830        ("Cofree", cofree_ty()),
831        ("FixPoint", fixpoint_ty()),
832        ("Mu", mu_ty()),
833        ("Nu", nu_ty()),
834        ("cata", cata_ty()),
835        ("ana", ana_ty()),
836        ("hylo", hylo_ty()),
837        ("Catamorphism", catamorphism_ty()),
838        ("Paramorphism", paramorphism_ty()),
839        ("Histomorphism", histomorphism_ty()),
840        ("Futumorphism", futumorphism_ty()),
841        ("Hylomorphism", hylomorphism_ty()),
842        ("Chronomorphism", chronomorphism_ty()),
843        ("Lens", lens_ty()),
844        ("Prism", prism_ty()),
845        ("Traversal", traversal_ty()),
846        ("Iso", iso_ty()),
847        ("AffineTraversal", affine_traversal_ty()),
848        ("Effect", effect_ty()),
849        ("EffectHandler", effect_handler_ty()),
850        ("AlgebraicEffect", algebraic_effect_ty()),
851        ("FreeSelective", free_selective_ty()),
852        ("Arrow", arrow_ty()),
853        ("HList", hlist_ty()),
854        ("HMap", hmap_ty()),
855        ("Singleton", singleton_ty()),
856        ("TypeEquality", type_equality_ty()),
857        ("Coerce", coerce_ty()),
858        ("free_monad_left_unit", free_monad_left_unit_ty()),
859        ("free_monad_right_unit", free_monad_right_unit_ty()),
860        ("lens_get_set", lens_get_set_ty()),
861        ("lens_set_get", lens_set_get_ty()),
862        ("iso_roundtrip", iso_roundtrip_ty()),
863        ("catamorphism_fusion", catamorphism_fusion_ty()),
864        ("hylo_fusion", hylo_fusion_ty()),
865        ("ScottDomain", scott_domain_ty()),
866        ("ScottContinuous", scott_continuous_ty()),
867        ("FixedPointSemantics", fixed_point_semantics_ty()),
868        ("FullAbstraction", full_abstraction_ty()),
869        ("LeastUpperBound", least_upper_bound_ty()),
870        ("ApproximationOrder", approximation_order_ty()),
871        ("EffectRow", effect_row_ty()),
872        ("ScopedEffect", scoped_effect_ty()),
873        ("DeepHandler", deep_handler_ty()),
874        ("ShallowHandler", shallow_handler_ty()),
875        ("EffectSubrow", effect_subrow_ty()),
876        ("FreerMonad", freer_monad_ty()),
877        ("FreeApplicative", free_applicative_ty()),
878        ("free_monad_bind", free_monad_bind_ty()),
879        ("freer_lift", freer_lift_ty()),
880        ("Profunctor", profunctor_ty()),
881        ("StrongProfunctor", strong_profunctor_ty()),
882        ("TambaraModule", tambara_module_ty()),
883        ("ProfunctorOptic", profunctor_optic_ty()),
884        ("dimap", dimap_ty()),
885        ("lens_set_set", lens_set_set_ty()),
886        ("VanLaarhovenLens", van_laarhoven_lens_ty()),
887        ("prism_law", prism_law_ty()),
888        ("traversal_compose", traversal_compose_ty()),
889        ("Comonad", comonad_ty()),
890        ("comonad_law", comonad_law_ty()),
891        ("CellularAutomataComonad", cellular_automata_comonad_ty()),
892        ("StreamComonad", stream_comonad_ty()),
893        ("cofree_comonad_unfold", cofree_comonad_unfold_ty()),
894        ("Applicative", applicative_ty()),
895        ("applicative_law", applicative_law_ty()),
896        ("DayConvolution", day_convolution_ty()),
897        ("IdiomBracket", idiom_bracket_ty()),
898        ("ArrowChoice", arrow_choice_ty()),
899        ("ArrowApply", arrow_apply_ty()),
900        ("arrow_law", arrow_law_ty()),
901        ("ArrowFirst", arrow_first_ty()),
902        ("initial_algebra", initial_algebra_ty()),
903        ("final_coalgebra", final_coalgebra_ty()),
904        ("BanachFixedPoint", banach_fixed_point_ty()),
905        ("FixpointType", fixpoint_type_ty()),
906        ("ContT", cont_t_ty()),
907        ("Shift", shift_ty()),
908        ("Reset", reset_ty()),
909        ("CpsTransform", cps_transform_ty()),
910        (
911            "double_negation_translation",
912            double_negation_translation_ty(),
913        ),
914        ("UniqueType", unique_type_ty()),
915        ("LinearType", linear_type_ty()),
916        ("uniqueness_law", uniqueness_law_ty()),
917        ("linearity_law", linearity_law_ty()),
918    ];
919    for (name, ty) in axioms {
920        env.add(Declaration::Axiom {
921            name: Name::str(*name),
922            univ_params: vec![],
923            ty: ty.clone(),
924        })
925        .ok();
926    }
927}
928#[cfg(test)]
929mod tests {
930    use super::*;
931    #[test]
932    fn test_free_monad_pure() {
933        let m: FreeMonad<i32> = FreeMonad::pure(42);
934        let result = m.fold(|a| a * 2, |_| 0);
935        assert_eq!(result, 84);
936    }
937    #[test]
938    fn test_list_cata_sum() {
939        let sum = list_cata(
940            |opt| match opt {
941                None => 0,
942                Some((a, acc)) => a + acc,
943            },
944            vec![1, 2, 3, 4, 5],
945        );
946        assert_eq!(sum, 15);
947    }
948    #[test]
949    fn test_list_ana_range() {
950        let list = list_ana(|n: usize| if n < 5 { Some((n, n + 1)) } else { None }, 0);
951        assert_eq!(list, vec![0, 1, 2, 3, 4]);
952    }
953    #[test]
954    fn test_list_hylo_factorial() {
955        let alg: &dyn Fn(Option<(u64, u64)>) -> u64 = &|opt| match opt {
956            None => 1,
957            Some((a, acc)) => a * acc,
958        };
959        let coalg: &dyn Fn(u64) -> Option<(u64, u64)> = &|n| {
960            if n == 0 {
961                None
962            } else {
963                Some((n, n - 1))
964            }
965        };
966        let fact5 = list_hylo(alg, coalg, 5u64);
967        assert_eq!(fact5, 120);
968    }
969    #[test]
970    fn test_list_para_reverse_list() {
971        let result = list_para(
972            |opt: Option<(i32, Vec<i32>, usize)>| match opt {
973                None => 0,
974                Some((_, tail, _)) => tail.len() + 1,
975            },
976            vec![1, 2, 3],
977        );
978        assert_eq!(result, 3);
979    }
980    #[test]
981    fn test_lens_view_set() {
982        let lens: Lens<(i32, i32), i32> = Lens::new(|(a, _)| *a, |v, (_, b)| (v, b));
983        let pair = (10, 20);
984        assert_eq!(lens.view(&pair), 10);
985        let pair2 = lens.set(99, pair);
986        assert_eq!(pair2, (99, 20));
987    }
988    #[test]
989    fn test_lens_over() {
990        let lens: Lens<(i32, i32), i32> = Lens::new(|(a, _)| *a, |v, (_, b)| (v, b));
991        let pair = (5, 7);
992        let pair2 = lens.over(|a| a * 2, pair);
993        assert_eq!(pair2, (10, 7));
994    }
995    #[test]
996    fn test_prism_some() {
997        let prism: Prism<Option<i32>, i32> = Prism::new(|s| s, |a| Some(a));
998        assert_eq!(prism.preview(Some(42)), Some(42));
999        assert_eq!(prism.preview(None), None);
1000        assert_eq!(prism.review(7), Some(7));
1001    }
1002    #[test]
1003    fn test_iso_swap() {
1004        let iso: Iso<(i32, i32), (i32, i32)> = Iso::new(|(a, b)| (b, a), |(b, a)| (a, b));
1005        assert_eq!(iso.view((1, 2)), (2, 1));
1006        assert_eq!(iso.review((2, 1)), (1, 2));
1007    }
1008    #[test]
1009    fn test_traversal_over() {
1010        let trav: Traversal<Vec<i32>, i32> =
1011            Traversal::new(|v: &Vec<i32>| v.clone(), |vals, _| vals);
1012        let v = vec![1, 2, 3];
1013        let v2 = trav.over(|x| x * 10, v);
1014        assert_eq!(v2, vec![10, 20, 30]);
1015    }
1016    #[test]
1017    fn test_hlist_len() {
1018        let list = HList::cons(42i32, HList::cons("hello", HList::nil()));
1019        assert_eq!(list.len(), 2);
1020    }
1021    #[test]
1022    fn test_hlist_empty() {
1023        let list = HList::nil();
1024        assert!(list.is_empty());
1025    }
1026    #[test]
1027    fn test_hmap_insert_get() {
1028        let mut map = HMap::new();
1029        map.insert("x", 42i32);
1030        map.insert("name", "OxiLean");
1031        assert_eq!(map.get::<i32>("x"), Some(&42));
1032        assert_eq!(map.get::<&str>("name"), Some(&"OxiLean"));
1033        assert_eq!(map.len(), 2);
1034    }
1035    #[test]
1036    fn test_singleton() {
1037        let s = Singleton::new(2.72f64);
1038        assert!((s.extract() - 2.72).abs() < 1e-15);
1039    }
1040    #[test]
1041    fn test_type_equality_refl() {
1042        let _eq: TypeEquality<i32, i32> = TypeEquality::refl();
1043    }
1044    #[test]
1045    fn test_arrow_compose() {
1046        let double = Arrow::arr(|x: i32| x * 2);
1047        let add_one = Arrow::arr(|x: i32| x + 1);
1048        let composed = double.compose(add_one);
1049        assert_eq!(composed.apply(5), 11);
1050    }
1051    #[test]
1052    fn test_build_env() {
1053        use oxilean_kernel::Environment;
1054        let mut env = Environment::new();
1055        build_env(&mut env);
1056        assert!(env.get(&Name::str("FreeMonad")).is_some());
1057        assert!(env.get(&Name::str("Lens")).is_some());
1058        assert!(env.get(&Name::str("HList")).is_some());
1059        assert!(env.get(&Name::str("Effect")).is_some());
1060        assert!(env.get(&Name::str("Mu")).is_some());
1061        assert!(env.get(&Name::str("ScottDomain")).is_some());
1062        assert!(env.get(&Name::str("EffectRow")).is_some());
1063        assert!(env.get(&Name::str("FreerMonad")).is_some());
1064        assert!(env.get(&Name::str("Profunctor")).is_some());
1065        assert!(env.get(&Name::str("Comonad")).is_some());
1066        assert!(env.get(&Name::str("Applicative")).is_some());
1067        assert!(env.get(&Name::str("ArrowChoice")).is_some());
1068        assert!(env.get(&Name::str("ContT")).is_some());
1069        assert!(env.get(&Name::str("UniqueType")).is_some());
1070    }
1071    #[test]
1072    fn test_recursion_scheme_cata_sum() {
1073        let tree = RoseTree::Node(
1074            1usize,
1075            vec![RoseTree::Node(2, vec![]), RoseTree::Node(3, vec![])],
1076        );
1077        let sum = RecursionSchemeEval::cata(tree, &|v: usize, children: Vec<usize>| {
1078            v + children.iter().sum::<usize>()
1079        });
1080        assert_eq!(sum, 6);
1081    }
1082    #[test]
1083    fn test_recursion_scheme_ana_binary_node_count() {
1084        let tree = RecursionSchemeEval::ana(2usize, &|d: usize| {
1085            if d == 0 {
1086                (d, vec![])
1087            } else {
1088                (d, vec![d - 1, d - 1])
1089            }
1090        });
1091        let node_count = RecursionSchemeEval::cata(tree, &|_: usize, children: Vec<usize>| {
1092            1 + children.iter().sum::<usize>()
1093        });
1094        assert_eq!(node_count, 7);
1095    }
1096    #[test]
1097    fn test_recursion_scheme_hylo_path_sum() {
1098        let result = RecursionSchemeEval::hylo(
1099            3usize,
1100            &|d: usize| {
1101                if d == 0 {
1102                    (d, vec![])
1103                } else {
1104                    (d, vec![d - 1])
1105                }
1106            },
1107            &|v: usize, children: Vec<usize>| v + children.iter().sum::<usize>(),
1108        );
1109        assert_eq!(result, 6);
1110    }
1111    #[test]
1112    fn test_lens_composer_get_set_law() {
1113        let lens: Lens<(i32, i32), i32> = Lens::new(|(a, _)| *a, |v, (_, b)| (v, b));
1114        assert!(LensComposer::check_get_set(&lens, (42, 7)));
1115    }
1116    #[test]
1117    fn test_lens_composer_set_get_law() {
1118        let lens: Lens<(i32, i32), i32> = Lens::new(|(a, _)| *a, |v, (_, b)| (v, b));
1119        assert!(LensComposer::check_set_get(&lens, 99, (1, 2)));
1120    }
1121    #[test]
1122    fn test_lens_composer_set_set_law() {
1123        let lens: Lens<(i32, i32), i32> = Lens::new(|(a, _)| *a, |v, (_, b)| (v, b));
1124        assert!(LensComposer::check_set_set(&lens, 10, 20, (1, 2)));
1125    }
1126    #[test]
1127    fn test_lens_composer_compose() {
1128        let outer: Lens<((i32, i32), i32), (i32, i32)> =
1129            Lens::new(|(pair, _)| *pair, |v, (_, b)| (v, b));
1130        let inner: Lens<(i32, i32), i32> = Lens::new(|(a, _)| *a, |v, (_, b)| (v, b));
1131        let composed = LensComposer::compose(outer, inner);
1132        let s = ((10, 20), 30);
1133        assert_eq!(composed(&s), 10);
1134    }
1135    #[test]
1136    fn test_free_monad_interpreter_print() {
1137        let prog = ConsoleProg::Step(
1138            ConsoleEffect::Print("hello".to_string()),
1139            Box::new(|_| ConsoleProg::Done(42i32)),
1140        );
1141        let mut output: Vec<String> = Vec::new();
1142        let result = FreeMonadInterpreter::run(
1143            prog,
1144            &mut |msg: &str| output.push(msg.to_string()),
1145            &mut || String::new(),
1146        );
1147        assert_eq!(result, 42);
1148        assert_eq!(output, vec!["hello"]);
1149    }
1150    #[test]
1151    fn test_free_monad_interpreter_read() {
1152        let prog = ConsoleProg::Step(
1153            ConsoleEffect::Read,
1154            Box::new(|line: String| ConsoleProg::Done(line.len())),
1155        );
1156        let result = FreeMonadInterpreter::run(prog, &mut |_| {}, &mut || "world".to_string());
1157        assert_eq!(result, 5);
1158    }
1159    #[test]
1160    fn test_profunctor_optic_lens() {
1161        let optic: ProfunctorOptic<(i32, i32), (i32, i32), i32, i32> =
1162            ProfunctorOptic::lens_optic(|(a, _): &(i32, i32)| *a, |v, (_, b): (i32, i32)| (v, b));
1163        let transform = optic.apply(|x| x * 10);
1164        let result = transform((3, 7));
1165        assert_eq!(result, (30, 7));
1166    }
1167    #[test]
1168    fn test_profunctor_optic_prism_some() {
1169        let optic: ProfunctorOptic<Option<i32>, Option<i32>, i32, i32> =
1170            ProfunctorOptic::prism_optic(|s: Option<i32>| s.ok_or(None), |b: i32| Some(b));
1171        let transform = optic.apply(|x| x + 1);
1172        assert_eq!(transform(Some(41)), Some(42));
1173    }
1174    #[test]
1175    fn test_profunctor_optic_prism_none() {
1176        let optic: ProfunctorOptic<Option<i32>, Option<i32>, i32, i32> =
1177            ProfunctorOptic::prism_optic(|s: Option<i32>| s.ok_or(None), |b: i32| Some(b));
1178        let transform = optic.apply(|x| x + 1);
1179        assert_eq!(transform(None), None);
1180    }
1181    #[test]
1182    fn test_zipper_extract() {
1183        let z = Zipper::new(vec![1, 2, 3, 4, 5], 2).expect("Zipper::new should succeed");
1184        assert_eq!(*z.extract(), 3);
1185    }
1186    #[test]
1187    fn test_zipper_move_left_right() {
1188        let z = Zipper::new(vec![10, 20, 30], 1).expect("Zipper::new should succeed");
1189        let z_left = z.move_left().expect("move_left should succeed");
1190        assert_eq!(*z_left.extract(), 10);
1191        let z_right = z.move_right().expect("move_right should succeed");
1192        assert_eq!(*z_right.extract(), 30);
1193    }
1194    #[test]
1195    fn test_zipper_to_vec() {
1196        let z = Zipper::new(vec![1, 2, 3], 0).expect("Zipper::new should succeed");
1197        assert_eq!(z.to_vec(), vec![1, 2, 3]);
1198    }
1199    #[test]
1200    fn test_comonad_extend_sum_neighbors() {
1201        let z = Zipper::new(vec![1i32, 2, 3, 4, 5], 2).expect("Zipper::new should succeed");
1202        let extended = ComonadExtend::extend(&z, |sub_z| {
1203            let left_val: i32 = sub_z.left.last().copied().unwrap_or(0);
1204            let right_val: i32 = sub_z.right.first().copied().unwrap_or(0);
1205            left_val + *sub_z.extract() + right_val
1206        });
1207        assert_eq!(extended.to_vec(), vec![3, 6, 9, 12, 9]);
1208        assert_eq!(*extended.extract(), 9);
1209    }
1210    #[test]
1211    fn test_comonad_duplicate_len() {
1212        let z = Zipper::new(vec![10, 20, 30], 1).expect("Zipper::new should succeed");
1213        let dup = ComonadExtend::duplicate(&z);
1214        assert_eq!(dup.len(), 3);
1215        assert_eq!(dup.extract().to_vec(), vec![10, 20, 30]);
1216    }
1217    #[test]
1218    fn test_new_axioms_registered() {
1219        use oxilean_kernel::Environment;
1220        let mut env = Environment::new();
1221        build_env(&mut env);
1222        assert!(env.get(&Name::str("FullAbstraction")).is_some());
1223        assert!(env.get(&Name::str("ApproximationOrder")).is_some());
1224        assert!(env.get(&Name::str("FixedPointSemantics")).is_some());
1225        assert!(env.get(&Name::str("DeepHandler")).is_some());
1226        assert!(env.get(&Name::str("ShallowHandler")).is_some());
1227        assert!(env.get(&Name::str("EffectSubrow")).is_some());
1228        assert!(env.get(&Name::str("FreeApplicative")).is_some());
1229        assert!(env.get(&Name::str("freer_lift")).is_some());
1230        assert!(env.get(&Name::str("free_monad_bind")).is_some());
1231        assert!(env.get(&Name::str("TambaraModule")).is_some());
1232        assert!(env.get(&Name::str("dimap")).is_some());
1233        assert!(env.get(&Name::str("StrongProfunctor")).is_some());
1234        assert!(env.get(&Name::str("VanLaarhovenLens")).is_some());
1235        assert!(env.get(&Name::str("lens_set_set")).is_some());
1236        assert!(env.get(&Name::str("prism_law")).is_some());
1237        assert!(env.get(&Name::str("traversal_compose")).is_some());
1238        assert!(env.get(&Name::str("StreamComonad")).is_some());
1239        assert!(env.get(&Name::str("CellularAutomataComonad")).is_some());
1240        assert!(env.get(&Name::str("cofree_comonad_unfold")).is_some());
1241        assert!(env.get(&Name::str("DayConvolution")).is_some());
1242        assert!(env.get(&Name::str("IdiomBracket")).is_some());
1243        assert!(env.get(&Name::str("applicative_law")).is_some());
1244        assert!(env.get(&Name::str("ArrowApply")).is_some());
1245        assert!(env.get(&Name::str("ArrowFirst")).is_some());
1246        assert!(env.get(&Name::str("arrow_law")).is_some());
1247        assert!(env.get(&Name::str("initial_algebra")).is_some());
1248        assert!(env.get(&Name::str("BanachFixedPoint")).is_some());
1249        assert!(env.get(&Name::str("FixpointType")).is_some());
1250        assert!(env.get(&Name::str("final_coalgebra")).is_some());
1251        assert!(env.get(&Name::str("Shift")).is_some());
1252        assert!(env.get(&Name::str("Reset")).is_some());
1253        assert!(env.get(&Name::str("CpsTransform")).is_some());
1254        assert!(env.get(&Name::str("double_negation_translation")).is_some());
1255        assert!(env.get(&Name::str("LinearType")).is_some());
1256        assert!(env.get(&Name::str("linearity_law")).is_some());
1257        assert!(env.get(&Name::str("uniqueness_law")).is_some());
1258    }
1259}
1260#[cfg(test)]
1261mod extended_fp_tests {
1262    use super::*;
1263    #[test]
1264    fn test_free_monad() {
1265        let fm = FreeMonadInfo::over("F", vec!["op1", "op2", "op3"]);
1266        assert_eq!(fm.num_operations(), 3);
1267        assert!(fm.interpreter_description().contains("foldFree"));
1268    }
1269    #[test]
1270    fn test_cps() {
1271        let cps = CpsTransform::new("Int", "R");
1272        assert!(cps.transform_description().contains("CPS[Int]"));
1273    }
1274    #[test]
1275    fn test_effect_system() {
1276        let st = EffectSystem::state("Int");
1277        assert_eq!(st.num_ops(), 2);
1278        let exc = EffectSystem::exception("Error");
1279        assert_eq!(exc.num_ops(), 1);
1280    }
1281    #[test]
1282    fn test_defunctionalized_closure() {
1283        let cl = DefunctClosure::new("Adder", vec![("n", "Int")], "n + x");
1284        assert_eq!(cl.arity(), 1);
1285        assert!(cl.apply_description().contains("apply(Adder)"));
1286    }
1287    #[test]
1288    fn test_type_constructor_functor() {
1289        let list = TypeConstructorFunctor::list();
1290        assert_eq!(list.num_laws(), 2);
1291        assert!(list.fmap_type.contains("List a -> List b"));
1292    }
1293}
1294#[cfg(test)]
1295mod tests_fp_ext {
1296    use super::*;
1297    #[test]
1298    fn test_applicative() {
1299        let maybe = ApplicativeData::maybe_applicative();
1300        assert!(maybe.is_monad);
1301        let laws = maybe.laws();
1302        assert_eq!(laws.len(), 4);
1303        assert!(laws[0].contains("Identity"));
1304        let paper = maybe.mcbride_paterson_paper();
1305        assert!(paper.contains("McBride"));
1306        let val = ApplicativeData::validation_applicative();
1307        assert!(!val.is_monad);
1308    }
1309    #[test]
1310    fn test_traversable() {
1311        let list_trav = TraversableData::list_traversable();
1312        assert!(list_trav.is_foldable);
1313        let laws = list_trav.laws();
1314        assert!(laws.len() >= 3);
1315        let acc = list_trav.efficient_mapaccum();
1316        assert!(acc.contains("O(n)"));
1317    }
1318    #[test]
1319    fn test_arrow_data() {
1320        let arr = ArrowData::function_arrow();
1321        assert!(arr.is_arrowchoice && arr.is_arrowloop);
1322        let laws = arr.hughes_laws();
1323        assert_eq!(laws.len(), 4);
1324        let freyd = arr.freyd_category_connection();
1325        assert!(freyd.contains("Freyd"));
1326        let kleisli = ArrowData::kleisli_arrow("Maybe");
1327        assert!(!kleisli.is_arrowloop);
1328    }
1329    #[test]
1330    fn test_profunctor() {
1331        let fp = ProfunctorData::function_profunctor();
1332        assert!(fp.is_cartesian && fp.is_closed);
1333        let optic = fp.optic_encoding();
1334        assert!(optic.contains("Profunctor optics"));
1335        let tambara = fp.tambara_module_connection();
1336        assert!(tambara.contains("Tambara"));
1337        let star = ProfunctorData::star_profunctor("Maybe");
1338        assert!(!star.is_closed);
1339    }
1340    #[test]
1341    fn test_dependent_type() {
1342        let vec5 = DependentTypeExample::fixed_length_vector("Int", 5);
1343        let safety = vec5.type_safety_guarantee();
1344        assert!(safety.contains("length is exactly 5"));
1345        let fin = DependentTypeExample::fin_type(10);
1346        assert!(fin.type_name.contains("Fin 10"));
1347    }
1348    #[test]
1349    fn test_homotopy_equivalence() {
1350        let heq = HomotopyEquivalence::new("A", "B", "f", "g").univalent_equivalence();
1351        assert!(heq.is_univalent);
1352        let ua = heq.univalence_axiom();
1353        assert!(ua.contains("Voevodsky"));
1354        let cond = heq.contractibility_condition();
1355        assert!(cond.contains("≃"));
1356    }
1357}