1use 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}
46pub fn free_monad_ty() -> Expr {
50 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
51}
52pub fn cofree_ty() -> Expr {
56 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
57}
58pub fn fixpoint_ty() -> Expr {
62 arrow(fn_ty(type0(), type0()), type0())
63}
64pub fn mu_ty() -> Expr {
68 arrow(fn_ty(type0(), type0()), type0())
69}
70pub fn nu_ty() -> Expr {
74 arrow(fn_ty(type0(), type0()), type0())
75}
76pub 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}
95pub 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}
112pub 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}
137pub fn catamorphism_ty() -> Expr {
141 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
142}
143pub fn paramorphism_ty() -> Expr {
147 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
148}
149pub fn histomorphism_ty() -> Expr {
153 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
154}
155pub fn futumorphism_ty() -> Expr {
159 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
160}
161pub fn hylomorphism_ty() -> Expr {
165 arrow(
166 fn_ty(type0(), type0()),
167 arrow(type0(), fn_ty(type0(), type0())),
168 )
169}
170pub fn chronomorphism_ty() -> Expr {
174 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
175}
176pub fn lens_ty() -> Expr {
180 arrow(type0(), fn_ty(type0(), type0()))
181}
182pub fn prism_ty() -> Expr {
186 arrow(type0(), fn_ty(type0(), type0()))
187}
188pub fn traversal_ty() -> Expr {
192 arrow(type0(), fn_ty(type0(), type0()))
193}
194pub fn iso_ty() -> Expr {
198 arrow(type0(), fn_ty(type0(), type0()))
199}
200pub fn affine_traversal_ty() -> Expr {
204 arrow(type0(), fn_ty(type0(), type0()))
205}
206pub fn effect_ty() -> Expr {
210 arrow(type0(), fn_ty(type0(), type0()))
211}
212pub fn effect_handler_ty() -> Expr {
216 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
217}
218pub fn algebraic_effect_ty() -> Expr {
222 arrow(type0(), fn_ty(type0(), type0()))
223}
224pub fn free_selective_ty() -> Expr {
228 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
229}
230pub fn arrow_ty() -> Expr {
234 arrow(type0(), fn_ty(type0(), type0()))
235}
236pub fn hlist_ty() -> Expr {
240 type0()
241}
242pub fn hmap_ty() -> Expr {
246 arrow(type0(), fn_ty(type0(), type0()))
247}
248pub fn singleton_ty() -> Expr {
252 arrow(type0(), type0())
253}
254pub fn type_equality_ty() -> Expr {
258 arrow(type0(), fn_ty(type0(), prop()))
259}
260pub fn coerce_ty() -> Expr {
264 arrow(type0(), fn_ty(type0(), prop()))
265}
266pub 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}
277pub 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}
288pub 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}
304pub 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}
320pub 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}
336pub 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}
347pub 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}
358pub 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}
366pub 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}
381pub 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}
395pub 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}
409pub fn scott_domain_ty() -> Expr {
414 type0()
415}
416pub fn scott_continuous_ty() -> Expr {
420 arrow(type0(), fn_ty(type0(), prop()))
421}
422pub fn fixed_point_semantics_ty() -> Expr {
427 pi(
428 BinderInfo::Default,
429 "F",
430 fn_ty(type0(), type0()),
431 arrow(type0(), prop()),
432 )
433}
434pub fn full_abstraction_ty() -> Expr {
438 arrow(type0(), fn_ty(type0(), prop()))
439}
440pub fn least_upper_bound_ty() -> Expr {
444 arrow(type0(), fn_ty(type0(), prop()))
445}
446pub fn approximation_order_ty() -> Expr {
450 arrow(type0(), fn_ty(type0(), prop()))
451}
452pub fn effect_row_ty() -> Expr {
457 type0()
458}
459pub fn scoped_effect_ty() -> Expr {
463 arrow(type0(), fn_ty(type0(), type0()))
464}
465pub fn deep_handler_ty() -> Expr {
470 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
471}
472pub fn shallow_handler_ty() -> Expr {
476 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
477}
478pub fn effect_subrow_ty() -> Expr {
482 arrow(type0(), fn_ty(type0(), prop()))
483}
484pub fn freer_monad_ty() -> Expr {
489 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
490}
491pub fn free_applicative_ty() -> Expr {
495 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
496}
497pub 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}
508pub 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}
527pub fn profunctor_ty() -> Expr {
531 arrow(type0(), fn_ty(type0(), type0()))
532}
533pub fn strong_profunctor_ty() -> Expr {
537 arrow(type0(), fn_ty(type0(), type0()))
538}
539pub fn tambara_module_ty() -> Expr {
544 arrow(type0(), fn_ty(type0(), type0()))
545}
546pub 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}
563pub 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}
584pub 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}
600pub fn van_laarhoven_lens_ty() -> Expr {
604 arrow(type0(), fn_ty(type0(), type0()))
605}
606pub 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}
622pub 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}
638pub fn comonad_ty() -> Expr {
642 arrow(fn_ty(type0(), type0()), type0())
643}
644pub fn comonad_law_ty() -> Expr {
649 pi(
650 BinderInfo::Default,
651 "W",
652 fn_ty(type0(), type0()),
653 arrow(type0(), prop()),
654 )
655}
656pub fn cellular_automata_comonad_ty() -> Expr {
660 arrow(type0(), type0())
661}
662pub fn stream_comonad_ty() -> Expr {
666 arrow(type0(), type0())
667}
668pub fn cofree_comonad_unfold_ty() -> Expr {
672 pi(
673 BinderInfo::Default,
674 "F",
675 fn_ty(type0(), type0()),
676 arrow(type0(), prop()),
677 )
678}
679pub fn applicative_ty() -> Expr {
683 arrow(fn_ty(type0(), type0()), type0())
684}
685pub fn applicative_law_ty() -> Expr {
689 pi(
690 BinderInfo::Default,
691 "F",
692 fn_ty(type0(), type0()),
693 arrow(type0(), prop()),
694 )
695}
696pub fn day_convolution_ty() -> Expr {
700 arrow(
701 fn_ty(type0(), type0()),
702 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0())),
703 )
704}
705pub fn idiom_bracket_ty() -> Expr {
709 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0()))
710}
711pub fn arrow_choice_ty() -> Expr {
715 arrow(type0(), fn_ty(type0(), type0()))
716}
717pub fn arrow_apply_ty() -> Expr {
721 arrow(type0(), fn_ty(type0(), type0()))
722}
723pub fn arrow_law_ty() -> Expr {
727 arrow(type0(), fn_ty(type0(), prop()))
728}
729pub fn arrow_first_ty() -> Expr {
733 arrow(type0(), arrow(type0(), fn_ty(type0(), type0())))
734}
735pub fn initial_algebra_ty() -> Expr {
739 pi(
740 BinderInfo::Default,
741 "F",
742 fn_ty(type0(), type0()),
743 arrow(type0(), prop()),
744 )
745}
746pub fn final_coalgebra_ty() -> Expr {
750 pi(
751 BinderInfo::Default,
752 "F",
753 fn_ty(type0(), type0()),
754 arrow(type0(), prop()),
755 )
756}
757pub fn banach_fixed_point_ty() -> Expr {
761 arrow(type0(), fn_ty(type0(), prop()))
762}
763pub fn fixpoint_type_ty() -> Expr {
767 arrow(fn_ty(type0(), type0()), type0())
768}
769pub fn cont_t_ty() -> Expr {
773 arrow(
774 type0(),
775 arrow(fn_ty(type0(), type0()), fn_ty(type0(), type0())),
776 )
777}
778pub fn shift_ty() -> Expr {
782 arrow(type0(), fn_ty(type0(), type0()))
783}
784pub fn reset_ty() -> Expr {
788 arrow(type0(), fn_ty(type0(), type0()))
789}
790pub fn cps_transform_ty() -> Expr {
794 arrow(type0(), fn_ty(type0(), type0()))
795}
796pub fn double_negation_translation_ty() -> Expr {
800 arrow(type0(), prop())
801}
802pub fn unique_type_ty() -> Expr {
806 arrow(type0(), type0())
807}
808pub fn linear_type_ty() -> Expr {
812 arrow(type0(), type0())
813}
814pub fn uniqueness_law_ty() -> Expr {
818 arrow(type0(), prop())
819}
820pub fn linearity_law_ty() -> Expr {
824 arrow(type0(), prop())
825}
826pub 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}