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