1use super::functions::*;
6
7#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct Futumorphism {
11 pub coalgebra_name: String,
12}
13#[allow(dead_code)]
14impl Futumorphism {
15 pub fn new(coalgebra_name: &str) -> Self {
16 Self {
17 coalgebra_name: coalgebra_name.to_string(),
18 }
19 }
20 pub fn interleave<A: Clone>(xs: &[A], ys: &[A]) -> Vec<A> {
22 let mut result = Vec::new();
23 for i in 0..xs.len().max(ys.len()) {
24 if i < xs.len() {
25 result.push(xs[i].clone());
26 }
27 if i < ys.len() {
28 result.push(ys[i].clone());
29 }
30 }
31 result
32 }
33}
34#[allow(dead_code)]
36#[derive(Debug, Clone)]
37pub struct DefunctClosure {
38 pub tag: String,
39 pub free_variables: Vec<(String, String)>,
40 pub apply_case: String,
41}
42#[allow(dead_code)]
43impl DefunctClosure {
44 pub fn new(tag: &str, free_vars: Vec<(&str, &str)>, apply: &str) -> Self {
46 Self {
47 tag: tag.to_string(),
48 free_variables: free_vars
49 .iter()
50 .map(|(n, t)| (n.to_string(), t.to_string()))
51 .collect(),
52 apply_case: apply.to_string(),
53 }
54 }
55 pub fn arity(&self) -> usize {
57 self.free_variables.len()
58 }
59 pub fn apply_description(&self) -> String {
61 format!("apply({}) = {}", self.tag, self.apply_case)
62 }
63}
64#[derive(Clone)]
69pub struct Zipper<A> {
70 pub left: Vec<A>,
71 pub focus: A,
72 pub right: Vec<A>,
73}
74impl<A: Clone> Zipper<A> {
75 pub fn new(data: Vec<A>, i: usize) -> Option<Self> {
79 if data.is_empty() || i >= data.len() {
80 return None;
81 }
82 let mut v = data;
83 let right = v.split_off(i + 1);
84 let focus = v
85 .pop()
86 .expect("v is non-empty: i < data.len() and v is data[..=i]");
87 Some(Self {
88 left: v,
89 focus,
90 right,
91 })
92 }
93 pub fn extract(&self) -> &A {
95 &self.focus
96 }
97 pub fn extend<B: Clone>(&self, f: impl Fn(&Zipper<A>) -> B) -> Zipper<B> {
101 let all: Vec<A> = self
102 .left
103 .iter()
104 .cloned()
105 .chain(std::iter::once(self.focus.clone()))
106 .chain(self.right.iter().cloned())
107 .collect();
108 let focus_idx = self.left.len();
109 let results: Vec<B> = (0..all.len())
110 .map(|i| {
111 let z = Zipper::new(all.clone(), i)
112 .expect("i < all.len(): iterating over 0..all.len()");
113 f(&z)
114 })
115 .collect();
116 Zipper::new(results, focus_idx).expect(
117 "focus_idx < results.len(): focus_idx == left.len() < all.len() == results.len()",
118 )
119 }
120 pub fn move_left(&self) -> Option<Zipper<A>> {
122 if self.left.is_empty() {
123 return None;
124 }
125 let mut new_left = self.left.clone();
126 let new_focus = new_left
127 .pop()
128 .expect("new_left is non-empty: left is non-empty, checked by early return");
129 let mut new_right = vec![self.focus.clone()];
130 new_right.extend(self.right.iter().cloned());
131 Some(Zipper {
132 left: new_left,
133 focus: new_focus,
134 right: new_right,
135 })
136 }
137 pub fn move_right(&self) -> Option<Zipper<A>> {
139 if self.right.is_empty() {
140 return None;
141 }
142 let mut new_right = self.right.clone();
143 let new_focus = new_right.remove(0);
144 let mut new_left = self.left.clone();
145 new_left.push(self.focus.clone());
146 Some(Zipper {
147 left: new_left,
148 focus: new_focus,
149 right: new_right,
150 })
151 }
152 pub fn to_vec(&self) -> Vec<A> {
154 self.left
155 .iter()
156 .cloned()
157 .chain(std::iter::once(self.focus.clone()))
158 .chain(self.right.iter().cloned())
159 .collect()
160 }
161 pub fn len(&self) -> usize {
163 self.left.len() + 1 + self.right.len()
164 }
165 pub fn is_empty(&self) -> bool {
167 false
168 }
169 pub fn is_singleton(&self) -> bool {
171 self.left.is_empty() && self.right.is_empty()
172 }
173}
174#[allow(dead_code)]
176#[derive(Debug, Clone)]
177pub struct Apomorphism {
178 pub coalgebra_name: String,
179}
180#[allow(dead_code)]
181impl Apomorphism {
182 pub fn new(coalgebra_name: &str) -> Self {
183 Self {
184 coalgebra_name: coalgebra_name.to_string(),
185 }
186 }
187 pub fn insert_sorted(mut xs: Vec<i64>, x: i64) -> Vec<i64> {
189 let pos = xs.partition_point(|&v| v <= x);
190 xs.insert(pos, x);
191 xs
192 }
193}
194#[allow(dead_code)]
196pub struct ChurchNumerals;
197#[allow(dead_code)]
198impl ChurchNumerals {
199 pub fn church_zero_desc() -> &'static str {
201 "λf. λx. x"
202 }
203 pub fn church_succ_desc() -> &'static str {
205 "λn. λf. λx. f (n f x)"
206 }
207 pub fn church_to_u64(n: u64) -> u64 {
209 n
210 }
211 pub fn church_add(m: u64, n: u64) -> u64 {
213 m + n
214 }
215 pub fn church_mul(m: u64, n: u64) -> u64 {
217 m * n
218 }
219 pub fn church_pow(m: u64, n: u64) -> u64 {
221 m.pow(n as u32)
222 }
223}
224#[allow(dead_code)]
225#[derive(Debug, Clone)]
226pub struct TraversableData {
227 pub container_type: String,
228 pub traverse_type: String,
229 pub is_foldable: bool,
230 pub naturality_condition: String,
231}
232#[allow(dead_code)]
233impl TraversableData {
234 pub fn list_traversable() -> Self {
235 TraversableData {
236 container_type: "List".to_string(),
237 traverse_type: "Applicative f => (a -> f b) -> [a] -> f [b]".to_string(),
238 is_foldable: true,
239 naturality_condition: "t . traverse g = traverse (t . g)".to_string(),
240 }
241 }
242 pub fn map_traversable() -> Self {
243 TraversableData {
244 container_type: "Map k".to_string(),
245 traverse_type: "Applicative f => (a -> f b) -> Map k a -> f (Map k b)".to_string(),
246 is_foldable: true,
247 naturality_condition: "t . traverse g = traverse (t . g)".to_string(),
248 }
249 }
250 pub fn laws(&self) -> Vec<String> {
251 vec![
252 "Naturality: t . traverse f = traverse (t . f) for natural t".to_string(),
253 "Identity: traverse Identity = Identity".to_string(),
254 "Composition: traverse (Compose . fmap g . f) = Compose . fmap (traverse g) . traverse f"
255 .to_string(),
256 ]
257 }
258 pub fn efficient_mapaccum(&self) -> String {
259 format!(
260 "mapAccumL/R for {}: O(n) traversal with accumulated state",
261 self.container_type
262 )
263 }
264}
265pub struct Traversal<S, A> {
267 to_list: Box<dyn Fn(&S) -> Vec<A>>,
269 from_list: Box<dyn Fn(Vec<A>, &S) -> S>,
271}
272impl<S: 'static + Clone, A: 'static + Clone> Traversal<S, A> {
273 pub fn new(
275 to_list: impl Fn(&S) -> Vec<A> + 'static,
276 from_list: impl Fn(Vec<A>, &S) -> S + 'static,
277 ) -> Self {
278 Self {
279 to_list: Box::new(to_list),
280 from_list: Box::new(from_list),
281 }
282 }
283 pub fn view(&self, s: &S) -> Vec<A> {
285 (self.to_list)(s)
286 }
287 pub fn over(&self, f: impl Fn(A) -> A, s: S) -> S {
289 let vals: Vec<A> = (self.to_list)(&s).into_iter().map(&f).collect();
290 (self.from_list)(vals, &s)
291 }
292}
293pub struct RecursionSchemeEval;
295impl RecursionSchemeEval {
296 pub fn cata<A, B>(tree: RoseTree<A>, alg: &dyn Fn(A, Vec<B>) -> B) -> B {
300 match tree {
301 RoseTree::Node(a, children) => {
302 let results: Vec<B> = children.into_iter().map(|c| Self::cata(c, alg)).collect();
303 alg(a, results)
304 }
305 }
306 }
307 pub fn ana<A, S: Clone>(seed: S, coalg: &dyn Fn(S) -> (A, Vec<S>)) -> RoseTree<A> {
311 let (a, children) = coalg(seed);
312 let subtrees = children.into_iter().map(|s| Self::ana(s, coalg)).collect();
313 RoseTree::Node(a, subtrees)
314 }
315 pub fn hylo<A, B, S: Clone>(
317 seed: S,
318 coalg: &dyn Fn(S) -> (A, Vec<S>),
319 alg: &dyn Fn(A, Vec<B>) -> B,
320 ) -> B {
321 let (a, children) = coalg(seed);
322 let results: Vec<B> = children
323 .into_iter()
324 .map(|s| Self::hylo(s, coalg, alg))
325 .collect();
326 alg(a, results)
327 }
328}
329#[allow(dead_code)]
331#[derive(Debug, Clone)]
332pub struct Paramorphism {
333 pub algebra_name: String,
334}
335#[allow(dead_code)]
336impl Paramorphism {
337 pub fn new(algebra_name: &str) -> Self {
338 Self {
339 algebra_name: algebra_name.to_string(),
340 }
341 }
342 pub fn factorial_para(n: u64) -> u64 {
344 (1..=n).product()
345 }
346 pub fn tails_para<A: Clone>(xs: &[A]) -> Vec<Vec<A>> {
348 (0..=xs.len()).map(|i| xs[i..].to_vec()).collect()
349 }
350}
351#[allow(dead_code)]
353#[derive(Debug, Clone)]
354pub struct ReaderMonad<R: Clone, A: Clone> {
355 _phantom_r: std::marker::PhantomData<R>,
356 _phantom_a: std::marker::PhantomData<A>,
357 pub description: String,
358}
359#[allow(dead_code)]
360impl<R: Clone, A: Clone> ReaderMonad<R, A> {
361 pub fn new(desc: &str) -> Self {
362 Self {
363 _phantom_r: std::marker::PhantomData,
364 _phantom_a: std::marker::PhantomData,
365 description: desc.to_string(),
366 }
367 }
368 pub fn ask_desc(&self) -> String {
369 format!("ask :: Reader {}", std::any::type_name::<R>())
370 }
371 pub fn local_desc(&self) -> String {
372 format!(
373 "local :: ({0} -> {0}) -> Reader {0} _",
374 std::any::type_name::<R>()
375 )
376 }
377}
378#[allow(dead_code)]
379#[derive(Debug, Clone)]
380pub struct ArrowData {
381 pub arrow_name: String,
382 pub arr_type: String,
383 pub compose_type: String,
384 pub first_type: String,
385 pub is_arrowchoice: bool,
386 pub is_arrowloop: bool,
387}
388#[allow(dead_code)]
389impl ArrowData {
390 pub fn function_arrow() -> Self {
391 ArrowData {
392 arrow_name: "->".to_string(),
393 arr_type: "(b -> c) -> Arrow b c".to_string(),
394 compose_type: "Arrow b c -> Arrow c d -> Arrow b d".to_string(),
395 first_type: "Arrow b c -> Arrow (b, d) (c, d)".to_string(),
396 is_arrowchoice: true,
397 is_arrowloop: true,
398 }
399 }
400 pub fn kleisli_arrow(monad: &str) -> Self {
401 ArrowData {
402 arrow_name: format!("Kleisli {}", monad),
403 arr_type: format!("(b -> {} c) -> Kleisli {} b c", monad, monad),
404 compose_type: format!(
405 "Kleisli {} b c -> Kleisli {} c d -> Kleisli {} b d",
406 monad, monad, monad
407 ),
408 first_type: format!("Kleisli {} b c -> Kleisli {} (b,d) (c,d)", monad, monad),
409 is_arrowchoice: false,
410 is_arrowloop: false,
411 }
412 }
413 pub fn hughes_laws(&self) -> Vec<String> {
414 vec![
415 "arr id = id".to_string(),
416 "arr (f . g) = arr f . arr g".to_string(),
417 "first (arr f) = arr (f *** id)".to_string(),
418 "first (f . g) = first f . first g".to_string(),
419 ]
420 }
421 pub fn freyd_category_connection(&self) -> String {
422 "Arrows generalize Freyd categories (Power-Thielecke): model effectful computations"
423 .to_string()
424 }
425}
426pub struct HMap {
428 entries: Vec<(String, Box<dyn std::any::Any>)>,
429}
430impl HMap {
431 pub fn new() -> Self {
433 Self {
434 entries: Vec::new(),
435 }
436 }
437 pub fn insert<V: 'static>(&mut self, key: impl Into<String>, value: V) {
439 self.entries.push((key.into(), Box::new(value)));
440 }
441 pub fn get<V: 'static>(&self, key: &str) -> Option<&V> {
443 self.entries
444 .iter()
445 .find(|(k, _)| k == key)
446 .and_then(|(_, v)| v.downcast_ref::<V>())
447 }
448 pub fn len(&self) -> usize {
450 self.entries.len()
451 }
452 pub fn is_empty(&self) -> bool {
454 self.entries.is_empty()
455 }
456}
457pub struct Prism<S, A> {
459 preview: Box<dyn Fn(S) -> Option<A>>,
460 review: Box<dyn Fn(A) -> S>,
461}
462impl<S: 'static, A: 'static> Prism<S, A> {
463 pub fn new(
465 preview: impl Fn(S) -> Option<A> + 'static,
466 review: impl Fn(A) -> S + 'static,
467 ) -> Self {
468 Self {
469 preview: Box::new(preview),
470 review: Box::new(review),
471 }
472 }
473 pub fn preview(&self, s: S) -> Option<A> {
475 (self.preview)(s)
476 }
477 pub fn review(&self, a: A) -> S {
479 (self.review)(a)
480 }
481}
482#[allow(dead_code)]
484pub enum ConsoleProg<A> {
485 Done(A),
487 Step(ConsoleEffect, Box<dyn FnOnce(String) -> ConsoleProg<A>>),
489}
490#[allow(dead_code)]
492#[derive(Debug, Clone)]
493pub struct StateMonad<S: Clone, A: Clone> {
494 _phantom_s: std::marker::PhantomData<S>,
495 _phantom_a: std::marker::PhantomData<A>,
496 pub description: String,
497}
498#[allow(dead_code)]
499impl<S: Clone, A: Clone> StateMonad<S, A> {
500 pub fn new(description: &str) -> Self {
501 Self {
502 _phantom_s: std::marker::PhantomData,
503 _phantom_a: std::marker::PhantomData,
504 description: description.to_string(),
505 }
506 }
507 pub fn get_desc(&self) -> String {
508 format!(
509 "get :: State {} {}",
510 std::any::type_name::<S>(),
511 std::any::type_name::<A>()
512 )
513 }
514 pub fn put_desc(&self) -> String {
515 format!(
516 "put :: {} -> State {} ()",
517 std::any::type_name::<S>(),
518 std::any::type_name::<S>()
519 )
520 }
521 pub fn modify_desc(&self) -> String {
522 format!(
523 "modify :: ({0} -> {0}) -> State {0} ()",
524 std::any::type_name::<S>()
525 )
526 }
527}
528#[allow(dead_code)]
529#[derive(Debug, Clone)]
530pub struct DependentTypeExample {
531 pub type_name: String,
532 pub type_signature: String,
533 pub invariant: String,
534 pub language: String,
535}
536#[allow(dead_code)]
537impl DependentTypeExample {
538 pub fn fixed_length_vector(elem_type: &str, n: usize) -> Self {
539 DependentTypeExample {
540 type_name: format!("Vec {} {}", elem_type, n),
541 type_signature: format!("Vec : Type -> ℕ -> Type"),
542 invariant: format!("length is exactly {}", n),
543 language: "Agda/Idris/Lean".to_string(),
544 }
545 }
546 pub fn sorted_list(elem_type: &str) -> Self {
547 DependentTypeExample {
548 type_name: format!("SortedList {}", elem_type),
549 type_signature: "SortedList : Type -> Type".to_string(),
550 invariant: "all elements in sorted order".to_string(),
551 language: "Agda".to_string(),
552 }
553 }
554 pub fn fin_type(n: usize) -> Self {
555 DependentTypeExample {
556 type_name: format!("Fin {}", n),
557 type_signature: "Fin : ℕ -> Type".to_string(),
558 invariant: format!("indices in {{0,..,{}}}", n.saturating_sub(1)),
559 language: "Agda/Lean".to_string(),
560 }
561 }
562 pub fn type_safety_guarantee(&self) -> String {
563 format!(
564 "{}: type system enforces '{}' statically (no runtime check needed)",
565 self.type_name, self.invariant
566 )
567 }
568 pub fn extraction_to_code(&self) -> String {
569 format!(
570 "From {} proof to certified {} code via extraction",
571 self.language, self.language
572 )
573 }
574}
575#[allow(dead_code)]
577#[derive(Debug, Clone)]
578pub enum FreeApplicative<A: Clone> {
579 Pure(A),
580 Ap(usize, Box<FreeApplicative<A>>),
581}
582#[allow(dead_code)]
583impl<A: Clone> FreeApplicative<A> {
584 pub fn pure_val(a: A) -> Self {
585 FreeApplicative::Pure(a)
586 }
587 pub fn depth(&self) -> usize {
588 match self {
589 FreeApplicative::Pure(_) => 0,
590 FreeApplicative::Ap(_, x) => 1 + x.depth(),
591 }
592 }
593}
594#[allow(dead_code)]
596#[derive(Debug, Clone)]
597pub struct Histomorphism {
598 pub algebra_name: String,
599 pub cache: Vec<i64>,
600}
601#[allow(dead_code)]
602impl Histomorphism {
603 pub fn new(algebra_name: &str) -> Self {
604 Self {
605 algebra_name: algebra_name.to_string(),
606 cache: Vec::new(),
607 }
608 }
609 pub fn fibonacci_histo(&mut self, n: usize) -> i64 {
611 for i in self.cache.len()..=n {
612 let v = if i == 0 {
613 0
614 } else if i == 1 {
615 1
616 } else {
617 self.cache[i - 1] + self.cache[i - 2]
618 };
619 self.cache.push(v);
620 }
621 self.cache[n]
622 }
623}
624pub enum Effect<E, A> {
626 Pure(A),
628 Perform(E, Box<dyn FnOnce(()) -> Effect<E, A>>),
630}
631impl<E: 'static, A: 'static> Effect<E, A> {
632 pub fn pure(a: A) -> Self {
634 Effect::Pure(a)
635 }
636 pub fn handle(self, handler: &dyn Fn(E)) -> A
638 where
639 A: Default,
640 {
641 match self {
642 Effect::Pure(a) => a,
643 Effect::Perform(e, k) => {
644 handler(e);
645 k(()).handle(handler)
646 }
647 }
648 }
649}
650pub struct ComonadExtend;
652impl ComonadExtend {
653 pub fn extend<A: Clone, B: Clone>(z: &Zipper<A>, f: impl Fn(&Zipper<A>) -> B) -> Zipper<B> {
655 z.extend(f)
656 }
657 pub fn duplicate<A: Clone>(z: &Zipper<A>) -> Zipper<Zipper<A>> {
659 z.extend(|sub_z| {
660 let left = sub_z.left.clone();
661 let focus = sub_z.focus.clone();
662 let right = sub_z.right.clone();
663 Zipper { left, focus, right }
664 })
665 }
666}
667#[allow(dead_code)]
669#[derive(Debug, Clone)]
670pub struct Hylomorphism {
671 pub seed_label: String,
672 pub unfold_steps: Vec<String>,
673 pub fold_steps: Vec<String>,
674}
675#[allow(dead_code)]
676impl Hylomorphism {
677 pub fn new(seed_label: &str) -> Self {
678 Self {
679 seed_label: seed_label.to_string(),
680 unfold_steps: Vec::new(),
681 fold_steps: Vec::new(),
682 }
683 }
684 pub fn add_unfold_step(mut self, step: &str) -> Self {
685 self.unfold_steps.push(step.to_string());
686 self
687 }
688 pub fn add_fold_step(mut self, step: &str) -> Self {
689 self.fold_steps.push(step.to_string());
690 self
691 }
692 pub fn fibonacci_hylo(n: u32) -> u64 {
694 fn fib(n: u32) -> u64 {
695 if n <= 1 {
696 return n as u64;
697 }
698 let mut a = 0u64;
699 let mut b = 1u64;
700 for _ in 2..=n {
701 let c = a + b;
702 a = b;
703 b = c;
704 }
705 b
706 }
707 fib(n)
708 }
709}
710#[allow(dead_code)]
712#[derive(Debug, Clone)]
713pub struct EffectSystem {
714 pub effect_name: String,
715 pub operations: Vec<(String, String)>,
716 pub handler_type: String,
717}
718#[allow(dead_code)]
719impl EffectSystem {
720 pub fn state(state_type: &str) -> Self {
722 Self {
723 effect_name: format!("State({})", state_type),
724 operations: vec![
725 ("get".to_string(), format!("unit -> {}", state_type)),
726 ("put".to_string(), format!("{} -> unit", state_type)),
727 ],
728 handler_type: format!("{} -> a -> ({} * {})", state_type, state_type, "a"),
729 }
730 }
731 pub fn exception(exc_type: &str) -> Self {
733 Self {
734 effect_name: format!("Exception({})", exc_type),
735 operations: vec![("throw".to_string(), format!("{} -> a", exc_type))],
736 handler_type: format!("({} -> b) -> (a -> b) -> b", exc_type),
737 }
738 }
739 pub fn num_ops(&self) -> usize {
741 self.operations.len()
742 }
743}
744pub struct ProfunctorOptic<S, T, A, B> {
749 run: Box<dyn Fn(Box<dyn Fn(A) -> B>) -> Box<dyn Fn(S) -> T>>,
750}
751impl<S: 'static, T: 'static, A: 'static, B: 'static> ProfunctorOptic<S, T, A, B> {
752 pub fn new(run: impl Fn(Box<dyn Fn(A) -> B>) -> Box<dyn Fn(S) -> T> + 'static) -> Self {
754 Self { run: Box::new(run) }
755 }
756 pub fn apply(&self, f: impl Fn(A) -> B + 'static) -> Box<dyn Fn(S) -> T> {
758 (self.run)(Box::new(f))
759 }
760 pub fn lens_optic(
762 getter: impl Fn(&S) -> A + 'static,
763 setter: impl Fn(B, S) -> T + 'static,
764 ) -> Self
765 where
766 S: Clone + 'static,
767 {
768 let getter = std::sync::Arc::new(getter);
769 let setter = std::sync::Arc::new(setter);
770 Self::new(move |f: Box<dyn Fn(A) -> B>| {
771 let getter = getter.clone();
772 let setter = setter.clone();
773 let f = std::sync::Arc::new(f);
774 Box::new(move |s: S| {
775 let a = getter(&s);
776 let b = f(a);
777 setter(b, s)
778 })
779 })
780 }
781 pub fn prism_optic(
783 preview: impl Fn(S) -> Result<A, T> + 'static,
784 review: impl Fn(B) -> T + 'static,
785 ) -> Self
786 where
787 S: 'static,
788 {
789 let preview = std::sync::Arc::new(preview);
790 let review = std::sync::Arc::new(review);
791 Self::new(move |f: Box<dyn Fn(A) -> B>| {
792 let preview = preview.clone();
793 let review = review.clone();
794 let f = std::sync::Arc::new(f);
795 Box::new(move |s: S| match preview(s) {
796 Ok(a) => review(f(a)),
797 Err(t) => t,
798 })
799 })
800 }
801}
802pub enum HList {
804 Nil,
806 Cons(Box<dyn std::any::Any>, Box<HList>),
808}
809impl HList {
810 pub fn nil() -> Self {
812 HList::Nil
813 }
814 pub fn cons<T: 'static>(head: T, tail: HList) -> Self {
816 HList::Cons(Box::new(head), Box::new(tail))
817 }
818 pub fn len(&self) -> usize {
820 match self {
821 HList::Nil => 0,
822 HList::Cons(_, tail) => 1 + tail.len(),
823 }
824 }
825 pub fn is_empty(&self) -> bool {
827 matches!(self, HList::Nil)
828 }
829}
830#[allow(dead_code)]
834pub enum RoseTree<A> {
835 Node(A, Vec<RoseTree<A>>),
837}
838pub struct TypeEquality<S, T> {
840 _coerce: std::marker::PhantomData<(S, T)>,
841}
842impl<T> TypeEquality<T, T> {
843 pub fn refl() -> Self {
845 TypeEquality {
846 _coerce: std::marker::PhantomData,
847 }
848 }
849}
850impl<S, T> TypeEquality<S, T> {
851 pub fn coerce(self, s: S) -> T
853 where
854 S: Into<T>,
855 {
856 s.into()
857 }
858}
859pub struct LensComposer;
861impl LensComposer {
862 pub fn compose<S, M, A>(outer: Lens<S, M>, inner: Lens<M, A>) -> impl Fn(&S) -> A
865 where
866 S: Clone + 'static,
867 M: Clone + 'static,
868 A: Clone + 'static,
869 {
870 move |s: &S| {
871 let m = outer.view(s);
872 inner.view(&m)
873 }
874 }
875 pub fn check_get_set<S, A>(lens: &Lens<S, A>, s: S) -> bool
877 where
878 S: Clone + PartialEq + 'static,
879 A: Clone + 'static,
880 {
881 let a = lens.view(&s);
882 let s2 = lens.set(a, s.clone());
883 s2 == s
884 }
885 pub fn check_set_get<S, A>(lens: &Lens<S, A>, a: A, s: S) -> bool
887 where
888 S: Clone + 'static,
889 A: Clone + PartialEq + 'static,
890 {
891 let s2 = lens.set(a.clone(), s);
892 let a2 = lens.view(&s2);
893 a2 == a
894 }
895 pub fn check_set_set<S, A>(lens: &Lens<S, A>, a1: A, a2: A, s: S) -> bool
897 where
898 S: Clone + PartialEq + 'static,
899 A: Clone + 'static,
900 {
901 let s_after_a1 = lens.set(a1, s.clone());
902 let s_after_a2_a1 = lens.set(a2.clone(), s_after_a1);
903 let s_after_a2 = lens.set(a2, s);
904 s_after_a2_a1 == s_after_a2
905 }
906}
907pub struct Coerce<S, T> {
909 _marker: std::marker::PhantomData<(S, T)>,
910}
911impl<S: 'static, T: 'static> Coerce<S, T> {
912 pub fn try_coerce(s: S) -> Option<T> {
914 let boxed: Box<dyn std::any::Any> = Box::new(s);
915 boxed.downcast::<T>().ok().map(|b| *b)
916 }
917}
918#[allow(dead_code)]
920#[derive(Debug, Clone)]
921pub struct FreeMonadInfo {
922 pub functor_name: String,
923 pub operations: Vec<String>,
924 pub description: String,
925}
926#[allow(dead_code)]
927impl FreeMonadInfo {
928 pub fn over(functor: &str, ops: Vec<&str>) -> Self {
930 Self {
931 functor_name: functor.to_string(),
932 operations: ops.iter().map(|s| s.to_string()).collect(),
933 description: format!("Free monad over {} with {} operations", functor, ops.len()),
934 }
935 }
936 pub fn interpreter_description(&self) -> String {
938 format!(
939 "foldFree :: ({} a -> m a) -> Free {} a -> m a",
940 self.functor_name, self.functor_name
941 )
942 }
943 pub fn num_operations(&self) -> usize {
945 self.operations.len()
946 }
947}
948#[allow(dead_code)]
950#[derive(Debug, Clone)]
951pub struct CpsTransform {
952 pub source_type: String,
953 pub result_type: String,
954 pub continuation_type: String,
955}
956#[allow(dead_code)]
957impl CpsTransform {
958 pub fn new(source: &str, result: &str) -> Self {
960 Self {
961 source_type: source.to_string(),
962 result_type: result.to_string(),
963 continuation_type: format!("({} -> {}) -> {}", source, result, result),
964 }
965 }
966 pub fn transform_description(&self) -> String {
968 format!("CPS[{}] = ({})", self.source_type, self.continuation_type)
969 }
970}
971#[allow(dead_code)]
973pub struct ScottEncoding;
974#[allow(dead_code)]
975impl ScottEncoding {
976 pub fn scott_true_desc() -> &'static str {
978 "λt. λf. t"
979 }
980 pub fn scott_false_desc() -> &'static str {
981 "λt. λf. f"
982 }
983 pub fn scott_pair_desc() -> &'static str {
985 "λa. λb. λs. s a b"
986 }
987 pub fn scott_fst_desc() -> &'static str {
989 "λp. p (λa. λb. a)"
990 }
991 pub fn scott_nil_desc() -> &'static str {
993 "λn. λc. n"
994 }
995 pub fn scott_cons_desc() -> &'static str {
996 "λh. λt. λn. λc. c h t"
997 }
998}
999pub struct Lens<S, A> {
1001 getter: Box<dyn Fn(&S) -> A>,
1002 setter: Box<dyn Fn(A, S) -> S>,
1003}
1004impl<S: 'static, A: 'static> Lens<S, A> {
1005 pub fn new(getter: impl Fn(&S) -> A + 'static, setter: impl Fn(A, S) -> S + 'static) -> Self {
1007 Self {
1008 getter: Box::new(getter),
1009 setter: Box::new(setter),
1010 }
1011 }
1012 pub fn view(&self, s: &S) -> A {
1014 (self.getter)(s)
1015 }
1016 pub fn set(&self, a: A, s: S) -> S {
1018 (self.setter)(a, s)
1019 }
1020 pub fn over(&self, f: impl Fn(A) -> A, s: S) -> S
1022 where
1023 S: Clone,
1024 {
1025 let a = self.view(&s);
1026 self.set(f(a), s)
1027 }
1028}
1029#[allow(dead_code)]
1031pub struct BoehmBerarducci;
1032#[allow(dead_code)]
1033impl BoehmBerarducci {
1034 pub fn bb_nat_type_desc() -> &'static str {
1036 "forall r. r -> (r -> r) -> r"
1037 }
1038 pub fn bb_list_type_desc() -> &'static str {
1040 "forall r. r -> (a -> r -> r) -> r"
1041 }
1042 pub fn bb_tree_type_desc() -> &'static str {
1044 "forall r. (a -> List r -> r) -> r"
1045 }
1046}
1047pub struct Iso<S, A> {
1049 to: Box<dyn Fn(S) -> A>,
1050 from: Box<dyn Fn(A) -> S>,
1051}
1052impl<S: 'static, A: 'static> Iso<S, A> {
1053 pub fn new(to: impl Fn(S) -> A + 'static, from: impl Fn(A) -> S + 'static) -> Self {
1055 Self {
1056 to: Box::new(to),
1057 from: Box::new(from),
1058 }
1059 }
1060 pub fn view(&self, s: S) -> A {
1062 (self.to)(s)
1063 }
1064 pub fn review(&self, a: A) -> S {
1066 (self.from)(a)
1067 }
1068 pub fn get(&self, s: S) -> A {
1070 (self.to)(s)
1071 }
1072}
1073pub struct EffectHandler<E, A, B> {
1075 handle_fn: Box<dyn Fn(E, Box<dyn FnOnce(A) -> B>) -> B>,
1076}
1077impl<E: 'static, A: 'static, B: 'static> EffectHandler<E, A, B> {
1078 pub fn new(handle_fn: impl Fn(E, Box<dyn FnOnce(A) -> B>) -> B + 'static) -> Self {
1080 Self {
1081 handle_fn: Box::new(handle_fn),
1082 }
1083 }
1084 pub fn run(&self, effect: E, continuation: impl FnOnce(A) -> B + 'static) -> B {
1086 (self.handle_fn)(effect, Box::new(continuation))
1087 }
1088}
1089#[allow(dead_code)]
1091#[derive(Debug, Clone)]
1092pub struct YonedaEmbedding<A: Clone> {
1093 pub object: A,
1094 pub morphism_count: usize,
1095}
1096#[allow(dead_code)]
1097impl<A: Clone> YonedaEmbedding<A> {
1098 pub fn new(object: A) -> Self {
1099 Self {
1100 object,
1101 morphism_count: 0,
1102 }
1103 }
1104 pub fn add_morphism(mut self) -> Self {
1106 self.morphism_count += 1;
1107 self
1108 }
1109}
1110#[allow(dead_code)]
1111#[derive(Debug, Clone)]
1112pub struct HomotopyEquivalence {
1113 pub type_a: String,
1114 pub type_b: String,
1115 pub forth_map: String,
1116 pub back_map: String,
1117 pub is_univalent: bool,
1118}
1119#[allow(dead_code)]
1120impl HomotopyEquivalence {
1121 pub fn new(a: &str, b: &str, f: &str, g: &str) -> Self {
1122 HomotopyEquivalence {
1123 type_a: a.to_string(),
1124 type_b: b.to_string(),
1125 forth_map: f.to_string(),
1126 back_map: g.to_string(),
1127 is_univalent: false,
1128 }
1129 }
1130 pub fn univalent_equivalence(mut self) -> Self {
1131 self.is_univalent = true;
1132 self
1133 }
1134 pub fn contractibility_condition(&self) -> String {
1135 format!(
1136 "{} ≃ {}: ∃ f:{}->{}, g:{}->{}, f∘g∼id, g∘f∼id",
1137 self.type_a, self.type_b, self.type_a, self.type_b, self.type_b, self.type_a
1138 )
1139 }
1140 pub fn univalence_axiom(&self) -> String {
1141 if self.is_univalent {
1142 "(A=B) ≃ (A≃B) (Voevodsky's univalence axiom)".to_string()
1143 } else {
1144 "Not using univalence axiom".to_string()
1145 }
1146 }
1147}
1148#[allow(dead_code)]
1150#[derive(Debug, Clone)]
1151pub struct Cont<R: Clone, A: Clone> {
1152 _phantom_r: std::marker::PhantomData<R>,
1153 _phantom_a: std::marker::PhantomData<A>,
1154 pub label: String,
1155}
1156#[allow(dead_code)]
1157impl<R: Clone, A: Clone> Cont<R, A> {
1158 pub fn new(label: &str) -> Self {
1159 Self {
1160 _phantom_r: std::marker::PhantomData,
1161 _phantom_a: std::marker::PhantomData,
1162 label: label.to_string(),
1163 }
1164 }
1165 pub fn run_cont_desc(&self) -> String {
1167 format!("Cont({}).run_cont", self.label)
1168 }
1169}
1170pub enum FreeMonad<A> {
1172 Pure(A),
1174 Free(Box<dyn FnOnce() -> FreeMonad<A>>),
1176}
1177impl<A> FreeMonad<A> {
1178 pub fn pure(a: A) -> Self {
1180 FreeMonad::Pure(a)
1181 }
1182 pub fn fold<B>(self, pure_fn: impl Fn(A) -> B, free_fn: impl Fn(FreeMonad<A>) -> B) -> B {
1184 match self {
1185 FreeMonad::Pure(a) => pure_fn(a),
1186 FreeMonad::Free(mk) => free_fn(mk()),
1187 }
1188 }
1189}
1190#[allow(dead_code)]
1192pub enum ConsoleEffect {
1193 Print(String),
1195 Read,
1197}
1198pub struct FreeMonadInterpreter;
1200impl FreeMonadInterpreter {
1201 pub fn run<A>(
1203 prog: ConsoleProg<A>,
1204 print_handler: &mut dyn FnMut(&str),
1205 read_handler: &mut dyn FnMut() -> String,
1206 ) -> A {
1207 match prog {
1208 ConsoleProg::Done(a) => a,
1209 ConsoleProg::Step(effect, k) => match effect {
1210 ConsoleEffect::Print(msg) => {
1211 print_handler(&msg);
1212 Self::run(k(String::new()), print_handler, read_handler)
1213 }
1214 ConsoleEffect::Read => {
1215 let line = read_handler();
1216 Self::run(k(line), print_handler, read_handler)
1217 }
1218 },
1219 }
1220 }
1221}
1222#[allow(dead_code)]
1224#[derive(Debug, Clone)]
1225pub struct TypeConstructorFunctor {
1226 pub name: String,
1227 pub fmap_type: String,
1228 pub laws: Vec<String>,
1229}
1230#[allow(dead_code)]
1231impl TypeConstructorFunctor {
1232 pub fn list() -> Self {
1234 Self {
1235 name: "List".to_string(),
1236 fmap_type: "(a -> b) -> List a -> List b".to_string(),
1237 laws: vec![
1238 "fmap id = id".to_string(),
1239 "fmap (f . g) = fmap f . fmap g".to_string(),
1240 ],
1241 }
1242 }
1243 pub fn maybe() -> Self {
1245 Self {
1246 name: "Maybe".to_string(),
1247 fmap_type: "(a -> b) -> Maybe a -> Maybe b".to_string(),
1248 laws: vec![
1249 "fmap id = id".to_string(),
1250 "fmap (f . g) = fmap f . fmap g".to_string(),
1251 ],
1252 }
1253 }
1254 pub fn num_laws(&self) -> usize {
1256 self.laws.len()
1257 }
1258}
1259#[allow(dead_code)]
1260#[derive(Debug, Clone)]
1261pub struct ProfunctorData {
1262 pub profunctor_name: String,
1263 pub dimap_type: String,
1264 pub is_cartesian: bool,
1265 pub is_cocartesian: bool,
1266 pub is_closed: bool,
1267}
1268#[allow(dead_code)]
1269impl ProfunctorData {
1270 pub fn function_profunctor() -> Self {
1271 ProfunctorData {
1272 profunctor_name: "(->)".to_string(),
1273 dimap_type: "(a -> b) -> (c -> d) -> (b -> c) -> (a -> d)".to_string(),
1274 is_cartesian: true,
1275 is_cocartesian: true,
1276 is_closed: true,
1277 }
1278 }
1279 pub fn star_profunctor(functor: &str) -> Self {
1280 ProfunctorData {
1281 profunctor_name: format!("Star {}", functor),
1282 dimap_type: format!(
1283 "(a -> b) -> (c -> d) -> (b -> {} c) -> (a -> {} d)",
1284 functor, functor
1285 ),
1286 is_cartesian: true,
1287 is_cocartesian: false,
1288 is_closed: false,
1289 }
1290 }
1291 pub fn optic_encoding(&self) -> String {
1292 "Profunctor optics: Lens = ∀p. Cartesian p => p a b -> p s t".to_string()
1293 }
1294 pub fn tambara_module_connection(&self) -> String {
1295 "Tambara module: profunctor P with strength α: P a b -> P (c,a) (c,b)".to_string()
1296 }
1297 pub fn bartosz_milewski_connection(&self) -> String {
1298 "Milewski: profunctors and optics in category theory for programmers".to_string()
1299 }
1300}
1301pub struct Singleton<T> {
1303 pub value: T,
1305}
1306impl<T: Clone> Singleton<T> {
1307 pub fn new(value: T) -> Self {
1309 Self { value }
1310 }
1311 pub fn extract(&self) -> T {
1313 self.value.clone()
1314 }
1315}
1316pub struct Arrow<A, B> {
1318 run: Box<dyn Fn(A) -> B>,
1319}
1320impl<A: 'static, B: 'static> Arrow<A, B> {
1321 pub fn arr(f: impl Fn(A) -> B + 'static) -> Self {
1323 Self { run: Box::new(f) }
1324 }
1325 pub fn apply(&self, a: A) -> B {
1327 (self.run)(a)
1328 }
1329 pub fn compose<C: 'static>(self, other: Arrow<B, C>) -> Arrow<A, C> {
1331 Arrow::arr(move |a| other.apply(self.apply(a)))
1332 }
1333}
1334pub struct AffineTraversal<S, A> {
1336 preview: Box<dyn Fn(&S) -> Option<A>>,
1337 set: Box<dyn Fn(A, S) -> S>,
1338}
1339impl<S: 'static, A: 'static> AffineTraversal<S, A> {
1340 pub fn new(
1342 preview: impl Fn(&S) -> Option<A> + 'static,
1343 set: impl Fn(A, S) -> S + 'static,
1344 ) -> Self {
1345 Self {
1346 preview: Box::new(preview),
1347 set: Box::new(set),
1348 }
1349 }
1350 pub fn preview(&self, s: &S) -> Option<A> {
1352 (self.preview)(s)
1353 }
1354 pub fn set(&self, a: A, s: S) -> S {
1356 (self.set)(a, s)
1357 }
1358}
1359#[allow(dead_code)]
1361#[derive(Debug, Clone)]
1362pub struct WriterMonad<A: Clone> {
1363 pub value: A,
1364 pub log: Vec<String>,
1365}
1366#[allow(dead_code)]
1367impl<A: Clone> WriterMonad<A> {
1368 pub fn new(value: A) -> Self {
1369 Self {
1370 value,
1371 log: Vec::new(),
1372 }
1373 }
1374 pub fn tell(mut self, msg: String) -> Self {
1375 self.log.push(msg);
1376 self
1377 }
1378 pub fn listen(&self) -> (&A, &Vec<String>) {
1379 (&self.value, &self.log)
1380 }
1381 pub fn pass<F: Fn(&Vec<String>) -> Vec<String>>(mut self, f: F) -> Self {
1382 self.log = f(&self.log);
1383 self
1384 }
1385}
1386#[allow(dead_code)]
1387#[derive(Debug, Clone)]
1388pub struct ApplicativeData {
1389 pub functor_name: String,
1390 pub pure_type: String,
1391 pub ap_type: String,
1392 pub is_monad: bool,
1393}
1394#[allow(dead_code)]
1395impl ApplicativeData {
1396 pub fn new(name: &str, pure_ty: &str, ap_ty: &str, monad: bool) -> Self {
1397 ApplicativeData {
1398 functor_name: name.to_string(),
1399 pure_type: pure_ty.to_string(),
1400 ap_type: ap_ty.to_string(),
1401 is_monad: monad,
1402 }
1403 }
1404 pub fn maybe_applicative() -> Self {
1405 ApplicativeData {
1406 functor_name: "Maybe".to_string(),
1407 pure_type: "a -> Maybe a".to_string(),
1408 ap_type: "Maybe (a -> b) -> Maybe a -> Maybe b".to_string(),
1409 is_monad: true,
1410 }
1411 }
1412 pub fn validation_applicative() -> Self {
1413 ApplicativeData {
1414 functor_name: "Validation e".to_string(),
1415 pure_type: "a -> Validation e a".to_string(),
1416 ap_type: "Validation e (a -> b) -> Validation e a -> Validation e b".to_string(),
1417 is_monad: false,
1418 }
1419 }
1420 pub fn laws(&self) -> Vec<String> {
1421 vec![
1422 "Identity: pure id <*> v = v".to_string(),
1423 "Composition: pure (.) <*> u <*> v <*> w = u <*> (v <*> w)".to_string(),
1424 "Homomorphism: pure f <*> pure x = pure (f x)".to_string(),
1425 "Interchange: u <*> pure y = pure ($ y) <*> u".to_string(),
1426 ]
1427 }
1428 pub fn mcbride_paterson_paper(&self) -> String {
1429 "McBride-Paterson (2008): Applicative programming with effects".to_string()
1430 }
1431}