1use 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}
47pub fn free_monad_ty() -> Expr {
51 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
52}
53pub fn cofree_ty() -> Expr {
57 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
58}
59pub fn fixpoint_ty() -> Expr {
63 arrow(fn_ty(type0(), type0()), type0())
64}
65pub fn mu_ty() -> Expr {
69 arrow(fn_ty(type0(), type0()), type0())
70}
71pub fn nu_ty() -> Expr {
75 arrow(fn_ty(type0(), type0()), type0())
76}
77pub 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}
96pub 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}
113pub 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}
138pub fn catamorphism_ty() -> Expr {
142 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
143}
144pub fn paramorphism_ty() -> Expr {
148 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
149}
150pub fn histomorphism_ty() -> Expr {
154 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
155}
156pub fn futumorphism_ty() -> Expr {
160 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
161}
162pub fn hylomorphism_ty() -> Expr {
166 arrow(
167 fn_ty(type0(), type0()),
168 arrow(type0(), fn_ty(type0(), type0())),
169 )
170}
171pub fn chronomorphism_ty() -> Expr {
175 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
176}
177pub fn lens_ty() -> Expr {
181 arrow(type0(), fn_ty(type0(), type0()))
182}
183pub fn prism_ty() -> Expr {
187 arrow(type0(), fn_ty(type0(), type0()))
188}
189pub fn traversal_ty() -> Expr {
193 arrow(type0(), fn_ty(type0(), type0()))
194}
195pub fn iso_ty() -> Expr {
199 arrow(type0(), fn_ty(type0(), type0()))
200}
201pub fn affine_traversal_ty() -> Expr {
205 arrow(type0(), fn_ty(type0(), type0()))
206}
207pub fn effect_ty() -> Expr {
211 arrow(type0(), fn_ty(type0(), type0()))
212}
213pub fn effect_handler_ty() -> Expr {
217 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
218}
219pub fn algebraic_effect_ty() -> Expr {
223 arrow(type0(), fn_ty(type0(), type0()))
224}
225pub fn free_selective_ty() -> Expr {
229 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
230}
231pub fn arrow_ty() -> Expr {
235 arrow(type0(), fn_ty(type0(), type0()))
236}
237pub fn hlist_ty() -> Expr {
241 type0()
242}
243pub fn hmap_ty() -> Expr {
247 arrow(type0(), fn_ty(type0(), type0()))
248}
249pub fn singleton_ty() -> Expr {
253 arrow(type0(), type0())
254}
255pub fn type_equality_ty() -> Expr {
259 arrow(type0(), fn_ty(type0(), prop()))
260}
261pub fn coerce_ty() -> Expr {
265 arrow(type0(), fn_ty(type0(), prop()))
266}
267pub 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}
278pub 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}
289pub 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}
305pub 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}
321pub 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}
337pub 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}
348pub 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}
359pub 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}
367pub 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}
382pub 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}
396pub 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}
410pub fn scott_domain_ty() -> Expr {
415 type0()
416}
417pub fn scott_continuous_ty() -> Expr {
421 arrow(type0(), fn_ty(type0(), prop()))
422}
423pub fn fixed_point_semantics_ty() -> Expr {
428 pi(
429 BinderInfo::Default,
430 "F",
431 fn_ty(type0(), type0()),
432 arrow(type0(), prop()),
433 )
434}
435pub fn full_abstraction_ty() -> Expr {
439 arrow(type0(), fn_ty(type0(), prop()))
440}
441pub fn least_upper_bound_ty() -> Expr {
445 arrow(type0(), fn_ty(type0(), prop()))
446}
447pub fn approximation_order_ty() -> Expr {
451 arrow(type0(), fn_ty(type0(), prop()))
452}
453pub fn effect_row_ty() -> Expr {
458 type0()
459}
460pub fn scoped_effect_ty() -> Expr {
464 arrow(type0(), fn_ty(type0(), type0()))
465}
466pub fn deep_handler_ty() -> Expr {
471 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
472}
473pub fn shallow_handler_ty() -> Expr {
477 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
478}
479pub fn effect_subrow_ty() -> Expr {
483 arrow(type0(), fn_ty(type0(), prop()))
484}
485pub fn freer_monad_ty() -> Expr {
490 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
491}
492pub fn free_applicative_ty() -> Expr {
496 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
497}
498pub 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}
509pub 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}
528pub fn profunctor_ty() -> Expr {
532 arrow(type0(), fn_ty(type0(), type0()))
533}
534pub fn strong_profunctor_ty() -> Expr {
538 arrow(type0(), fn_ty(type0(), type0()))
539}
540pub fn tambara_module_ty() -> Expr {
545 arrow(type0(), fn_ty(type0(), type0()))
546}
547pub 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}
564pub 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}
585pub 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}
601pub fn van_laarhoven_lens_ty() -> Expr {
605 arrow(type0(), fn_ty(type0(), type0()))
606}
607pub 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}
623pub 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}
639pub fn comonad_ty() -> Expr {
643 arrow(fn_ty(type0(), type0()), type0())
644}
645pub fn comonad_law_ty() -> Expr {
650 pi(
651 BinderInfo::Default,
652 "W",
653 fn_ty(type0(), type0()),
654 arrow(type0(), prop()),
655 )
656}
657pub fn cellular_automata_comonad_ty() -> Expr {
661 arrow(type0(), type0())
662}
663pub fn stream_comonad_ty() -> Expr {
667 arrow(type0(), type0())
668}
669pub fn cofree_comonad_unfold_ty() -> Expr {
673 pi(
674 BinderInfo::Default,
675 "F",
676 fn_ty(type0(), type0()),
677 arrow(type0(), prop()),
678 )
679}
680pub fn applicative_ty() -> Expr {
684 arrow(fn_ty(type0(), type0()), type0())
685}
686pub fn applicative_law_ty() -> Expr {
690 pi(
691 BinderInfo::Default,
692 "F",
693 fn_ty(type0(), type0()),
694 arrow(type0(), prop()),
695 )
696}
697pub fn day_convolution_ty() -> Expr {
701 arrow(
702 fn_ty(type0(), type0()),
703 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0())),
704 )
705}
706pub fn idiom_bracket_ty() -> Expr {
710 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
711}
712pub fn arrow_choice_ty() -> Expr {
716 arrow(type0(), fn_ty(type0(), type0()))
717}
718pub fn arrow_apply_ty() -> Expr {
722 arrow(type0(), fn_ty(type0(), type0()))
723}
724pub fn arrow_law_ty() -> Expr {
728 arrow(type0(), fn_ty(type0(), prop()))
729}
730pub fn arrow_first_ty() -> Expr {
734 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
735}
736pub fn initial_algebra_ty() -> Expr {
740 pi(
741 BinderInfo::Default,
742 "F",
743 fn_ty(type0(), type0()),
744 arrow(type0(), prop()),
745 )
746}
747pub fn final_coalgebra_ty() -> Expr {
751 pi(
752 BinderInfo::Default,
753 "F",
754 fn_ty(type0(), type0()),
755 arrow(type0(), prop()),
756 )
757}
758pub fn banach_fixed_point_ty() -> Expr {
762 arrow(type0(), fn_ty(type0(), prop()))
763}
764pub fn fixpoint_type_ty() -> Expr {
768 arrow(fn_ty(type0(), type0()), type0())
769}
770pub fn cont_t_ty() -> Expr {
774 arrow(
775 type0(),
776 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0())),
777 )
778}
779pub fn shift_ty() -> Expr {
783 arrow(type0(), fn_ty(type0(), type0()))
784}
785pub fn reset_ty() -> Expr {
789 arrow(type0(), fn_ty(type0(), type0()))
790}
791pub fn cps_transform_ty() -> Expr {
795 arrow(type0(), fn_ty(type0(), type0()))
796}
797pub fn double_negation_translation_ty() -> Expr {
801 arrow(type0(), prop())
802}
803pub fn unique_type_ty() -> Expr {
807 arrow(type0(), type0())
808}
809pub fn linear_type_ty() -> Expr {
813 arrow(type0(), type0())
814}
815pub fn uniqueness_law_ty() -> Expr {
819 arrow(type0(), prop())
820}
821pub fn linearity_law_ty() -> Expr {
825 arrow(type0(), prop())
826}
827pub 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}