1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 Either, OptionFunctor, Pred, Reader, RepresentableFunctorExt, ResultFunctor, VecFunctor, Writer,
9};
10
11pub fn build_functor_env(env: &mut Environment) -> Result<(), String> {
13 let type1 = Expr::Sort(Level::succ(Level::zero()));
14 let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
15 let functor_ty = Expr::Pi(
16 BinderInfo::Default,
17 Name::str("f"),
18 Box::new(Expr::Pi(
19 BinderInfo::Default,
20 Name::str("_"),
21 Box::new(type1.clone()),
22 Box::new(type1.clone()),
23 )),
24 Box::new(type2.clone()),
25 );
26 env.add(Declaration::Axiom {
27 name: Name::str("Functor"),
28 univ_params: vec![],
29 ty: functor_ty,
30 })
31 .map_err(|e| e.to_string())?;
32 let map_ty = Expr::Pi(
33 BinderInfo::Implicit,
34 Name::str("f"),
35 Box::new(Expr::Pi(
36 BinderInfo::Default,
37 Name::str("_"),
38 Box::new(type1.clone()),
39 Box::new(type1.clone()),
40 )),
41 Box::new(Expr::Pi(
42 BinderInfo::InstImplicit,
43 Name::str("_"),
44 Box::new(Expr::App(
45 Box::new(Expr::Const(Name::str("Functor"), vec![])),
46 Box::new(Expr::BVar(0)),
47 )),
48 Box::new(Expr::Pi(
49 BinderInfo::Implicit,
50 Name::str("a"),
51 Box::new(type1.clone()),
52 Box::new(Expr::Pi(
53 BinderInfo::Implicit,
54 Name::str("b"),
55 Box::new(type1.clone()),
56 Box::new(Expr::Pi(
57 BinderInfo::Default,
58 Name::str("fn"),
59 Box::new(Expr::Pi(
60 BinderInfo::Default,
61 Name::str("_"),
62 Box::new(Expr::BVar(1)),
63 Box::new(Expr::BVar(1)),
64 )),
65 Box::new(Expr::Pi(
66 BinderInfo::Default,
67 Name::str("fa"),
68 Box::new(Expr::App(Box::new(Expr::BVar(4)), Box::new(Expr::BVar(2)))),
69 Box::new(Expr::App(Box::new(Expr::BVar(5)), Box::new(Expr::BVar(2)))),
70 )),
71 )),
72 )),
73 )),
74 )),
75 );
76 env.add(Declaration::Axiom {
77 name: Name::str("Functor.map"),
78 univ_params: vec![],
79 ty: map_ty,
80 })
81 .map_err(|e| e.to_string())?;
82 Ok(())
83}
84pub fn build_functor_map_const(env: &mut Environment) -> Result<(), String> {
86 let type1 = Expr::Sort(Level::succ(Level::zero()));
87 let ty = Expr::Pi(
88 BinderInfo::Default,
89 Name::str("_"),
90 Box::new(type1.clone()),
91 Box::new(type1),
92 );
93 env.add(Declaration::Axiom {
94 name: Name::str("Functor.mapConst"),
95 univ_params: vec![],
96 ty,
97 })
98 .map_err(|e| e.to_string())
99}
100pub fn build_all_functor_decls(env: &mut Environment) -> Result<(), String> {
102 build_functor_env(env)?;
103 build_functor_map_const(env)?;
104 Ok(())
105}
106pub trait Functor<A> {
108 type Mapped<B>;
110 fn fmap<B, F: Fn(A) -> B>(self, f: F) -> Self::Mapped<B>;
112}
113pub fn fmap_option<A, B, F: Fn(A) -> B>(opt: Option<A>, f: F) -> Option<B> {
115 opt.map(f)
116}
117pub fn fmap_vec<A, B, F: Fn(A) -> B>(v: Vec<A>, f: F) -> Vec<B> {
119 v.into_iter().map(f).collect()
120}
121pub fn fmap_result<A, B, E, F: Fn(A) -> B>(r: Result<A, E>, f: F) -> Result<B, E> {
123 r.map(f)
124}
125pub fn make_fmap_expr(f_ty: Expr, map_fn: Expr, fa: Expr) -> Expr {
127 Expr::App(
128 Box::new(Expr::App(
129 Box::new(Expr::App(
130 Box::new(Expr::Const(Name::str("Functor.map"), vec![])),
131 Box::new(f_ty),
132 )),
133 Box::new(map_fn),
134 )),
135 Box::new(fa),
136 )
137}
138pub fn make_map_const_expr(f_ty: Expr, a: Expr, fb: Expr) -> Expr {
140 Expr::App(
141 Box::new(Expr::App(
142 Box::new(Expr::App(
143 Box::new(Expr::Const(Name::str("Functor.mapConst"), vec![])),
144 Box::new(f_ty),
145 )),
146 Box::new(a),
147 )),
148 Box::new(fb),
149 )
150}
151pub fn option_identity_law<A: Clone + PartialEq>(x: Option<A>) -> bool {
153 fmap_option(x.clone(), |a| a) == x
154}
155pub fn option_composition_law<A: Clone, B: Clone + PartialEq, C: PartialEq>(
157 x: Option<A>,
158 f: impl Fn(A) -> B + Clone,
159 g: impl Fn(B) -> C + Clone,
160) -> bool {
161 let f2 = f.clone();
162 let g2 = g.clone();
163 fmap_option(x.clone(), move |a| g(f(a))) == fmap_option(fmap_option(x, f2), g2)
164}
165pub fn vec_identity_law<A: Clone + PartialEq>(xs: Vec<A>) -> bool {
167 fmap_vec(xs.clone(), |a| a) == xs
168}
169pub fn fmap_option_vec<A, B, F: Fn(A) -> B>(opt_vec: Option<Vec<A>>, f: F) -> Option<Vec<B>> {
171 fmap_option(opt_vec, |v| fmap_vec(v, &f))
172}
173pub fn fmap_vec_option<A, B, F: Fn(A) -> B>(v: Vec<Option<A>>, f: F) -> Vec<Option<B>> {
175 fmap_vec(v, |opt| fmap_option(opt, &f))
176}
177pub fn fmap_vec_result<A, B, E, F: Fn(A) -> B>(v: Vec<Result<A, E>>, f: F) -> Vec<Result<B, E>> {
179 fmap_vec(v, |r| fmap_result(r, &f))
180}
181pub fn option_to_vec<A>(opt: Option<A>) -> Vec<A> {
183 match opt {
184 Some(a) => vec![a],
185 None => vec![],
186 }
187}
188pub fn vec_to_option<A>(v: Vec<A>) -> Option<A> {
190 v.into_iter().next()
191}
192pub fn join_option<A>(opt: Option<Option<A>>) -> Option<A> {
194 opt.flatten()
195}
196pub fn join_vec<A>(vv: Vec<Vec<A>>) -> Vec<A> {
198 vv.into_iter().flatten().collect()
199}
200pub fn ap_option<A, B, F: Fn(A) -> B>(f: Option<F>, a: Option<A>) -> Option<B> {
202 match (f, a) {
203 (Some(g), Some(x)) => Some(g(x)),
204 _ => None,
205 }
206}
207#[allow(clippy::redundant_closure)]
209pub fn ap_vec<A: Clone, B, F: Fn(A) -> B>(fs: Vec<F>, xs: Vec<A>) -> Vec<B> {
210 fs.into_iter()
211 .flat_map(|f| xs.iter().cloned().map(move |x| f(x)))
212 .collect()
213}
214pub fn bind_option<A, B, F: Fn(A) -> Option<B>>(opt: Option<A>, f: F) -> Option<B> {
216 opt.and_then(f)
217}
218pub fn bind_vec<A, B, F: Fn(A) -> Vec<B>>(v: Vec<A>, f: F) -> Vec<B> {
220 v.into_iter().flat_map(f).collect()
221}
222pub fn traverse_vec_option<A, B, F: Fn(A) -> Option<B>>(v: Vec<A>, f: F) -> Option<Vec<B>> {
224 v.into_iter().map(f).collect()
225}
226pub fn traverse_vec_result<A, B, E, F: Fn(A) -> Result<B, E>>(
228 v: Vec<A>,
229 f: F,
230) -> Result<Vec<B>, E> {
231 v.into_iter().map(f).collect()
232}
233pub fn fold_left_vec<A, B, F: Fn(B, &A) -> B>(v: &[A], init: B, f: F) -> B {
235 v.iter().fold(init, f)
236}
237pub fn fold_right_vec<A, B, F: Fn(&A, B) -> B>(v: &[A], init: B, f: F) -> B {
239 v.iter().rfold(init, |b, a| f(a, b))
240}
241pub fn count_elements<A>(v: &[A]) -> usize {
243 v.len()
244}
245pub fn sum_u64_slice(v: &[u64]) -> u64 {
247 v.iter().sum()
248}
249pub fn option_lift2<A, B, C, F: FnOnce(A, B) -> C>(f: F, a: Option<A>, b: Option<B>) -> Option<C> {
251 match (a, b) {
252 (Some(x), Some(y)) => Some(f(x, y)),
253 _ => None,
254 }
255}
256pub fn option_lift3<A, B, C, D, F: FnOnce(A, B, C) -> D>(
258 f: F,
259 a: Option<A>,
260 b: Option<B>,
261 c: Option<C>,
262) -> Option<D> {
263 match (a, b, c) {
264 (Some(x), Some(y), Some(z)) => Some(f(x, y, z)),
265 _ => None,
266 }
267}
268pub fn collect_somes<A: Clone>(opts: &[Option<A>]) -> Vec<A> {
270 opts.iter().filter_map(|o| o.clone()).collect()
271}
272pub fn count_somes<A>(opts: &[Option<A>]) -> usize {
274 opts.iter().filter(|o| o.is_some()).count()
275}
276pub fn zip_vecs<A: Clone, B: Clone>(a: &[A], b: &[B]) -> Vec<(A, B)> {
278 a.iter()
279 .zip(b.iter())
280 .map(|(x, y)| (x.clone(), y.clone()))
281 .collect()
282}
283pub fn unzip_pairs<A, B>(pairs: Vec<(A, B)>) -> (Vec<A>, Vec<B>) {
285 pairs.into_iter().unzip()
286}
287pub fn find_first<A, P: Fn(&A) -> bool>(v: &[A], pred: P) -> Option<&A> {
289 v.iter().find(|a| pred(a))
290}
291pub fn partition_by<A, P: Fn(&A) -> bool>(v: Vec<A>, pred: P) -> (Vec<A>, Vec<A>) {
293 v.into_iter().partition(|a| pred(a))
294}
295pub fn scan_left<A: Clone, B: Clone, F: Fn(B, &A) -> B>(v: &[A], init: B, f: F) -> Vec<B> {
297 let mut acc = init;
298 let mut result = vec![acc.clone()];
299 for a in v {
300 acc = f(acc, a);
301 result.push(acc.clone());
302 }
303 result
304}
305pub fn group_by_eq<A: PartialEq + Clone>(v: Vec<A>) -> Vec<Vec<A>> {
307 let mut result: Vec<Vec<A>> = Vec::new();
308 for item in v {
309 if let Some(last) = result.last_mut() {
310 if last.first() == Some(&item) {
311 last.push(item);
312 continue;
313 }
314 }
315 result.push(vec![item]);
316 }
317 result
318}
319pub fn interleave<A>(a: Vec<A>, b: Vec<A>) -> Vec<A> {
321 let mut result = Vec::new();
322 let mut ai = a.into_iter();
323 let mut bi = b.into_iter();
324 loop {
325 match (ai.next(), bi.next()) {
326 (Some(x), Some(y)) => {
327 result.push(x);
328 result.push(y);
329 }
330 (Some(x), None) => {
331 result.push(x);
332 result.extend(ai);
333 break;
334 }
335 (None, Some(y)) => {
336 result.push(y);
337 result.extend(bi);
338 break;
339 }
340 (None, None) => break,
341 }
342 }
343 result
344}
345pub fn rotate_left<A: Clone>(v: Vec<A>, n: usize) -> Vec<A> {
347 if v.is_empty() {
348 return v;
349 }
350 let n = n % v.len();
351 let mut result = v[n..].to_vec();
352 result.extend_from_slice(&v[..n]);
353 result
354}
355pub fn rotate_right<A: Clone>(v: Vec<A>, n: usize) -> Vec<A> {
357 if v.is_empty() {
358 return v;
359 }
360 let len = v.len();
361 let n = n % len;
362 rotate_left(v, len.wrapping_sub(n) % len)
363}
364pub fn dedup_stable<A: PartialEq + Clone>(v: Vec<A>) -> Vec<A> {
366 let mut result = Vec::new();
367 for item in v {
368 if !result.contains(&item) {
369 result.push(item);
370 }
371 }
372 result
373}
374#[cfg(test)]
375mod tests {
376 use super::*;
377 #[test]
378 fn test_build_functor_env() {
379 let mut env = Environment::new();
380 assert!(build_functor_env(&mut env).is_ok());
381 assert!(env.get(&Name::str("Functor")).is_some());
382 assert!(env.get(&Name::str("Functor.map")).is_some());
383 }
384 #[test]
385 fn test_build_all_functor_decls() {
386 let mut env = Environment::new();
387 assert!(build_all_functor_decls(&mut env).is_ok());
388 assert!(env.contains(&Name::str("Functor")));
389 assert!(env.contains(&Name::str("Functor.map")));
390 assert!(env.contains(&Name::str("Functor.mapConst")));
391 }
392 #[test]
393 fn test_fmap_option_some() {
394 assert_eq!(fmap_option(Some(3), |x| x * 2), Some(6));
395 }
396 #[test]
397 fn test_fmap_option_none() {
398 assert_eq!(fmap_option(None::<i32>, |x| x * 2), None);
399 }
400 #[test]
401 fn test_fmap_vec() {
402 assert_eq!(fmap_vec(vec![1i32, 2, 3], |x| x + 10), vec![11, 12, 13]);
403 }
404 #[test]
405 fn test_fmap_result_ok() {
406 assert_eq!(fmap_result(Ok::<i32, &str>(5), |x| x + 1), Ok(6));
407 }
408 #[test]
409 fn test_fmap_result_err() {
410 assert!(fmap_result(Err::<i32, &str>("bad"), |x| x + 1).is_err());
411 }
412 #[test]
413 fn test_option_identity_law() {
414 assert!(option_identity_law(Some(42)));
415 assert!(option_identity_law::<i32>(None));
416 }
417 #[test]
418 fn test_option_composition_law() {
419 assert!(option_composition_law(Some(3i32), |a| a + 1, |b| b * 2));
420 }
421 #[test]
422 fn test_vec_identity_law() {
423 assert!(vec_identity_law(vec![1i32, 2, 3]));
424 assert!(vec_identity_law::<i32>(vec![]));
425 }
426 #[test]
427 fn test_either_left_right() {
428 let l: Either<i32, &str> = Either::Left(1);
429 let r: Either<i32, &str> = Either::Right("hi");
430 assert!(l.is_left());
431 assert!(r.is_right());
432 }
433 #[test]
434 fn test_either_bimap() {
435 let e: Either<i32, &str> = Either::Left(2);
436 let m = e.bimap(|x| x + 1, |s: &str| s.len());
437 assert_eq!(m.unwrap_left(), 3);
438 }
439 #[test]
440 fn test_pred_contramap() {
441 let is_pos = Pred::new(|x: i32| x > 0);
442 let is_len_pos = is_pos.contramap(|s: &str| s.len() as i32);
443 assert!(is_len_pos.test("hello"));
444 assert!(!is_len_pos.test(""));
445 }
446 #[test]
447 fn test_fmap_option_vec() {
448 let v: Option<Vec<i32>> = Some(vec![1, 2, 3]);
449 assert_eq!(fmap_option_vec(v, |x| x * 2), Some(vec![2, 4, 6]));
450 }
451 #[test]
452 fn test_natural_transformations() {
453 assert_eq!(option_to_vec(Some(1)), vec![1]);
454 assert_eq!(option_to_vec::<i32>(None), vec![]);
455 assert_eq!(vec_to_option(vec![1, 2, 3]), Some(1));
456 }
457 #[test]
458 fn test_join_option() {
459 assert_eq!(join_option(Some(Some(42))), Some(42));
460 assert_eq!(join_option::<i32>(None), None);
461 }
462 #[test]
463 fn test_join_vec() {
464 assert_eq!(join_vec(vec![vec![1, 2], vec![3]]), vec![1, 2, 3]);
465 }
466 #[test]
467 fn test_ap_option() {
468 let f: Option<fn(i32) -> i32> = Some(|x| x + 1);
469 assert_eq!(ap_option(f, Some(5)), Some(6));
470 }
471 #[test]
472 fn test_bind_option() {
473 assert_eq!(
474 bind_option(Some(5), |x| if x > 3 { Some(x * 2) } else { None }),
475 Some(10)
476 );
477 }
478 #[test]
479 fn test_bind_vec() {
480 assert_eq!(
481 bind_vec(vec![1i32, 2], |x| vec![x, x * 10]),
482 vec![1, 10, 2, 20]
483 );
484 }
485 #[test]
486 fn test_traverse_vec_option() {
487 assert_eq!(
488 traverse_vec_option(vec![1i32, 2, 3], |x| if x > 0 { Some(x * 2) } else { None }),
489 Some(vec![2, 4, 6])
490 );
491 assert_eq!(
492 traverse_vec_option(vec![1i32, -1], |x| if x > 0 { Some(x) } else { None }),
493 None
494 );
495 }
496 #[test]
497 fn test_traverse_vec_result() {
498 let r: Result<Vec<i32>, _> = traverse_vec_result(vec!["1", "2"], |s| s.parse::<i32>());
499 assert_eq!(r, Ok(vec![1, 2]));
500 }
501 #[test]
502 fn test_fold_left_vec() {
503 assert_eq!(fold_left_vec(&[1u64, 2, 3], 0, |acc, x| acc + x), 6);
504 }
505 #[test]
506 fn test_option_lift2() {
507 assert_eq!(option_lift2(|a, b| a + b, Some(3i32), Some(4)), Some(7));
508 assert_eq!(option_lift2(|a: i32, b: i32| a + b, None, Some(4)), None);
509 }
510 #[test]
511 fn test_option_lift3() {
512 assert_eq!(
513 option_lift3(|a, b, c| a + b + c, Some(1i32), Some(2), Some(3)),
514 Some(6)
515 );
516 }
517 #[test]
518 fn test_collect_somes() {
519 let opts = vec![Some(1), None, Some(3), None];
520 assert_eq!(collect_somes(&opts), vec![1, 3]);
521 }
522 #[test]
523 fn test_zip_unzip() {
524 let pairs = zip_vecs(&[1i32, 2], &["a", "b"]);
525 assert_eq!(pairs, vec![(1, "a"), (2, "b")]);
526 let (a, b): (Vec<i32>, Vec<&str>) = unzip_pairs(pairs);
527 assert_eq!(a, vec![1, 2]);
528 assert_eq!(b, vec!["a", "b"]);
529 }
530 #[test]
531 fn test_find_first() {
532 let v = vec![1, 2, 3, 4, 5];
533 assert_eq!(find_first(&v, |x| *x > 3), Some(&4));
534 }
535 #[test]
536 fn test_partition_by() {
537 let v = vec![1i32, 2, 3, 4, 5];
538 let (evens, odds) = partition_by(v, |x| x % 2 == 0);
539 assert_eq!(evens, vec![2, 4]);
540 assert_eq!(odds, vec![1, 3, 5]);
541 }
542 #[test]
543 fn test_scan_left() {
544 let v = vec![1u64, 2, 3, 4];
545 let scanned = scan_left(&v, 0u64, |acc, x| acc + x);
546 assert_eq!(scanned, vec![0, 1, 3, 6, 10]);
547 }
548 #[test]
549 fn test_rotate_left() {
550 assert_eq!(rotate_left(vec![1, 2, 3, 4, 5], 2), vec![3, 4, 5, 1, 2]);
551 }
552 #[test]
553 fn test_dedup_stable() {
554 assert_eq!(dedup_stable(vec![1, 2, 1, 3, 2]), vec![1, 2, 3]);
555 }
556 #[test]
557 fn test_interleave() {
558 assert_eq!(
559 interleave(vec![1, 3, 5], vec![2, 4, 6]),
560 vec![1, 2, 3, 4, 5, 6]
561 );
562 }
563 #[test]
564 fn test_make_fmap_expr() {
565 let result = make_fmap_expr(
566 Expr::Sort(Level::zero()),
567 Expr::Sort(Level::zero()),
568 Expr::Sort(Level::zero()),
569 );
570 assert!(matches!(result, Expr::App(_, _)));
571 }
572 #[test]
573 fn test_option_functor_wrapper() {
574 let of = OptionFunctor(Some(5i32));
575 let mapped = of.fmap(|x| x.to_string());
576 assert_eq!(mapped.0, Some("5".to_string()));
577 }
578 #[test]
579 fn test_vec_functor_wrapper() {
580 let vf = VecFunctor(vec![1i32, 2, 3]);
581 let mapped = vf.fmap(|x| x * x);
582 assert_eq!(mapped.0, vec![1, 4, 9]);
583 }
584 #[test]
585 fn test_result_functor_wrapper() {
586 let rf: ResultFunctor<i32, &str> = ResultFunctor(Ok(7));
587 let mapped = rf.fmap(|x| x + 1);
588 assert_eq!(mapped.0, Ok(8));
589 }
590}
591pub fn tap<A, F: FnMut(&A)>(v: A, mut f: F) -> A {
593 f(&v);
594 v
595}
596pub fn tap_option<A, F: Fn(&A)>(opt: Option<A>, f: F) -> Option<A> {
598 if let Some(ref v) = opt {
599 f(v);
600 }
601 opt
602}
603pub fn tap_vec<A, F: Fn(&A)>(v: Vec<A>, f: F) -> Vec<A> {
605 for x in &v {
606 f(x);
607 }
608 v
609}
610pub fn iterate_while<A: Clone, F: Fn(A) -> A, P: Fn(&A) -> bool>(mut x: A, f: F, p: P) -> A {
612 while p(&x) {
613 x = f(x);
614 }
615 x
616}
617pub fn generate_vec<A: Clone, F: Fn(A) -> A>(seed: A, f: F, n: usize) -> Vec<A> {
619 let mut result = vec![seed.clone()];
620 let mut cur = seed;
621 for _ in 0..n {
622 cur = f(cur);
623 result.push(cur.clone());
624 }
625 result
626}
627pub fn iterate_n<A, F: Fn(A) -> A>(mut x: A, f: F, n: usize) -> A {
629 for _ in 0..n {
630 x = f(x);
631 }
632 x
633}
634pub fn memoize_vec<A: Clone, F: Fn(usize) -> A>(f: F, n: usize) -> Vec<A> {
636 (0..n).map(f).collect()
637}
638pub fn compose<A, B, C, F: Fn(A) -> B, G: Fn(B) -> C>(f: F, g: G) -> impl Fn(A) -> C {
640 move |a| g(f(a))
641}
642pub fn compose3<A, B, C, D, F: Fn(A) -> B, G: Fn(B) -> C, H: Fn(C) -> D>(
644 f: F,
645 g: G,
646 h: H,
647) -> impl Fn(A) -> D {
648 move |a| h(g(f(a)))
649}
650pub fn identity<A>(a: A) -> A {
652 a
653}
654pub fn constant<A: Clone, B>(a: A) -> impl Fn(B) -> A {
656 move |_| a.clone()
657}
658pub fn flip2<A, B, C, F: Fn(A, B) -> C>(f: F) -> impl Fn(B, A) -> C {
660 move |b, a| f(a, b)
661}
662pub fn apply_if<A, F: Fn(A) -> A>(cond: bool, a: A, f: F) -> A {
664 if cond {
665 f(a)
666 } else {
667 a
668 }
669}
670pub fn map_where<A, F: Fn(A) -> A, P: Fn(&A) -> bool>(v: Vec<A>, pred: P, f: F) -> Vec<A> {
672 v.into_iter()
673 .map(|x| if pred(&x) { f(x) } else { x })
674 .collect()
675}
676pub fn split_at_pred<A, P: Fn(&A) -> bool>(v: Vec<A>, pred: P) -> (Vec<A>, Vec<A>) {
678 let pos = v.iter().position(pred).unwrap_or(v.len());
679 let mut right = v;
680 let left = right.drain(..pos).collect();
681 (left, right)
682}
683pub fn flatten_opt_vec<A>(opt: Option<Vec<A>>) -> Vec<A> {
685 opt.unwrap_or_default()
686}
687pub fn flatten_vec_opt<A>(v: Vec<Option<A>>) -> Vec<A> {
689 v.into_iter().flatten().collect()
690}
691pub fn chunk<A: Clone>(v: Vec<A>, n: usize) -> Vec<Vec<A>> {
693 if n == 0 {
694 return vec![];
695 }
696 v.chunks(n).map(|c| c.to_vec()).collect()
697}
698pub fn windows<A: Clone>(v: &[A], n: usize) -> Vec<Vec<A>> {
700 v.windows(n).map(|w| w.to_vec()).collect()
701}
702pub fn transpose<A: Clone>(vv: Vec<Vec<A>>) -> Vec<Vec<A>> {
704 if vv.is_empty() {
705 return vec![];
706 }
707 let n = vv[0].len();
708 (0..n)
709 .map(|i| vv.iter().filter_map(|row| row.get(i)).cloned().collect())
710 .collect()
711}
712pub fn map_indexed<A, B, F: Fn(usize, A) -> B>(v: Vec<A>, f: F) -> Vec<B> {
714 v.into_iter().enumerate().map(|(i, a)| f(i, a)).collect()
715}
716pub fn flat_map_indexed<A, B, F: Fn(usize, A) -> Vec<B>>(v: Vec<A>, f: F) -> Vec<B> {
718 v.into_iter()
719 .enumerate()
720 .flat_map(|(i, a)| f(i, a))
721 .collect()
722}
723pub fn filter_indexed<A, P: Fn(usize, &A) -> bool>(v: Vec<A>, pred: P) -> Vec<A> {
725 v.into_iter()
726 .enumerate()
727 .filter(|(i, a)| pred(*i, a))
728 .map(|(_, a)| a)
729 .collect()
730}
731pub fn replicate<A: Clone>(n: usize, a: A) -> Vec<A> {
733 vec![a; n]
734}
735pub fn take_while<A, P: Fn(&A) -> bool>(v: Vec<A>, pred: P) -> Vec<A> {
737 v.into_iter().take_while(|a| pred(a)).collect()
738}
739pub fn drop_while<A, P: Fn(&A) -> bool>(v: Vec<A>, pred: P) -> Vec<A> {
741 v.into_iter().skip_while(|a| pred(a)).collect()
742}
743pub fn span<A, P: Fn(&A) -> bool>(v: Vec<A>, pred: P) -> (Vec<A>, Vec<A>) {
745 let pos = v.iter().position(|a| !pred(a)).unwrap_or(v.len());
746 let mut right = v;
747 let left = right.drain(..pos).collect();
748 (left, right)
749}
750#[cfg(test)]
751mod extra_tests {
752 use super::*;
753 #[test]
754 fn test_tap() {
755 let mut side = 0;
756 let v = tap(42, |x| {
757 let _ = x;
758 side = 1;
759 });
760 assert_eq!(v, 42);
761 assert_eq!(side, 1);
762 }
763 #[test]
764 fn test_iterate_while() {
765 let result = iterate_while(1u32, |x| x * 2, |x| *x < 100);
766 assert!(result >= 100);
767 }
768 #[test]
769 fn test_generate_vec() {
770 let v = generate_vec(1u64, |x| x * 2, 4);
771 assert_eq!(v, vec![1, 2, 4, 8, 16]);
772 }
773 #[test]
774 fn test_iterate_n() {
775 let result = iterate_n(1u64, |x| x * 2, 10);
776 assert_eq!(result, 1024);
777 }
778 #[test]
779 fn test_compose() {
780 let f = compose(|x: i32| x + 1, |x: i32| x * 2);
781 assert_eq!(f(3), 8);
782 }
783 #[test]
784 fn test_compose3() {
785 let f = compose3(|x: i32| x + 1, |x: i32| x * 2, |x: i32| x - 1);
786 assert_eq!(f(3), 7);
787 }
788 #[test]
789 fn test_identity() {
790 assert_eq!(identity(42), 42);
791 assert_eq!(identity("hello"), "hello");
792 }
793 #[test]
794 fn test_constant() {
795 let always5 = constant(5i32);
796 assert_eq!(always5("anything"), 5);
797 assert_eq!(always5("any"), 5);
798 }
799 #[test]
800 fn test_flip2() {
801 let sub = |a: i32, b: i32| a - b;
802 let flipped = flip2(sub);
803 assert_eq!(flipped(1, 10), 9);
804 }
805 #[test]
806 fn test_apply_if_true() {
807 let result = apply_if(true, 5, |x| x * 2);
808 assert_eq!(result, 10);
809 }
810 #[test]
811 fn test_apply_if_false() {
812 let result = apply_if(false, 5, |x| x * 2);
813 assert_eq!(result, 5);
814 }
815 #[test]
816 fn test_map_where() {
817 let v = vec![1i32, 2, 3, 4, 5];
818 let result = map_where(v, |x| *x % 2 == 0, |x| x * 10);
819 assert_eq!(result, vec![1, 20, 3, 40, 5]);
820 }
821 #[test]
822 fn test_flatten_opt_vec() {
823 assert_eq!(flatten_opt_vec(Some(vec![1, 2, 3])), vec![1, 2, 3]);
824 assert_eq!(flatten_opt_vec::<i32>(None), vec![]);
825 }
826 #[test]
827 fn test_flatten_vec_opt() {
828 let v = vec![Some(1), None, Some(3)];
829 assert_eq!(flatten_vec_opt(v), vec![1, 3]);
830 }
831 #[test]
832 fn test_chunk() {
833 let v = vec![1, 2, 3, 4, 5];
834 assert_eq!(chunk(v, 2), vec![vec![1, 2], vec![3, 4], vec![5]]);
835 }
836 #[test]
837 fn test_windows() {
838 let v = vec![1, 2, 3, 4];
839 assert_eq!(windows(&v, 2), vec![vec![1, 2], vec![2, 3], vec![3, 4]]);
840 }
841 #[test]
842 fn test_transpose() {
843 let vv = vec![vec![1, 2, 3], vec![4, 5, 6]];
844 let t = transpose(vv);
845 assert_eq!(t, vec![vec![1, 4], vec![2, 5], vec![3, 6]]);
846 }
847 #[test]
848 fn test_map_indexed() {
849 let v = vec!["a", "b", "c"];
850 let result = map_indexed(v, |i, s| format!("{}{}", i, s));
851 assert_eq!(result, vec!["0a", "1b", "2c"]);
852 }
853 #[test]
854 fn test_replicate() {
855 assert_eq!(replicate(4, 0i32), vec![0, 0, 0, 0]);
856 }
857 #[test]
858 fn test_take_while() {
859 let v = vec![1, 2, 3, 4, 5];
860 assert_eq!(take_while(v, |x| *x < 4), vec![1, 2, 3]);
861 }
862 #[test]
863 fn test_drop_while() {
864 let v = vec![1, 2, 3, 4, 5];
865 assert_eq!(drop_while(v, |x| *x < 4), vec![4, 5]);
866 }
867 #[test]
868 fn test_span() {
869 let v = vec![1, 2, 3, 4, 5];
870 let (left, right) = span(v, |x| *x < 4);
871 assert_eq!(left, vec![1, 2, 3]);
872 assert_eq!(right, vec![4, 5]);
873 }
874 #[test]
875 fn test_memoize_vec() {
876 let cached = memoize_vec(|i| i * i, 5);
877 assert_eq!(cached, vec![0, 1, 4, 9, 16]);
878 }
879}
880pub trait Foldable<A> {
885 fn fold_left<B>(self, init: B, f: impl Fn(B, A) -> B) -> B;
887 fn fold_right<B>(self, init: B, f: impl Fn(A, B) -> B) -> B;
889 fn length(self) -> usize
891 where
892 Self: Sized,
893 A: Clone,
894 {
895 self.fold_left(0, |acc, _| acc + 1)
896 }
897 fn any<F: Fn(&A) -> bool>(self, pred: F) -> bool
899 where
900 Self: Sized,
901 A: Clone,
902 {
903 self.fold_left(false, |acc, x| acc || pred(&x))
904 }
905 fn all<F: Fn(&A) -> bool>(self, pred: F) -> bool
907 where
908 Self: Sized,
909 A: Clone,
910 {
911 self.fold_left(true, |acc, x| acc && pred(&x))
912 }
913}
914impl<A: Clone> Foldable<A> for Vec<A> {
915 fn fold_left<B>(self, init: B, f: impl Fn(B, A) -> B) -> B {
916 self.into_iter().fold(init, f)
917 }
918 fn fold_right<B>(self, init: B, f: impl Fn(A, B) -> B) -> B {
919 self.into_iter().rev().fold(init, |acc, x| f(x, acc))
920 }
921}
922pub trait Traversable<A, B, E> {
927 type Output;
929 fn traverse(self, f: impl Fn(A) -> Result<B, E>) -> Result<Self::Output, E>;
931}
932impl<A, B, E> Traversable<A, B, E> for Vec<A> {
933 type Output = Vec<B>;
934 fn traverse(self, f: impl Fn(A) -> Result<B, E>) -> Result<Vec<B>, E> {
935 let mut result = Vec::with_capacity(self.len());
936 for item in self {
937 result.push(f(item)?);
938 }
939 Ok(result)
940 }
941}
942#[cfg(test)]
943mod extra_functor_tests {
944 use super::*;
945 #[test]
946 fn test_foldable_fold_left() {
947 let v = vec![1i32, 2, 3, 4, 5];
948 let sum = v.fold_left(0i32, |acc, x| acc + x);
949 assert_eq!(sum, 15);
950 }
951 #[test]
952 fn test_foldable_fold_right() {
953 let v = vec![1i32, 2, 3];
954 let result = v.fold_right(Vec::<i32>::new(), |x, mut acc| {
955 acc.insert(0, x);
956 acc
957 });
958 assert_eq!(result, vec![1, 2, 3]);
959 }
960 #[test]
961 fn test_foldable_any_true() {
962 let v = vec![1i32, 2, 3];
963 assert!(v.any(|x| *x == 2));
964 }
965 #[test]
966 fn test_foldable_any_false() {
967 let v = vec![1i32, 2, 3];
968 assert!(!v.any(|x| *x == 99));
969 }
970 #[test]
971 fn test_foldable_all_true() {
972 let v = vec![2i32, 4, 6];
973 assert!(v.all(|x| *x % 2 == 0));
974 }
975 #[test]
976 fn test_foldable_all_false() {
977 let v = vec![2i32, 3, 6];
978 assert!(!v.all(|x| *x % 2 == 0));
979 }
980 #[test]
981 fn test_traversable_ok() {
982 let v = vec![1i32, 2, 3];
983 let result: Result<Vec<i32>, &str> = v.traverse(|x| Ok(x * 2));
984 assert_eq!(result, Ok(vec![2, 4, 6]));
985 }
986 #[test]
987 fn test_traversable_err() {
988 let v = vec![1i32, 0, 3];
989 let result: Result<Vec<i32>, &str> =
990 v.traverse(|x| if x != 0 { Ok(x * 2) } else { Err("zero") });
991 assert_eq!(result, Err("zero"));
992 }
993 #[test]
994 fn test_reader_run() {
995 let r: Reader<i32, i32> = Reader::new(|env| env * 2);
996 assert_eq!(r.run_reader(5), 10);
997 }
998 #[test]
999 fn test_reader_map() {
1000 let r: Reader<i32, i32> = Reader::new(|env| env + 1);
1001 let r2 = r.map(|x| x * 3);
1002 assert_eq!(r2.run_reader(4), 15);
1003 }
1004 #[test]
1005 fn test_reader_pure() {
1006 let r: Reader<i32, i32> = Reader::pure(42);
1007 assert_eq!(r.run_reader(999), 42);
1008 }
1009 #[test]
1010 fn test_writer_run() {
1011 let w: Writer<i32, Vec<String>> = Writer::new(42, vec!["logged".to_string()]);
1012 let (v, log) = w.run();
1013 assert_eq!(v, 42);
1014 assert_eq!(log, vec!["logged".to_string()]);
1015 }
1016 #[test]
1017 fn test_writer_pure() {
1018 let w: Writer<i32, Vec<String>> = Writer::pure(7);
1019 assert_eq!(w.get_value(), 7);
1020 }
1021}
1022pub fn ftr_ext_identity_law_ty() -> Expr {
1023 let type1 = Expr::Sort(Level::succ(Level::zero()));
1024 Expr::Pi(
1025 BinderInfo::Default,
1026 Name::str("f_alpha"),
1027 Box::new(type1.clone()),
1028 Box::new(type1),
1029 )
1030}
1031pub fn ftr_ext_composition_law_ty() -> Expr {
1032 let type1 = Expr::Sort(Level::succ(Level::zero()));
1033 Expr::Pi(
1034 BinderInfo::Default,
1035 Name::str("f_alpha"),
1036 Box::new(type1.clone()),
1037 Box::new(type1),
1038 )
1039}
1040pub fn ftr_ext_naturality_ty() -> Expr {
1041 let type1 = Expr::Sort(Level::succ(Level::zero()));
1042 Expr::Pi(
1043 BinderInfo::Default,
1044 Name::str("nat_ty"),
1045 Box::new(type1.clone()),
1046 Box::new(type1),
1047 )
1048}
1049pub fn ftr_ext_list_identity_ty() -> Expr {
1050 let type1 = Expr::Sort(Level::succ(Level::zero()));
1051 Expr::Pi(
1052 BinderInfo::Default,
1053 Name::str("list_a"),
1054 Box::new(Expr::App(
1055 Box::new(Expr::Const(Name::str("List"), vec![])),
1056 Box::new(type1.clone()),
1057 )),
1058 Box::new(Expr::App(
1059 Box::new(Expr::Const(Name::str("List"), vec![])),
1060 Box::new(type1),
1061 )),
1062 )
1063}
1064pub fn ftr_ext_list_composition_ty() -> Expr {
1065 let type1 = Expr::Sort(Level::succ(Level::zero()));
1066 Expr::Pi(
1067 BinderInfo::Default,
1068 Name::str("list_compose"),
1069 Box::new(type1.clone()),
1070 Box::new(type1),
1071 )
1072}
1073pub fn ftr_ext_option_identity_ty() -> Expr {
1074 let type1 = Expr::Sort(Level::succ(Level::zero()));
1075 Expr::Pi(
1076 BinderInfo::Default,
1077 Name::str("opt_id"),
1078 Box::new(Expr::App(
1079 Box::new(Expr::Const(Name::str("Option"), vec![])),
1080 Box::new(type1.clone()),
1081 )),
1082 Box::new(Expr::App(
1083 Box::new(Expr::Const(Name::str("Option"), vec![])),
1084 Box::new(type1),
1085 )),
1086 )
1087}
1088pub fn ftr_ext_option_composition_ty() -> Expr {
1089 let type1 = Expr::Sort(Level::succ(Level::zero()));
1090 Expr::Pi(
1091 BinderInfo::Default,
1092 Name::str("opt_comp"),
1093 Box::new(type1.clone()),
1094 Box::new(type1),
1095 )
1096}
1097pub fn ftr_ext_result_identity_ty() -> Expr {
1098 let type1 = Expr::Sort(Level::succ(Level::zero()));
1099 Expr::Pi(
1100 BinderInfo::Default,
1101 Name::str("res_id"),
1102 Box::new(type1.clone()),
1103 Box::new(type1),
1104 )
1105}
1106pub fn ftr_ext_pair_fmap_ty() -> Expr {
1107 let type1 = Expr::Sort(Level::succ(Level::zero()));
1108 Expr::Pi(
1109 BinderInfo::Default,
1110 Name::str("pair_fmap"),
1111 Box::new(type1.clone()),
1112 Box::new(type1),
1113 )
1114}
1115pub fn ftr_ext_bifunctor_identity_ty() -> Expr {
1116 let type1 = Expr::Sort(Level::succ(Level::zero()));
1117 Expr::Pi(
1118 BinderInfo::Default,
1119 Name::str("bimap_id"),
1120 Box::new(type1.clone()),
1121 Box::new(type1),
1122 )
1123}
1124pub fn ftr_ext_bifunctor_composition_ty() -> Expr {
1125 let type1 = Expr::Sort(Level::succ(Level::zero()));
1126 Expr::Pi(
1127 BinderInfo::Default,
1128 Name::str("bimap_comp"),
1129 Box::new(type1.clone()),
1130 Box::new(type1),
1131 )
1132}
1133pub fn ftr_ext_contramap_identity_ty() -> Expr {
1134 let type1 = Expr::Sort(Level::succ(Level::zero()));
1135 Expr::Pi(
1136 BinderInfo::Default,
1137 Name::str("cmap_id"),
1138 Box::new(type1.clone()),
1139 Box::new(type1),
1140 )
1141}
1142pub fn ftr_ext_contramap_composition_ty() -> Expr {
1143 let type1 = Expr::Sort(Level::succ(Level::zero()));
1144 Expr::Pi(
1145 BinderInfo::Default,
1146 Name::str("cmap_comp"),
1147 Box::new(type1.clone()),
1148 Box::new(type1),
1149 )
1150}
1151pub fn ftr_ext_profunctor_identity_ty() -> Expr {
1152 let type1 = Expr::Sort(Level::succ(Level::zero()));
1153 Expr::Pi(
1154 BinderInfo::Default,
1155 Name::str("dimap_id"),
1156 Box::new(type1.clone()),
1157 Box::new(type1),
1158 )
1159}
1160pub fn ftr_ext_profunctor_composition_ty() -> Expr {
1161 let type1 = Expr::Sort(Level::succ(Level::zero()));
1162 Expr::Pi(
1163 BinderInfo::Default,
1164 Name::str("dimap_comp"),
1165 Box::new(type1.clone()),
1166 Box::new(type1),
1167 )
1168}
1169pub fn ftr_ext_ap_identity_ty() -> Expr {
1170 let type1 = Expr::Sort(Level::succ(Level::zero()));
1171 Expr::Pi(
1172 BinderInfo::Default,
1173 Name::str("ap_id"),
1174 Box::new(type1.clone()),
1175 Box::new(type1),
1176 )
1177}
1178pub fn ftr_ext_ap_homomorphism_ty() -> Expr {
1179 let type1 = Expr::Sort(Level::succ(Level::zero()));
1180 Expr::Pi(
1181 BinderInfo::Default,
1182 Name::str("ap_hom"),
1183 Box::new(type1.clone()),
1184 Box::new(type1),
1185 )
1186}
1187pub fn ftr_ext_ap_interchange_ty() -> Expr {
1188 let type1 = Expr::Sort(Level::succ(Level::zero()));
1189 Expr::Pi(
1190 BinderInfo::Default,
1191 Name::str("ap_interchange"),
1192 Box::new(type1.clone()),
1193 Box::new(type1),
1194 )
1195}
1196pub fn ftr_ext_ap_composition_ty() -> Expr {
1197 let type1 = Expr::Sort(Level::succ(Level::zero()));
1198 Expr::Pi(
1199 BinderInfo::Default,
1200 Name::str("ap_comp"),
1201 Box::new(type1.clone()),
1202 Box::new(type1),
1203 )
1204}
1205pub fn ftr_ext_monoidal_unit_ty() -> Expr {
1206 let type1 = Expr::Sort(Level::succ(Level::zero()));
1207 Expr::Pi(
1208 BinderInfo::Default,
1209 Name::str("mono_unit"),
1210 Box::new(type1.clone()),
1211 Box::new(type1),
1212 )
1213}
1214pub fn ftr_ext_monoidal_zip_ty() -> Expr {
1215 let type1 = Expr::Sort(Level::succ(Level::zero()));
1216 Expr::Pi(
1217 BinderInfo::Default,
1218 Name::str("mono_zip"),
1219 Box::new(type1.clone()),
1220 Box::new(type1),
1221 )
1222}
1223pub fn ftr_ext_strong_first_ty() -> Expr {
1224 let type1 = Expr::Sort(Level::succ(Level::zero()));
1225 Expr::Pi(
1226 BinderInfo::Default,
1227 Name::str("strong_first"),
1228 Box::new(type1.clone()),
1229 Box::new(type1),
1230 )
1231}
1232pub fn ftr_ext_strong_second_ty() -> Expr {
1233 let type1 = Expr::Sort(Level::succ(Level::zero()));
1234 Expr::Pi(
1235 BinderInfo::Default,
1236 Name::str("strong_second"),
1237 Box::new(type1.clone()),
1238 Box::new(type1),
1239 )
1240}
1241pub fn ftr_ext_cartesian_copy_ty() -> Expr {
1242 let type1 = Expr::Sort(Level::succ(Level::zero()));
1243 Expr::Pi(
1244 BinderInfo::Default,
1245 Name::str("cartesian_copy"),
1246 Box::new(type1.clone()),
1247 Box::new(type1),
1248 )
1249}
1250pub fn ftr_ext_cartesian_delete_ty() -> Expr {
1251 let type1 = Expr::Sort(Level::succ(Level::zero()));
1252 Expr::Pi(
1253 BinderInfo::Default,
1254 Name::str("cartesian_delete"),
1255 Box::new(type1.clone()),
1256 Box::new(type1),
1257 )
1258}
1259pub fn ftr_ext_closed_apply_ty() -> Expr {
1260 let type1 = Expr::Sort(Level::succ(Level::zero()));
1261 Expr::Pi(
1262 BinderInfo::Default,
1263 Name::str("closed_apply"),
1264 Box::new(type1.clone()),
1265 Box::new(type1),
1266 )
1267}
1268pub fn ftr_ext_closed_curry_ty() -> Expr {
1269 let type1 = Expr::Sort(Level::succ(Level::zero()));
1270 Expr::Pi(
1271 BinderInfo::Default,
1272 Name::str("closed_curry"),
1273 Box::new(type1.clone()),
1274 Box::new(type1),
1275 )
1276}
1277pub fn ftr_ext_traverse_identity_ty() -> Expr {
1278 let type1 = Expr::Sort(Level::succ(Level::zero()));
1279 Expr::Pi(
1280 BinderInfo::Default,
1281 Name::str("trav_id"),
1282 Box::new(type1.clone()),
1283 Box::new(type1),
1284 )
1285}
1286pub fn ftr_ext_traverse_composition_ty() -> Expr {
1287 let type1 = Expr::Sort(Level::succ(Level::zero()));
1288 Expr::Pi(
1289 BinderInfo::Default,
1290 Name::str("trav_comp"),
1291 Box::new(type1.clone()),
1292 Box::new(type1),
1293 )
1294}
1295pub fn ftr_ext_fold_consistent_ty() -> Expr {
1296 let type1 = Expr::Sort(Level::succ(Level::zero()));
1297 Expr::Pi(
1298 BinderInfo::Default,
1299 Name::str("fold_consist"),
1300 Box::new(type1.clone()),
1301 Box::new(type1),
1302 )
1303}
1304pub fn ftr_ext_foldmap_morphism_ty() -> Expr {
1305 let type1 = Expr::Sort(Level::succ(Level::zero()));
1306 Expr::Pi(
1307 BinderInfo::Default,
1308 Name::str("foldmap_morph"),
1309 Box::new(type1.clone()),
1310 Box::new(type1),
1311 )
1312}
1313pub fn ftr_ext_representable_tabulate_ty() -> Expr {
1314 let type1 = Expr::Sort(Level::succ(Level::zero()));
1315 Expr::Pi(
1316 BinderInfo::Default,
1317 Name::str("rep_tab"),
1318 Box::new(type1.clone()),
1319 Box::new(type1),
1320 )
1321}
1322pub fn ftr_ext_representable_index_ty() -> Expr {
1323 let type1 = Expr::Sort(Level::succ(Level::zero()));
1324 Expr::Pi(
1325 BinderInfo::Default,
1326 Name::str("rep_idx"),
1327 Box::new(type1.clone()),
1328 Box::new(type1),
1329 )
1330}
1331pub fn ftr_ext_kan_left_ty() -> Expr {
1332 let type1 = Expr::Sort(Level::succ(Level::zero()));
1333 let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
1334 Expr::Pi(
1335 BinderInfo::Default,
1336 Name::str("lan_k"),
1337 Box::new(type2),
1338 Box::new(type1),
1339 )
1340}
1341pub fn ftr_ext_kan_right_ty() -> Expr {
1342 let type1 = Expr::Sort(Level::succ(Level::zero()));
1343 let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
1344 Expr::Pi(
1345 BinderInfo::Default,
1346 Name::str("ran_k"),
1347 Box::new(type2),
1348 Box::new(type1),
1349 )
1350}
1351pub fn ftr_ext_day_conv_unit_ty() -> Expr {
1352 let type1 = Expr::Sort(Level::succ(Level::zero()));
1353 Expr::Pi(
1354 BinderInfo::Default,
1355 Name::str("day_unit"),
1356 Box::new(type1.clone()),
1357 Box::new(type1),
1358 )
1359}
1360pub fn ftr_ext_day_conv_assoc_ty() -> Expr {
1361 let type1 = Expr::Sort(Level::succ(Level::zero()));
1362 Expr::Pi(
1363 BinderInfo::Default,
1364 Name::str("day_assoc"),
1365 Box::new(type1.clone()),
1366 Box::new(type1),
1367 )
1368}
1369pub fn ftr_ext_compose_identity_ty() -> Expr {
1370 let type1 = Expr::Sort(Level::succ(Level::zero()));
1371 Expr::Pi(
1372 BinderInfo::Default,
1373 Name::str("fcomp_id"),
1374 Box::new(type1.clone()),
1375 Box::new(type1),
1376 )
1377}
1378pub fn ftr_ext_compose_assoc_ty() -> Expr {
1379 let type1 = Expr::Sort(Level::succ(Level::zero()));
1380 Expr::Pi(
1381 BinderInfo::Default,
1382 Name::str("fcomp_assoc"),
1383 Box::new(type1.clone()),
1384 Box::new(type1),
1385 )
1386}
1387pub fn ftr_ext_nat_trans_id_ty() -> Expr {
1388 let type1 = Expr::Sort(Level::succ(Level::zero()));
1389 Expr::Pi(
1390 BinderInfo::Default,
1391 Name::str("nat_trans_id"),
1392 Box::new(type1.clone()),
1393 Box::new(type1),
1394 )
1395}
1396pub fn ftr_ext_nat_trans_comp_ty() -> Expr {
1397 let type1 = Expr::Sort(Level::succ(Level::zero()));
1398 Expr::Pi(
1399 BinderInfo::Default,
1400 Name::str("nat_trans_comp"),
1401 Box::new(type1.clone()),
1402 Box::new(type1),
1403 )
1404}
1405pub fn ftr_ext_adjunction_unit_ty() -> Expr {
1406 let type1 = Expr::Sort(Level::succ(Level::zero()));
1407 Expr::Pi(
1408 BinderInfo::Default,
1409 Name::str("adj_unit"),
1410 Box::new(type1.clone()),
1411 Box::new(type1),
1412 )
1413}
1414pub fn ftr_ext_adjunction_counit_ty() -> Expr {
1415 let type1 = Expr::Sort(Level::succ(Level::zero()));
1416 Expr::Pi(
1417 BinderInfo::Default,
1418 Name::str("adj_counit"),
1419 Box::new(type1.clone()),
1420 Box::new(type1),
1421 )
1422}
1423pub fn ftr_ext_adjunction_triangle_ty() -> Expr {
1424 let type1 = Expr::Sort(Level::succ(Level::zero()));
1425 Expr::Pi(
1426 BinderInfo::Default,
1427 Name::str("adj_triangle"),
1428 Box::new(type1.clone()),
1429 Box::new(type1),
1430 )
1431}
1432pub fn ftr_ext_functor_cat_obj_ty() -> Expr {
1433 let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
1434 Expr::Pi(
1435 BinderInfo::Default,
1436 Name::str("fcat_obj"),
1437 Box::new(type2.clone()),
1438 Box::new(type2),
1439 )
1440}
1441pub fn ftr_ext_functor_cat_mor_ty() -> Expr {
1442 let type1 = Expr::Sort(Level::succ(Level::zero()));
1443 Expr::Pi(
1444 BinderInfo::Default,
1445 Name::str("fcat_mor"),
1446 Box::new(type1.clone()),
1447 Box::new(type1),
1448 )
1449}
1450pub fn ftr_ext_presheaf_ty() -> Expr {
1451 let type1 = Expr::Sort(Level::succ(Level::zero()));
1452 let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
1453 Expr::Pi(
1454 BinderInfo::Default,
1455 Name::str("presheaf"),
1456 Box::new(type2),
1457 Box::new(type1),
1458 )
1459}
1460pub fn ftr_ext_yoneda_lemma_ty() -> Expr {
1461 let type1 = Expr::Sort(Level::succ(Level::zero()));
1462 Expr::Pi(
1463 BinderInfo::Default,
1464 Name::str("yoneda"),
1465 Box::new(type1.clone()),
1466 Box::new(type1),
1467 )
1468}
1469pub fn ftr_ext_yoneda_embedding_ty() -> Expr {
1470 let type1 = Expr::Sort(Level::succ(Level::zero()));
1471 let type2 = Expr::Sort(Level::succ(Level::succ(Level::zero())));
1472 Expr::Pi(
1473 BinderInfo::Default,
1474 Name::str("yoneda_embed"),
1475 Box::new(type1),
1476 Box::new(type2),
1477 )
1478}
1479pub fn ftr_ext_sheaf_gluing_ty() -> Expr {
1480 let type1 = Expr::Sort(Level::succ(Level::zero()));
1481 Expr::Pi(
1482 BinderInfo::Default,
1483 Name::str("sheaf_glue"),
1484 Box::new(type1.clone()),
1485 Box::new(type1),
1486 )
1487}
1488pub fn ftr_ext_sheaf_locality_ty() -> Expr {
1489 let type1 = Expr::Sort(Level::succ(Level::zero()));
1490 Expr::Pi(
1491 BinderInfo::Default,
1492 Name::str("sheaf_local"),
1493 Box::new(type1.clone()),
1494 Box::new(type1),
1495 )
1496}
1497pub fn ftr_ext_fmap_preserves_eq_ty() -> Expr {
1498 let type1 = Expr::Sort(Level::succ(Level::zero()));
1499 Expr::Pi(
1500 BinderInfo::Default,
1501 Name::str("fmap_eq"),
1502 Box::new(type1.clone()),
1503 Box::new(type1),
1504 )
1505}
1506pub fn ftr_ext_free_functor_ty() -> Expr {
1507 let type1 = Expr::Sort(Level::succ(Level::zero()));
1508 Expr::Pi(
1509 BinderInfo::Default,
1510 Name::str("free_functor"),
1511 Box::new(type1.clone()),
1512 Box::new(type1),
1513 )
1514}
1515pub fn ftr_ext_cofree_functor_ty() -> Expr {
1516 let type1 = Expr::Sort(Level::succ(Level::zero()));
1517 Expr::Pi(
1518 BinderInfo::Default,
1519 Name::str("cofree_functor"),
1520 Box::new(type1.clone()),
1521 Box::new(type1),
1522 )
1523}
1524pub fn ftr_ext_exponential_functor_ty() -> Expr {
1525 let type1 = Expr::Sort(Level::succ(Level::zero()));
1526 Expr::Pi(
1527 BinderInfo::Default,
1528 Name::str("exp_functor"),
1529 Box::new(type1.clone()),
1530 Box::new(type1),
1531 )
1532}
1533pub fn register_functor_extended_axioms(env: &mut Environment) {
1535 let axioms: &[(&str, fn() -> Expr)] = &[
1536 ("Functor.Ext.IdentityLaw", ftr_ext_identity_law_ty),
1537 ("Functor.Ext.CompositionLaw", ftr_ext_composition_law_ty),
1538 ("Functor.Ext.Naturality", ftr_ext_naturality_ty),
1539 ("Functor.Ext.ListIdentity", ftr_ext_list_identity_ty),
1540 ("Functor.Ext.ListComposition", ftr_ext_list_composition_ty),
1541 ("Functor.Ext.OptionIdentity", ftr_ext_option_identity_ty),
1542 (
1543 "Functor.Ext.OptionComposition",
1544 ftr_ext_option_composition_ty,
1545 ),
1546 ("Functor.Ext.ResultIdentity", ftr_ext_result_identity_ty),
1547 ("Functor.Ext.PairFmap", ftr_ext_pair_fmap_ty),
1548 (
1549 "Functor.Ext.BifunctorIdentity",
1550 ftr_ext_bifunctor_identity_ty,
1551 ),
1552 (
1553 "Functor.Ext.BifunctorComposition",
1554 ftr_ext_bifunctor_composition_ty,
1555 ),
1556 (
1557 "Functor.Ext.ContramapIdentity",
1558 ftr_ext_contramap_identity_ty,
1559 ),
1560 (
1561 "Functor.Ext.ContramapComposition",
1562 ftr_ext_contramap_composition_ty,
1563 ),
1564 (
1565 "Functor.Ext.ProfunctorIdentity",
1566 ftr_ext_profunctor_identity_ty,
1567 ),
1568 (
1569 "Functor.Ext.ProfunctorComposition",
1570 ftr_ext_profunctor_composition_ty,
1571 ),
1572 ("Functor.Ext.ApIdentity", ftr_ext_ap_identity_ty),
1573 ("Functor.Ext.ApHomomorphism", ftr_ext_ap_homomorphism_ty),
1574 ("Functor.Ext.ApInterchange", ftr_ext_ap_interchange_ty),
1575 ("Functor.Ext.ApComposition", ftr_ext_ap_composition_ty),
1576 ("Functor.Ext.MonoidalUnit", ftr_ext_monoidal_unit_ty),
1577 ("Functor.Ext.MonoidalZip", ftr_ext_monoidal_zip_ty),
1578 ("Functor.Ext.StrongFirst", ftr_ext_strong_first_ty),
1579 ("Functor.Ext.StrongSecond", ftr_ext_strong_second_ty),
1580 ("Functor.Ext.CartesianCopy", ftr_ext_cartesian_copy_ty),
1581 ("Functor.Ext.CartesianDelete", ftr_ext_cartesian_delete_ty),
1582 ("Functor.Ext.ClosedApply", ftr_ext_closed_apply_ty),
1583 ("Functor.Ext.ClosedCurry", ftr_ext_closed_curry_ty),
1584 ("Functor.Ext.TraverseIdentity", ftr_ext_traverse_identity_ty),
1585 (
1586 "Functor.Ext.TraverseComposition",
1587 ftr_ext_traverse_composition_ty,
1588 ),
1589 ("Functor.Ext.FoldConsistent", ftr_ext_fold_consistent_ty),
1590 ("Functor.Ext.FoldmapMorphism", ftr_ext_foldmap_morphism_ty),
1591 (
1592 "Functor.Ext.RepresentableTabulate",
1593 ftr_ext_representable_tabulate_ty,
1594 ),
1595 (
1596 "Functor.Ext.RepresentableIndex",
1597 ftr_ext_representable_index_ty,
1598 ),
1599 ("Functor.Ext.KanLeft", ftr_ext_kan_left_ty),
1600 ("Functor.Ext.KanRight", ftr_ext_kan_right_ty),
1601 ("Functor.Ext.DayConvUnit", ftr_ext_day_conv_unit_ty),
1602 ("Functor.Ext.DayConvAssoc", ftr_ext_day_conv_assoc_ty),
1603 ("Functor.Ext.ComposeIdentity", ftr_ext_compose_identity_ty),
1604 ("Functor.Ext.ComposeAssoc", ftr_ext_compose_assoc_ty),
1605 ("Functor.Ext.NatTransId", ftr_ext_nat_trans_id_ty),
1606 ("Functor.Ext.NatTransComp", ftr_ext_nat_trans_comp_ty),
1607 ("Functor.Ext.AdjunctionUnit", ftr_ext_adjunction_unit_ty),
1608 ("Functor.Ext.AdjunctionCounit", ftr_ext_adjunction_counit_ty),
1609 (
1610 "Functor.Ext.AdjunctionTriangle",
1611 ftr_ext_adjunction_triangle_ty,
1612 ),
1613 ("Functor.Ext.FunctorCatObj", ftr_ext_functor_cat_obj_ty),
1614 ("Functor.Ext.FunctorCatMor", ftr_ext_functor_cat_mor_ty),
1615 ("Functor.Ext.Presheaf", ftr_ext_presheaf_ty),
1616 ("Functor.Ext.YonedaLemma", ftr_ext_yoneda_lemma_ty),
1617 ("Functor.Ext.YonedaEmbedding", ftr_ext_yoneda_embedding_ty),
1618 ("Functor.Ext.SheafGluing", ftr_ext_sheaf_gluing_ty),
1619 ("Functor.Ext.SheafLocality", ftr_ext_sheaf_locality_ty),
1620 ("Functor.Ext.FmapPreservesEq", ftr_ext_fmap_preserves_eq_ty),
1621 ("Functor.Ext.FreeFunctor", ftr_ext_free_functor_ty),
1622 ("Functor.Ext.CofreeFunctor", ftr_ext_cofree_functor_ty),
1623 (
1624 "Functor.Ext.ExponentialFunctor",
1625 ftr_ext_exponential_functor_ty,
1626 ),
1627 ];
1628 for (name, ty_fn) in axioms {
1629 let _ = env.add(Declaration::Axiom {
1630 name: Name::str(*name),
1631 univ_params: vec![],
1632 ty: ty_fn(),
1633 });
1634 }
1635}
1636pub fn kleisli_compose_option<A, B, C, F, G>(f: F, g: G) -> impl Fn(A) -> Option<C>
1638where
1639 F: Fn(A) -> Option<B>,
1640 G: Fn(B) -> Option<C>,
1641{
1642 move |a| f(a).and_then(|b| g(b))
1643}
1644pub fn kleisli_compose_vec<A, B, C, F, G>(f: F, g: G) -> impl Fn(A) -> Vec<C>
1646where
1647 F: Fn(A) -> Vec<B>,
1648 G: Fn(B) -> Vec<C>,
1649 B: Clone,
1650{
1651 move |a| f(a).into_iter().flat_map(|b| g(b)).collect()
1652}
1653pub fn reader_fmap<E: Clone + 'static, A: 'static, B: 'static>(
1655 reader: Reader<E, A>,
1656 f: impl Fn(A) -> B + 'static,
1657) -> Reader<E, B> {
1658 reader.map(f)
1659}
1660pub fn dimap_fn<A, B, C, D>(
1662 pre: impl Fn(C) -> A + 'static,
1663 post: impl Fn(B) -> D + 'static,
1664 f: impl Fn(A) -> B + 'static,
1665) -> impl Fn(C) -> D {
1666 move |c| post(f(pre(c)))
1667}
1668pub fn fmap_via_nat_trans<A: Clone, B, F: Fn(A) -> B>(v: Option<A>, f: F) -> Vec<B> {
1670 option_to_vec(v).into_iter().map(f).collect()
1671}
1672pub fn sequence_option_vec<A: Clone>(xs: Vec<Option<A>>) -> Option<Vec<A>> {
1674 xs.into_iter().collect()
1675}
1676pub fn fmap_option_then_vec<A, B: Clone, F: Fn(A) -> B>(opt: Option<A>, f: F) -> Vec<B> {
1678 match opt {
1679 Some(a) => vec![f(a)],
1680 None => vec![],
1681 }
1682}
1683pub fn pure_option<A>(a: A) -> Option<A> {
1685 Some(a)
1686}
1687pub fn pure_vec<A>(a: A) -> Vec<A> {
1689 vec![a]
1690}
1691pub fn fish_option<A, B, C>(
1693 f: impl Fn(A) -> Option<B>,
1694 g: impl Fn(B) -> Option<C>,
1695 a: A,
1696) -> Option<C> {
1697 f(a).and_then(g)
1698}
1699pub fn option_zip<A, B>(a: Option<A>, b: Option<B>) -> Option<(A, B)> {
1701 match (a, b) {
1702 (Some(x), Some(y)) => Some((x, y)),
1703 _ => None,
1704 }
1705}
1706pub fn day_conv_vec<A: Clone, B: Clone, C>(
1708 fa: Vec<A>,
1709 fb: Vec<B>,
1710 combine: impl Fn(A, B) -> C,
1711) -> Vec<C> {
1712 let mut result = Vec::new();
1713 for a in fa {
1714 for b in fb.iter().cloned() {
1715 result.push(combine(a.clone(), b));
1716 }
1717 }
1718 result
1719}
1720pub fn contramap_compose<A: 'static, B: 'static, C: 'static>(
1722 pred: Pred<A>,
1723 f: impl Fn(B) -> A + 'static,
1724 g: impl Fn(C) -> B + 'static,
1725) -> Pred<C> {
1726 pred.contramap(move |c| f(g(c)))
1727}
1728pub fn profunctor_identity_law<A: Clone + PartialEq>(
1730 f: impl Fn(A) -> A + Clone + 'static,
1731 x: A,
1732) -> bool {
1733 let f2 = f.clone();
1734 let dimapped = dimap_fn(|a: A| a, |a: A| a, f2);
1735 dimapped(x.clone()) == f(x)
1736}
1737pub fn double_fmap<A, B, C>(
1739 xs: Vec<Option<A>>,
1740 f: impl Fn(A) -> B,
1741 g: impl Fn(B) -> C,
1742) -> Vec<Option<C>> {
1743 xs.into_iter().map(|opt| opt.map(|a| g(f(a)))).collect()
1744}
1745pub fn adjunction_triangle_option<A: Clone + PartialEq>(a: A) -> bool {
1748 let unit = |x: A| Some(x);
1749 let counit = |opt: Option<A>| opt.expect("unit always produces Some, so counit receives Some");
1750 counit(unit(a.clone())) == a
1751}
1752pub fn yoneda_reduction<A: Clone + PartialEq>(fa: Option<A>) -> bool {
1755 fmap_option(fa.clone(), |a| a) == fa
1756}
1757pub fn lan_approximation<A: Clone, B: Clone, C>(
1759 k: impl Fn(A) -> B,
1760 f: impl Fn(A) -> C,
1761 xs: Vec<A>,
1762) -> Vec<C> {
1763 xs.into_iter()
1764 .map(|a| {
1765 let _ = k(a.clone());
1766 f(a)
1767 })
1768 .collect()
1769}
1770pub fn sheaf_glue_option<A: Clone + PartialEq>(s1: Option<A>, s2: Option<A>) -> Option<A> {
1773 match (s1, s2) {
1774 (Some(a), None) => Some(a),
1775 (None, Some(b)) => Some(b),
1776 (Some(a), Some(_)) => Some(a),
1777 (None, None) => None,
1778 }
1779}
1780pub fn representable_roundtrip<A: Clone + PartialEq>(
1782 n: usize,
1783 f: impl Fn(usize) -> A,
1784 i: usize,
1785) -> bool {
1786 let rep = RepresentableFunctorExt::tabulate(n, &f);
1787 if i < n {
1788 rep.index(i).cloned() == Some(f(i))
1789 } else {
1790 rep.index(i).is_none()
1791 }
1792}
1793pub fn day_conv_unit_vec<A: Clone + PartialEq>(fa: Vec<A>) -> bool {
1795 let id_unit: Vec<()> = vec![()];
1796 let result: Vec<A> = day_conv_vec(fa.clone(), id_unit, |a, _| a);
1797 result == fa
1798}