1use oxilean_kernel::Node;
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7
8use super::types::{EitherLeftIter, EitherRightIter, LeftIter, OxiEither, RightIter, TripleSum};
9
10pub fn type1() -> Expr {
11 Expr::Sort(Level::succ(Level::zero()))
12}
13pub fn type2() -> Expr {
14 Expr::Sort(Level::succ(Level::succ(Level::zero())))
15}
16pub fn either_of(alpha: Expr, beta: Expr) -> Expr {
17 Expr::App(
18 Node::new(Expr::App(
19 Node::new(Expr::Const(Name::str("Either"), vec![])),
20 Node::new(alpha),
21 )),
22 Node::new(beta),
23 )
24}
25pub fn option_of(alpha: Expr) -> Expr {
26 Expr::App(
27 Node::new(Expr::Const(Name::str("Option"), vec![])),
28 Node::new(alpha),
29 )
30}
31pub fn bool_ty() -> Expr {
32 Expr::Const(Name::str("Bool"), vec![])
33}
34pub fn list_of(alpha: Expr) -> Expr {
35 Expr::App(
36 Node::new(Expr::Const(Name::str("List"), vec![])),
37 Node::new(alpha),
38 )
39}
40pub fn prod_of(alpha: Expr, beta: Expr) -> Expr {
41 Expr::App(
42 Node::new(Expr::App(
43 Node::new(Expr::Const(Name::str("Prod"), vec![])),
44 Node::new(alpha),
45 )),
46 Node::new(beta),
47 )
48}
49pub fn axiom(env: &mut Environment, name: &str, ty: Expr) -> Result<(), String> {
50 env.add(Declaration::Axiom {
51 name: Name::str(name),
52 univ_params: vec![],
53 ty,
54 })
55 .map_err(|e| e.to_string())
56}
57pub fn ab_implicit(inner: Expr) -> Expr {
58 Expr::Pi(
59 BinderInfo::Implicit,
60 Name::str("α"),
61 Node::new(type1()),
62 Node::new(Expr::Pi(
63 BinderInfo::Implicit,
64 Name::str("β"),
65 Node::new(type1()),
66 Node::new(inner),
67 )),
68 )
69}
70pub fn build_either_env(env: &mut Environment) -> Result<(), String> {
72 let either_ty = Expr::Pi(
73 BinderInfo::Default,
74 Name::str("α"),
75 Node::new(type1()),
76 Node::new(Expr::Pi(
77 BinderInfo::Default,
78 Name::str("β"),
79 Node::new(type1()),
80 Node::new(type2()),
81 )),
82 );
83 env.add(Declaration::Axiom {
84 name: Name::str("Either"),
85 univ_params: vec![],
86 ty: either_ty,
87 })
88 .map_err(|e| e.to_string())?;
89 add_left(env)?;
90 add_right(env)?;
91 add_is_left(env)?;
92 add_is_right(env)?;
93 add_get_left(env)?;
94 add_get_right(env)?;
95 add_cases(env)?;
96 add_map(env)?;
97 add_map_left(env)?;
98 add_bimap(env)?;
99 add_swap(env)?;
100 add_fold(env)?;
101 add_to_option(env)?;
102 add_from_option(env)?;
103 add_sequence(env)?;
104 add_partition_eithers(env)?;
105 Ok(())
106}
107pub fn add_left(env: &mut Environment) -> Result<(), String> {
108 let ty = ab_implicit(Expr::Pi(
109 BinderInfo::Default,
110 Name::str("a"),
111 Node::new(Expr::BVar(1)),
112 Node::new(either_of(Expr::BVar(2), Expr::BVar(1))),
113 ));
114 axiom(env, "Either.left", ty)
115}
116pub fn add_right(env: &mut Environment) -> Result<(), String> {
117 let ty = ab_implicit(Expr::Pi(
118 BinderInfo::Default,
119 Name::str("b"),
120 Node::new(Expr::BVar(0)),
121 Node::new(either_of(Expr::BVar(2), Expr::BVar(1))),
122 ));
123 axiom(env, "Either.right", ty)
124}
125pub fn add_is_left(env: &mut Environment) -> Result<(), String> {
126 let ty = ab_implicit(Expr::Pi(
127 BinderInfo::Default,
128 Name::str("e"),
129 Node::new(either_of(Expr::BVar(1), Expr::BVar(0))),
130 Node::new(bool_ty()),
131 ));
132 axiom(env, "Either.isLeft", ty)
133}
134pub fn add_is_right(env: &mut Environment) -> Result<(), String> {
135 let ty = ab_implicit(Expr::Pi(
136 BinderInfo::Default,
137 Name::str("e"),
138 Node::new(either_of(Expr::BVar(1), Expr::BVar(0))),
139 Node::new(bool_ty()),
140 ));
141 axiom(env, "Either.isRight", ty)
142}
143pub fn add_get_left(env: &mut Environment) -> Result<(), String> {
144 let ty = ab_implicit(Expr::Pi(
145 BinderInfo::Default,
146 Name::str("e"),
147 Node::new(either_of(Expr::BVar(1), Expr::BVar(0))),
148 Node::new(option_of(Expr::BVar(2))),
149 ));
150 axiom(env, "Either.getLeft", ty)
151}
152pub fn add_get_right(env: &mut Environment) -> Result<(), String> {
153 let ty = ab_implicit(Expr::Pi(
154 BinderInfo::Default,
155 Name::str("e"),
156 Node::new(either_of(Expr::BVar(1), Expr::BVar(0))),
157 Node::new(option_of(Expr::BVar(1))),
158 ));
159 axiom(env, "Either.getRight", ty)
160}
161pub fn add_cases(env: &mut Environment) -> Result<(), String> {
162 let fl = Expr::Pi(
163 BinderInfo::Default,
164 Name::str("_"),
165 Node::new(Expr::BVar(2)),
166 Node::new(Expr::BVar(2)),
167 );
168 let fr = Expr::Pi(
169 BinderInfo::Default,
170 Name::str("_"),
171 Node::new(Expr::BVar(2)),
172 Node::new(Expr::BVar(2)),
173 );
174 let ty = Expr::Pi(
175 BinderInfo::Implicit,
176 Name::str("α"),
177 Node::new(type1()),
178 Node::new(Expr::Pi(
179 BinderInfo::Implicit,
180 Name::str("β"),
181 Node::new(type1()),
182 Node::new(Expr::Pi(
183 BinderInfo::Implicit,
184 Name::str("γ"),
185 Node::new(type1()),
186 Node::new(Expr::Pi(
187 BinderInfo::Default,
188 Name::str("e"),
189 Node::new(either_of(Expr::BVar(2), Expr::BVar(1))),
190 Node::new(Expr::Pi(
191 BinderInfo::Default,
192 Name::str("l"),
193 Node::new(fl),
194 Node::new(Expr::Pi(
195 BinderInfo::Default,
196 Name::str("r"),
197 Node::new(fr),
198 Node::new(Expr::BVar(3)),
199 )),
200 )),
201 )),
202 )),
203 )),
204 );
205 axiom(env, "Either.cases", ty)
206}
207pub fn add_map(env: &mut Environment) -> Result<(), String> {
208 let fn_ty = Expr::Pi(
209 BinderInfo::Default,
210 Name::str("_"),
211 Node::new(Expr::BVar(1)),
212 Node::new(Expr::BVar(1)),
213 );
214 let ty = Expr::Pi(
215 BinderInfo::Implicit,
216 Name::str("α"),
217 Node::new(type1()),
218 Node::new(Expr::Pi(
219 BinderInfo::Implicit,
220 Name::str("β"),
221 Node::new(type1()),
222 Node::new(Expr::Pi(
223 BinderInfo::Implicit,
224 Name::str("γ"),
225 Node::new(type1()),
226 Node::new(Expr::Pi(
227 BinderInfo::Default,
228 Name::str("f"),
229 Node::new(fn_ty),
230 Node::new(Expr::Pi(
231 BinderInfo::Default,
232 Name::str("e"),
233 Node::new(either_of(Expr::BVar(3), Expr::BVar(2))),
234 Node::new(either_of(Expr::BVar(4), Expr::BVar(2))),
235 )),
236 )),
237 )),
238 )),
239 );
240 axiom(env, "Either.map", ty)
241}
242pub fn add_map_left(env: &mut Environment) -> Result<(), String> {
243 let fn_ty = Expr::Pi(
244 BinderInfo::Default,
245 Name::str("_"),
246 Node::new(Expr::BVar(2)),
247 Node::new(Expr::BVar(2)),
248 );
249 let ty = Expr::Pi(
250 BinderInfo::Implicit,
251 Name::str("α"),
252 Node::new(type1()),
253 Node::new(Expr::Pi(
254 BinderInfo::Implicit,
255 Name::str("β"),
256 Node::new(type1()),
257 Node::new(Expr::Pi(
258 BinderInfo::Implicit,
259 Name::str("γ"),
260 Node::new(type1()),
261 Node::new(Expr::Pi(
262 BinderInfo::Default,
263 Name::str("f"),
264 Node::new(fn_ty),
265 Node::new(Expr::Pi(
266 BinderInfo::Default,
267 Name::str("e"),
268 Node::new(either_of(Expr::BVar(3), Expr::BVar(2))),
269 Node::new(either_of(Expr::BVar(2), Expr::BVar(3))),
270 )),
271 )),
272 )),
273 )),
274 );
275 axiom(env, "Either.mapLeft", ty)
276}
277pub fn add_bimap(env: &mut Environment) -> Result<(), String> {
278 let fl = Expr::Pi(
279 BinderInfo::Default,
280 Name::str("_"),
281 Node::new(Expr::BVar(3)),
282 Node::new(Expr::BVar(3)),
283 );
284 let fr = Expr::Pi(
285 BinderInfo::Default,
286 Name::str("_"),
287 Node::new(Expr::BVar(3)),
288 Node::new(Expr::BVar(3)),
289 );
290 let ty = Expr::Pi(
291 BinderInfo::Implicit,
292 Name::str("α"),
293 Node::new(type1()),
294 Node::new(Expr::Pi(
295 BinderInfo::Implicit,
296 Name::str("β"),
297 Node::new(type1()),
298 Node::new(Expr::Pi(
299 BinderInfo::Implicit,
300 Name::str("γ"),
301 Node::new(type1()),
302 Node::new(Expr::Pi(
303 BinderInfo::Implicit,
304 Name::str("δ"),
305 Node::new(type1()),
306 Node::new(Expr::Pi(
307 BinderInfo::Default,
308 Name::str("fl"),
309 Node::new(fl),
310 Node::new(Expr::Pi(
311 BinderInfo::Default,
312 Name::str("fr"),
313 Node::new(fr),
314 Node::new(Expr::Pi(
315 BinderInfo::Default,
316 Name::str("e"),
317 Node::new(either_of(Expr::BVar(5), Expr::BVar(4))),
318 Node::new(either_of(Expr::BVar(4), Expr::BVar(4))),
319 )),
320 )),
321 )),
322 )),
323 )),
324 )),
325 );
326 axiom(env, "Either.bimap", ty)
327}
328pub fn add_swap(env: &mut Environment) -> Result<(), String> {
329 let ty = ab_implicit(Expr::Pi(
330 BinderInfo::Default,
331 Name::str("e"),
332 Node::new(either_of(Expr::BVar(1), Expr::BVar(0))),
333 Node::new(either_of(Expr::BVar(1), Expr::BVar(2))),
334 ));
335 axiom(env, "Either.swap", ty)
336}
337pub fn add_fold(env: &mut Environment) -> Result<(), String> {
338 let fl = Expr::Pi(
339 BinderInfo::Default,
340 Name::str("_"),
341 Node::new(Expr::BVar(2)),
342 Node::new(Expr::BVar(2)),
343 );
344 let fr = Expr::Pi(
345 BinderInfo::Default,
346 Name::str("_"),
347 Node::new(Expr::BVar(2)),
348 Node::new(Expr::BVar(2)),
349 );
350 let ty = Expr::Pi(
351 BinderInfo::Implicit,
352 Name::str("α"),
353 Node::new(type1()),
354 Node::new(Expr::Pi(
355 BinderInfo::Implicit,
356 Name::str("β"),
357 Node::new(type1()),
358 Node::new(Expr::Pi(
359 BinderInfo::Implicit,
360 Name::str("γ"),
361 Node::new(type1()),
362 Node::new(Expr::Pi(
363 BinderInfo::Default,
364 Name::str("fl"),
365 Node::new(fl),
366 Node::new(Expr::Pi(
367 BinderInfo::Default,
368 Name::str("fr"),
369 Node::new(fr),
370 Node::new(Expr::Pi(
371 BinderInfo::Default,
372 Name::str("e"),
373 Node::new(either_of(Expr::BVar(4), Expr::BVar(3))),
374 Node::new(Expr::BVar(3)),
375 )),
376 )),
377 )),
378 )),
379 )),
380 );
381 axiom(env, "Either.fold", ty)
382}
383pub fn add_to_option(env: &mut Environment) -> Result<(), String> {
384 let ty = ab_implicit(Expr::Pi(
385 BinderInfo::Default,
386 Name::str("e"),
387 Node::new(either_of(Expr::BVar(1), Expr::BVar(0))),
388 Node::new(option_of(Expr::BVar(1))),
389 ));
390 axiom(env, "Either.toOption", ty)
391}
392pub fn add_from_option(env: &mut Environment) -> Result<(), String> {
393 let ty = ab_implicit(Expr::Pi(
394 BinderInfo::Default,
395 Name::str("err"),
396 Node::new(Expr::BVar(1)),
397 Node::new(Expr::Pi(
398 BinderInfo::Default,
399 Name::str("opt"),
400 Node::new(option_of(Expr::BVar(1))),
401 Node::new(either_of(Expr::BVar(3), Expr::BVar(2))),
402 )),
403 ));
404 axiom(env, "Either.fromOption", ty)
405}
406pub fn add_sequence(env: &mut Environment) -> Result<(), String> {
407 let ty = ab_implicit(Expr::Pi(
408 BinderInfo::Default,
409 Name::str("xs"),
410 Node::new(list_of(either_of(Expr::BVar(1), Expr::BVar(0)))),
411 Node::new(either_of(Expr::BVar(2), list_of(Expr::BVar(1)))),
412 ));
413 axiom(env, "Either.sequence", ty)
414}
415pub fn add_partition_eithers(env: &mut Environment) -> Result<(), String> {
416 let ty = ab_implicit(Expr::Pi(
417 BinderInfo::Default,
418 Name::str("xs"),
419 Node::new(list_of(either_of(Expr::BVar(1), Expr::BVar(0)))),
420 Node::new(prod_of(list_of(Expr::BVar(2)), list_of(Expr::BVar(1)))),
421 ));
422 axiom(env, "Either.partitionEithers", ty)
423}
424pub fn setup_base_env() -> Environment {
425 let mut env = Environment::new();
426 let t1 = type1();
427 for name in ["Bool", "Option", "List", "Prod"] {
428 env.add(Declaration::Axiom {
429 name: Name::str(name),
430 univ_params: vec![],
431 ty: t1.clone(),
432 })
433 .unwrap_or(());
434 }
435 env
436}
437#[cfg(test)]
438mod tests {
439 use super::*;
440 #[test]
441 fn test_build_either_env() {
442 let mut env = setup_base_env();
443 assert!(build_either_env(&mut env).is_ok());
444 assert!(env.get(&Name::str("Either")).is_some());
445 assert!(env.get(&Name::str("Either.left")).is_some());
446 assert!(env.get(&Name::str("Either.right")).is_some());
447 }
448 #[test]
449 fn test_either_is_left() {
450 let mut env = setup_base_env();
451 build_either_env(&mut env).expect("build_either_env should succeed");
452 assert!(matches!(
453 env.get(&Name::str("Either.isLeft"))
454 .expect("declaration 'Either.isLeft' should exist in env"),
455 Declaration::Axiom { .. }
456 ));
457 }
458 #[test]
459 fn test_either_is_right() {
460 let mut env = setup_base_env();
461 build_either_env(&mut env).expect("build_either_env should succeed");
462 assert!(matches!(
463 env.get(&Name::str("Either.isRight"))
464 .expect("declaration 'Either.isRight' should exist in env"),
465 Declaration::Axiom { .. }
466 ));
467 }
468 #[test]
469 fn test_either_get_left() {
470 let mut env = setup_base_env();
471 build_either_env(&mut env).expect("build_either_env should succeed");
472 assert!(env.get(&Name::str("Either.getLeft")).is_some());
473 }
474 #[test]
475 fn test_either_get_right() {
476 let mut env = setup_base_env();
477 build_either_env(&mut env).expect("build_either_env should succeed");
478 assert!(env.get(&Name::str("Either.getRight")).is_some());
479 }
480 #[test]
481 fn test_either_cases() {
482 let mut env = setup_base_env();
483 build_either_env(&mut env).expect("build_either_env should succeed");
484 assert!(env.get(&Name::str("Either.cases")).is_some());
485 }
486 #[test]
487 fn test_either_map() {
488 let mut env = setup_base_env();
489 build_either_env(&mut env).expect("build_either_env should succeed");
490 assert!(env.get(&Name::str("Either.map")).is_some());
491 }
492 #[test]
493 fn test_either_map_left() {
494 let mut env = setup_base_env();
495 build_either_env(&mut env).expect("build_either_env should succeed");
496 assert!(env.get(&Name::str("Either.mapLeft")).is_some());
497 }
498 #[test]
499 fn test_either_bimap() {
500 let mut env = setup_base_env();
501 build_either_env(&mut env).expect("build_either_env should succeed");
502 assert!(env.get(&Name::str("Either.bimap")).is_some());
503 }
504 #[test]
505 fn test_either_swap() {
506 let mut env = setup_base_env();
507 build_either_env(&mut env).expect("build_either_env should succeed");
508 assert!(env.get(&Name::str("Either.swap")).is_some());
509 }
510 #[test]
511 fn test_either_fold() {
512 let mut env = setup_base_env();
513 build_either_env(&mut env).expect("build_either_env should succeed");
514 assert!(env.get(&Name::str("Either.fold")).is_some());
515 }
516 #[test]
517 fn test_either_to_option() {
518 let mut env = setup_base_env();
519 build_either_env(&mut env).expect("build_either_env should succeed");
520 assert!(env.get(&Name::str("Either.toOption")).is_some());
521 }
522 #[test]
523 fn test_either_from_option() {
524 let mut env = setup_base_env();
525 build_either_env(&mut env).expect("build_either_env should succeed");
526 assert!(env.get(&Name::str("Either.fromOption")).is_some());
527 }
528 #[test]
529 fn test_either_sequence() {
530 let mut env = setup_base_env();
531 build_either_env(&mut env).expect("build_either_env should succeed");
532 assert!(env.get(&Name::str("Either.sequence")).is_some());
533 }
534 #[test]
535 fn test_either_partition_eithers() {
536 let mut env = setup_base_env();
537 build_either_env(&mut env).expect("build_either_env should succeed");
538 assert!(env.get(&Name::str("Either.partitionEithers")).is_some());
539 }
540}
541pub trait EitherIterExt<A, B>: Iterator<Item = OxiEither<A, B>> + Sized {
543 fn lefts(self) -> LeftIter<A, B, Self> {
545 LeftIter { inner: self }
546 }
547 fn rights(self) -> RightIter<A, B, Self> {
549 RightIter { inner: self }
550 }
551 fn partition_either(self) -> (Vec<A>, Vec<B>) {
553 let mut ls = Vec::new();
554 let mut rs = Vec::new();
555 for e in self {
556 match e {
557 OxiEither::Left(a) => ls.push(a),
558 OxiEither::Right(b) => rs.push(b),
559 }
560 }
561 (ls, rs)
562 }
563}
564impl<A, B, I: Iterator<Item = OxiEither<A, B>>> EitherIterExt<A, B> for I {}
565pub fn validate_all<A: Clone, E: Clone, I: IntoIterator<Item = OxiEither<A, E>>>(
570 items: I,
571) -> OxiEither<Vec<A>, Vec<E>> {
572 let mut successes = Vec::new();
573 let mut errors = Vec::new();
574 for item in items {
575 match item {
576 OxiEither::Left(a) => successes.push(a),
577 OxiEither::Right(e) => errors.push(e),
578 }
579 }
580 if errors.is_empty() {
581 OxiEither::Left(successes)
582 } else {
583 OxiEither::Right(errors)
584 }
585}
586pub fn sequence_either<A: Clone, E: Clone, I: IntoIterator<Item = OxiEither<A, E>>>(
588 items: I,
589) -> OxiEither<Vec<A>, E> {
590 let mut results = Vec::new();
591 for item in items {
592 match item {
593 OxiEither::Left(a) => results.push(a),
594 OxiEither::Right(e) => return OxiEither::Right(e),
595 }
596 }
597 OxiEither::Left(results)
598}
599pub fn traverse_either<A, B, E, F, I>(items: I, f: F) -> OxiEither<Vec<B>, E>
601where
602 I: IntoIterator<Item = A>,
603 F: Fn(A) -> OxiEither<B, E>,
604{
605 let mut results = Vec::new();
606 for item in items {
607 match f(item) {
608 OxiEither::Left(b) => results.push(b),
609 OxiEither::Right(e) => return OxiEither::Right(e),
610 }
611 }
612 OxiEither::Left(results)
613}
614pub fn zip_either<A, B, C>(ea: OxiEither<A, C>, eb: OxiEither<B, C>) -> OxiEither<(A, B), C> {
616 match (ea, eb) {
617 (OxiEither::Left(a), OxiEither::Left(b)) => OxiEither::Left((a, b)),
618 (OxiEither::Right(e), _) | (_, OxiEither::Right(e)) => OxiEither::Right(e),
619 }
620}
621pub fn merge_either<A, B, C, F>(ea: OxiEither<A, B>, eb: OxiEither<A, B>, f: F) -> OxiEither<A, B>
623where
624 F: Fn(A, A) -> A,
625 A: Clone,
626 B: Clone,
627{
628 match (ea, eb) {
629 (OxiEither::Left(a1), OxiEither::Left(a2)) => OxiEither::Left(f(a1, a2)),
630 (OxiEither::Right(e), _) | (_, OxiEither::Right(e)) => OxiEither::Right(e),
631 }
632}
633pub fn option_to_either<A>(opt: Option<A>) -> OxiEither<A, ()> {
635 match opt {
636 Some(a) => OxiEither::Left(a),
637 None => OxiEither::Right(()),
638 }
639}
640pub fn either_to_option<A>(e: OxiEither<A, ()>) -> Option<A> {
642 match e {
643 OxiEither::Left(a) => Some(a),
644 OxiEither::Right(()) => None,
645 }
646}
647pub fn result_to_either<A, E>(r: Result<A, E>) -> OxiEither<A, E> {
649 match r {
650 Ok(a) => OxiEither::Left(a),
651 Err(e) => OxiEither::Right(e),
652 }
653}
654pub fn either_to_result<A, E>(e: OxiEither<A, E>) -> Result<A, E> {
656 match e {
657 OxiEither::Left(a) => Ok(a),
658 OxiEither::Right(e) => Err(e),
659 }
660}
661pub fn count_lefts_rights<A, B, I: IntoIterator<Item = OxiEither<A, B>>>(
663 items: I,
664) -> (usize, usize) {
665 items.into_iter().fold((0, 0), |(ls, rs), e| match e {
666 OxiEither::Left(_) => (ls + 1, rs),
667 OxiEither::Right(_) => (ls, rs + 1),
668 })
669}
670pub fn either_from_pred<A: Clone, B: Clone, F: Fn(&A) -> Option<B>>(a: A, f: F) -> OxiEither<A, B> {
672 match f(&a) {
673 Some(b) => OxiEither::Right(b),
674 None => OxiEither::Left(a),
675 }
676}
677#[cfg(test)]
678mod either_extended_tests {
679 use super::*;
680 #[test]
681 fn test_lefts_iter() {
682 let items: Vec<OxiEither<i32, &str>> = vec![
683 OxiEither::Left(1),
684 OxiEither::Right("no"),
685 OxiEither::Left(2),
686 ];
687 let lefts: Vec<i32> = items.into_iter().lefts().collect();
688 assert_eq!(lefts, vec![1, 2]);
689 }
690 #[test]
691 fn test_rights_iter() {
692 let items: Vec<OxiEither<i32, &str>> = vec![
693 OxiEither::Left(1),
694 OxiEither::Right("yes"),
695 OxiEither::Right("also"),
696 ];
697 let rights: Vec<&str> = items.into_iter().rights().collect();
698 assert_eq!(rights, vec!["yes", "also"]);
699 }
700 #[test]
701 fn test_partition_either_iter() {
702 let items: Vec<OxiEither<i32, &str>> = vec![
703 OxiEither::Left(1),
704 OxiEither::Right("e"),
705 OxiEither::Left(2),
706 ];
707 let (ls, rs) = items.into_iter().partition_either();
708 assert_eq!(ls, vec![1, 2]);
709 assert_eq!(rs, vec!["e"]);
710 }
711 #[test]
712 fn test_validate_all_ok() {
713 let items: Vec<OxiEither<i32, &str>> = vec![OxiEither::Left(1), OxiEither::Left(2)];
714 let result = validate_all(items);
715 assert_eq!(result, OxiEither::Left(vec![1, 2]));
716 }
717 #[test]
718 fn test_validate_all_errors() {
719 let items: Vec<OxiEither<i32, &str>> = vec![OxiEither::Left(1), OxiEither::Right("bad")];
720 let result = validate_all(items);
721 assert_eq!(result, OxiEither::Right(vec!["bad"]));
722 }
723 #[test]
724 fn test_sequence_either_ok() {
725 let items: Vec<OxiEither<i32, &str>> = vec![OxiEither::Left(1), OxiEither::Left(2)];
726 assert_eq!(sequence_either(items), OxiEither::Left(vec![1, 2]));
727 }
728 #[test]
729 fn test_sequence_either_fail() {
730 let items: Vec<OxiEither<i32, &str>> = vec![OxiEither::Left(1), OxiEither::Right("err")];
731 assert_eq!(sequence_either(items), OxiEither::Right("err"));
732 }
733 #[test]
734 fn test_traverse_either_ok() {
735 let result = traverse_either(vec![1i32, 2, 3], |x| OxiEither::Left(x * 2));
736 assert_eq!(result, OxiEither::<Vec<i32>, &str>::Left(vec![2, 4, 6]));
737 }
738 #[test]
739 fn test_option_to_either() {
740 let e = option_to_either(Some(42i32));
741 assert_eq!(e, OxiEither::Left(42));
742 let e2: OxiEither<i32, ()> = option_to_either(None);
743 assert_eq!(e2, OxiEither::Right(()));
744 }
745 #[test]
746 fn test_result_to_either() {
747 let e: OxiEither<i32, &str> = result_to_either(Ok(1));
748 assert_eq!(e, OxiEither::Left(1));
749 let e2: OxiEither<i32, &str> = result_to_either(Err("oops"));
750 assert_eq!(e2, OxiEither::Right("oops"));
751 }
752 #[test]
753 fn test_count_lefts_rights() {
754 let items: Vec<OxiEither<i32, &str>> = vec![
755 OxiEither::Left(1),
756 OxiEither::Right("a"),
757 OxiEither::Left(2),
758 ];
759 assert_eq!(count_lefts_rights(items), (2, 1));
760 }
761 #[test]
762 fn test_triple_sum_to_nested() {
763 let t: TripleSum<i32, &str, f64> = TripleSum::First(1);
764 let nested = t.to_nested();
765 assert!(nested.is_left());
766 let t2: TripleSum<i32, &str, f64> = TripleSum::Second("hi");
767 let nested2 = t2.to_nested();
768 assert!(nested2.is_right());
769 }
770 #[test]
771 fn test_triple_sum_variants() {
772 let a: TripleSum<i32, i32, i32> = TripleSum::First(1);
773 let b: TripleSum<i32, i32, i32> = TripleSum::Second(2);
774 let c: TripleSum<i32, i32, i32> = TripleSum::Third(3);
775 assert!(a.is_first() && !a.is_second() && !a.is_third());
776 assert!(b.is_second());
777 assert!(c.is_third());
778 }
779 #[test]
780 fn test_zip_either_both_left() {
781 let ea: OxiEither<i32, &str> = OxiEither::Left(1);
782 let eb: OxiEither<i32, &str> = OxiEither::Left(2);
783 let result = zip_either(ea, eb);
784 assert_eq!(result, OxiEither::Left((1, 2)));
785 }
786 #[test]
787 fn test_zip_either_one_right() {
788 let ea: OxiEither<i32, &str> = OxiEither::Left(1);
789 let eb: OxiEither<i32, &str> = OxiEither::Right("err");
790 let result = zip_either(ea, eb);
791 assert!(result.is_right());
792 }
793}
794pub fn left_or_else<A, B, F: FnOnce(B) -> A>(e: OxiEither<A, B>, f: F) -> A {
796 match e {
797 OxiEither::Left(a) => a,
798 OxiEither::Right(b) => f(b),
799 }
800}
801pub fn right_or_else<A, B, F: FnOnce(A) -> B>(e: OxiEither<A, B>, f: F) -> B {
803 match e {
804 OxiEither::Right(b) => b,
805 OxiEither::Left(a) => f(a),
806 }
807}
808pub fn filter_with_either<T, F: Fn(&T) -> bool>(
810 items: impl IntoIterator<Item = T>,
811 pred: F,
812) -> Vec<OxiEither<T, T>> {
813 items
814 .into_iter()
815 .map(|item| {
816 if pred(&item) {
817 OxiEither::Left(item)
818 } else {
819 OxiEither::Right(item)
820 }
821 })
822 .collect()
823}
824pub fn flatten_either<A, B>(e: OxiEither<OxiEither<A, B>, B>) -> OxiEither<A, B> {
826 match e {
827 OxiEither::Left(inner) => inner,
828 OxiEither::Right(b) => OxiEither::Right(b),
829 }
830}
831pub fn transpose_option_either<A, B>(e: OxiEither<Option<A>, B>) -> Option<OxiEither<A, B>> {
833 match e {
834 OxiEither::Left(Some(a)) => Some(OxiEither::Left(a)),
835 OxiEither::Left(None) => None,
836 OxiEither::Right(b) => Some(OxiEither::Right(b)),
837 }
838}
839pub fn collect_errors<A, E, I: IntoIterator<Item = OxiEither<A, E>>>(items: I) -> (Vec<A>, Vec<E>) {
841 items
842 .into_iter()
843 .fold((Vec::new(), Vec::new()), |(mut ls, mut rs), e| {
844 match e {
845 OxiEither::Left(a) => ls.push(a),
846 OxiEither::Right(e) => rs.push(e),
847 }
848 (ls, rs)
849 })
850}
851pub fn try_map<A, B, E, F, I>(items: I, f: F) -> OxiEither<Vec<B>, E>
853where
854 I: IntoIterator<Item = A>,
855 F: Fn(A) -> OxiEither<B, E>,
856{
857 traverse_either(items, f)
858}
859pub type Homo<T> = OxiEither<T, T>;
861#[cfg(test)]
862mod either_further_tests {
863 use super::*;
864 #[test]
865 fn test_left_or_else() {
866 let e: OxiEither<i32, &str> = OxiEither::Left(5);
867 assert_eq!(left_or_else(e, |_| 99), 5);
868 let e2: OxiEither<i32, &str> = OxiEither::Right("err");
869 assert_eq!(left_or_else(e2, |_| 99), 99);
870 }
871 #[test]
872 fn test_right_or_else() {
873 let e: OxiEither<i32, &str> = OxiEither::Right("ok");
874 assert_eq!(right_or_else(e, |_| "default"), "ok");
875 let e2: OxiEither<i32, &str> = OxiEither::Left(1);
876 assert_eq!(right_or_else(e2, |_| "default"), "default");
877 }
878 #[test]
879 fn test_filter_with_either() {
880 let items = vec![1i32, 2, 3, 4];
881 let result = filter_with_either(items, |x| x % 2 == 0);
882 let (evens, odds): (Vec<_>, Vec<_>) = result.into_iter().partition(|e| e.is_left());
883 assert_eq!(evens.len(), 2);
884 assert_eq!(odds.len(), 2);
885 }
886 #[test]
887 fn test_flatten_either() {
888 let e: OxiEither<OxiEither<i32, &str>, &str> = OxiEither::Left(OxiEither::Left(1));
889 assert_eq!(flatten_either(e), OxiEither::Left(1));
890 let e2: OxiEither<OxiEither<i32, &str>, &str> = OxiEither::Right("err");
891 assert_eq!(flatten_either(e2), OxiEither::Right("err"));
892 }
893 #[test]
894 fn test_transpose_option_either_some() {
895 let e: OxiEither<Option<i32>, &str> = OxiEither::Left(Some(42));
896 assert_eq!(transpose_option_either(e), Some(OxiEither::Left(42)));
897 }
898 #[test]
899 fn test_transpose_option_either_none() {
900 let e: OxiEither<Option<i32>, &str> = OxiEither::Left(None);
901 assert_eq!(transpose_option_either(e), None);
902 }
903 #[test]
904 fn test_collect_errors() {
905 let items: Vec<OxiEither<i32, &str>> = vec![
906 OxiEither::Left(1),
907 OxiEither::Right("e1"),
908 OxiEither::Left(2),
909 OxiEither::Right("e2"),
910 ];
911 let (ls, rs) = collect_errors(items);
912 assert_eq!(ls, vec![1, 2]);
913 assert_eq!(rs, vec!["e1", "e2"]);
914 }
915 #[test]
916 fn test_homo_into_inner() {
917 let e: OxiEither<i32, i32> = OxiEither::Left(5);
918 assert_eq!(e.into_inner(), 5);
919 let e2: OxiEither<i32, i32> = OxiEither::Right(7);
920 assert_eq!(e2.into_inner(), 7);
921 }
922 #[test]
923 fn test_try_map_ok() {
924 let result = try_map(vec![1i32, 2, 3], |x| {
925 if x > 0 {
926 OxiEither::Left(x * 2)
927 } else {
928 OxiEither::Right("neg")
929 }
930 });
931 assert_eq!(result, OxiEither::Left(vec![2, 4, 6]));
932 }
933 #[test]
934 fn test_try_map_fail() {
935 let result: OxiEither<Vec<i32>, &str> = try_map(vec![1i32, -1, 2], |x| {
936 if x > 0 {
937 OxiEither::Left(x)
938 } else {
939 OxiEither::Right("neg")
940 }
941 });
942 assert_eq!(result, OxiEither::Right("neg"));
943 }
944}
945pub fn separate<A: Clone, B: Clone>(items: &[OxiEither<A, B>]) -> (Vec<A>, Vec<B>) {
947 let mut lefts = Vec::new();
948 let mut rights = Vec::new();
949 for item in items {
950 match item {
951 OxiEither::Left(a) => lefts.push(a.clone()),
952 OxiEither::Right(b) => rights.push(b.clone()),
953 }
954 }
955 (lefts, rights)
956}
957pub fn count_lefts<A, B>(items: &[OxiEither<A, B>]) -> usize {
959 items.iter().filter(|e| e.is_left()).count()
960}
961pub fn count_rights<A, B>(items: &[OxiEither<A, B>]) -> usize {
963 items.iter().filter(|e| e.is_right()).count()
964}
965pub fn map_rights<A: Clone, B: Clone, C>(
967 items: &[OxiEither<A, B>],
968 f: impl Fn(B) -> C,
969) -> Vec<OxiEither<A, C>> {
970 items.iter().map(|e| e.clone().map_right(&f)).collect()
971}
972pub fn map_lefts<A: Clone, B: Clone, C>(
974 items: &[OxiEither<A, B>],
975 f: impl Fn(A) -> C,
976) -> Vec<OxiEither<C, B>> {
977 items.iter().map(|e| e.clone().map_left(&f)).collect()
978}
979pub fn collect_rights<A, B: Clone>(items: &[OxiEither<A, B>]) -> Vec<B> {
981 items.iter().filter_map(|e| e.as_right().cloned()).collect()
982}
983pub fn collect_lefts<A: Clone, B>(items: &[OxiEither<A, B>]) -> Vec<A> {
985 items.iter().filter_map(|e| e.as_left().cloned()).collect()
986}
987#[cfg(test)]
988mod extra_either_tests {
989 use super::*;
990 #[test]
991 fn test_either_right_iter_some() {
992 let e: OxiEither<i32, &str> = OxiEither::Right("hello");
993 let mut it = EitherRightIter::new(e);
994 assert_eq!(it.next(), Some("hello"));
995 assert_eq!(it.next(), None);
996 }
997 #[test]
998 fn test_either_right_iter_none() {
999 let e: OxiEither<i32, &str> = OxiEither::Left(42);
1000 let mut it = EitherRightIter::new(e);
1001 assert_eq!(it.next(), None);
1002 }
1003 #[test]
1004 fn test_either_left_iter_some() {
1005 let e: OxiEither<i32, &str> = OxiEither::Left(99);
1006 let mut it = EitherLeftIter::new(e);
1007 assert_eq!(it.next(), Some(99));
1008 assert_eq!(it.next(), None);
1009 }
1010 #[test]
1011 fn test_either_left_iter_none() {
1012 let e: OxiEither<i32, &str> = OxiEither::Right("r");
1013 let mut it = EitherLeftIter::new(e);
1014 assert_eq!(it.next(), None);
1015 }
1016 #[test]
1017 fn test_separate() {
1018 let items: Vec<OxiEither<i32, &str>> = vec![
1019 OxiEither::Left(1),
1020 OxiEither::Right("a"),
1021 OxiEither::Left(2),
1022 ];
1023 let (ls, rs) = separate(&items);
1024 assert_eq!(ls, vec![1, 2]);
1025 assert_eq!(rs, vec!["a"]);
1026 }
1027 #[test]
1028 fn test_count_lefts_rights() {
1029 let items: Vec<OxiEither<i32, &str>> = vec![
1030 OxiEither::Left(1),
1031 OxiEither::Right("x"),
1032 OxiEither::Left(2),
1033 OxiEither::Right("y"),
1034 ];
1035 assert_eq!(count_lefts(&items), 2);
1036 assert_eq!(count_rights(&items), 2);
1037 }
1038 #[test]
1039 fn test_map_rights() {
1040 let items: Vec<OxiEither<i32, i32>> = vec![OxiEither::Left(1), OxiEither::Right(2)];
1041 let mapped = map_rights(&items, |x| x * 10);
1042 assert_eq!(mapped[0], OxiEither::Left(1));
1043 assert_eq!(mapped[1], OxiEither::Right(20));
1044 }
1045 #[test]
1046 fn test_map_lefts() {
1047 let items: Vec<OxiEither<i32, i32>> = vec![OxiEither::Left(3), OxiEither::Right(4)];
1048 let mapped = map_lefts(&items, |x| x + 100);
1049 assert_eq!(mapped[0], OxiEither::Left(103));
1050 assert_eq!(mapped[1], OxiEither::Right(4));
1051 }
1052 #[test]
1053 fn test_collect_rights() {
1054 let items: Vec<OxiEither<i32, &str>> = vec![
1055 OxiEither::Left(1),
1056 OxiEither::Right("a"),
1057 OxiEither::Right("b"),
1058 ];
1059 assert_eq!(collect_rights(&items), vec!["a", "b"]);
1060 }
1061 #[test]
1062 fn test_collect_lefts() {
1063 let items: Vec<OxiEither<i32, &str>> = vec![
1064 OxiEither::Left(10),
1065 OxiEither::Right("x"),
1066 OxiEither::Left(20),
1067 ];
1068 assert_eq!(collect_lefts(&items), vec![10, 20]);
1069 }
1070}
1071pub fn ei_ext_app(f: Expr, a: Expr) -> Expr {
1072 Expr::App(Node::new(f), Node::new(a))
1073}
1074pub fn ei_ext_app2(f: Expr, a: Expr, b: Expr) -> Expr {
1075 ei_ext_app(ei_ext_app(f, a), b)
1076}
1077pub fn ei_ext_cst(s: &str) -> Expr {
1078 Expr::Const(Name::str(s), vec![])
1079}
1080pub fn ei_ext_prop() -> Expr {
1081 Expr::Sort(Level::zero())
1082}
1083pub fn ei_ext_type0() -> Expr {
1084 Expr::Sort(Level::succ(Level::zero()))
1085}
1086pub fn ei_ext_bvar(n: u32) -> Expr {
1087 Expr::BVar(n)
1088}
1089pub fn ei_ext_nat_ty() -> Expr {
1090 ei_ext_cst("Nat")
1091}
1092pub fn ei_ext_arrow(dom: Expr, cod: Expr) -> Expr {
1093 Expr::Pi(
1094 BinderInfo::Default,
1095 Name::Anonymous,
1096 Node::new(dom),
1097 Node::new(cod),
1098 )
1099}
1100pub fn ei_ext_pi(binfo: BinderInfo, nm: &str, dom: Expr, cod: Expr) -> Expr {
1101 Expr::Pi(binfo, Name::str(nm), Node::new(dom), Node::new(cod))
1102}
1103pub fn ei_ext_ipi(nm: &str, dom: Expr, cod: Expr) -> Expr {
1104 ei_ext_pi(BinderInfo::Implicit, nm, dom, cod)
1105}
1106pub fn ei_ext_dpi(nm: &str, dom: Expr, cod: Expr) -> Expr {
1107 ei_ext_pi(BinderInfo::Default, nm, dom, cod)
1108}
1109pub fn ei_ext_either(a: Expr, b: Expr) -> Expr {
1110 ei_ext_app2(ei_ext_cst("Either"), a, b)
1111}
1112pub fn ei_ext_prod(a: Expr, b: Expr) -> Expr {
1113 ei_ext_app2(ei_ext_cst("Prod"), a, b)
1114}
1115pub fn ei_ext_list(a: Expr) -> Expr {
1116 ei_ext_app(ei_ext_cst("List"), a)
1117}
1118pub fn ei_ext_option(a: Expr) -> Expr {
1119 ei_ext_app(ei_ext_cst("Option"), a)
1120}
1121pub fn ei_ext_result(a: Expr, e: Expr) -> Expr {
1122 ei_ext_app2(ei_ext_cst("Result"), a, e)
1123}
1124pub fn ei_ext_sum(a: Expr, b: Expr) -> Expr {
1125 ei_ext_app2(ei_ext_cst("Sum"), a, b)
1126}
1127pub fn ei_ext_eq(a: Expr, x: Expr, y: Expr) -> Expr {
1128 ei_ext_app2(ei_ext_app(ei_ext_cst("Eq"), a), x, y)
1129}
1130pub fn ei_ext_axiom(env: &mut Environment, name: &str, ty: Expr) -> Result<(), String> {
1131 env.add(Declaration::Axiom {
1132 name: Name::str(name),
1133 univ_params: vec![],
1134 ty,
1135 })
1136 .map_err(|e| e.to_string())
1137}
1138pub fn ei_ext_forall_ab(body: Expr) -> Expr {
1139 ei_ext_ipi("α", ei_ext_type0(), ei_ext_ipi("β", ei_ext_type0(), body))
1140}
1141pub fn ei_ext_forall_abg(body: Expr) -> Expr {
1142 ei_ext_ipi(
1143 "α",
1144 ei_ext_type0(),
1145 ei_ext_ipi("β", ei_ext_type0(), ei_ext_ipi("γ", ei_ext_type0(), body)),
1146 )
1147}
1148pub fn ei_ext_forall_abgd(body: Expr) -> Expr {
1149 ei_ext_ipi(
1150 "α",
1151 ei_ext_type0(),
1152 ei_ext_ipi(
1153 "β",
1154 ei_ext_type0(),
1155 ei_ext_ipi("γ", ei_ext_type0(), ei_ext_ipi("δ", ei_ext_type0(), body)),
1156 ),
1157 )
1158}
1159pub fn ei_coproduct_inl(env: &mut Environment) -> Result<(), String> {
1161 let ty = ei_ext_forall_ab(ei_ext_arrow(
1162 ei_ext_bvar(1),
1163 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1164 ));
1165 ei_ext_axiom(env, "Either.inl", ty)
1166}
1167pub fn ei_coproduct_inr(env: &mut Environment) -> Result<(), String> {
1169 let ty = ei_ext_forall_ab(ei_ext_arrow(
1170 ei_ext_bvar(0),
1171 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1172 ));
1173 ei_ext_axiom(env, "Either.inr", ty)
1174}
1175pub fn ei_coproduct_universal(env: &mut Environment) -> Result<(), String> {
1178 let ty = ei_ext_forall_abg(ei_ext_dpi(
1179 "fl",
1180 ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(0)),
1181 ei_ext_dpi(
1182 "fr",
1183 ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(1)),
1184 ei_ext_dpi(
1185 "e",
1186 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1187 ei_ext_bvar(3),
1188 ),
1189 ),
1190 ));
1191 ei_ext_axiom(env, "Either.coprod", ty)
1192}
1193pub fn ei_bimap_id(env: &mut Environment) -> Result<(), String> {
1196 let ty = ei_ext_forall_ab(ei_ext_dpi(
1197 "e",
1198 ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0)),
1199 ei_ext_eq(
1200 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(2)),
1201 ei_ext_bvar(0),
1202 ei_ext_bvar(0),
1203 ),
1204 ));
1205 ei_ext_axiom(env, "Either.bimap_id", ty)
1206}
1207pub fn ei_bimap_comp(env: &mut Environment) -> Result<(), String> {
1209 ei_ext_axiom(env, "Either.bimap_comp", ei_ext_prop())
1210}
1211pub fn ei_bifunctor_left_comp(env: &mut Environment) -> Result<(), String> {
1213 ei_ext_axiom(env, "Either.mapLeft_comp", ei_ext_prop())
1214}
1215pub fn ei_bifunctor_right_comp(env: &mut Environment) -> Result<(), String> {
1217 ei_ext_axiom(env, "Either.map_comp", ei_ext_prop())
1218}
1219pub fn ei_monad_pure(env: &mut Environment) -> Result<(), String> {
1222 let ty = ei_ext_forall_ab(ei_ext_arrow(
1223 ei_ext_bvar(0),
1224 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1225 ));
1226 ei_ext_axiom(env, "Either.pure", ty)
1227}
1228pub fn ei_monad_bind(env: &mut Environment) -> Result<(), String> {
1231 let ty = ei_ext_forall_abg(ei_ext_dpi(
1232 "e",
1233 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1234 ei_ext_dpi(
1235 "f",
1236 ei_ext_arrow(
1237 ei_ext_bvar(1),
1238 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1239 ),
1240 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1241 ),
1242 ));
1243 ei_ext_axiom(env, "Either.bind", ty)
1244}
1245pub fn ei_monad_left_id(env: &mut Environment) -> Result<(), String> {
1247 ei_ext_axiom(env, "Either.bind_pure_left", ei_ext_prop())
1248}
1249pub fn ei_monad_right_id(env: &mut Environment) -> Result<(), String> {
1251 ei_ext_axiom(env, "Either.bind_pure_right", ei_ext_prop())
1252}
1253pub fn ei_monad_assoc(env: &mut Environment) -> Result<(), String> {
1255 ei_ext_axiom(env, "Either.bind_assoc", ei_ext_prop())
1256}
1257pub fn ei_applicative_ap(env: &mut Environment) -> Result<(), String> {
1259 let ty = ei_ext_forall_abg(ei_ext_dpi(
1260 "ef",
1261 ei_ext_either(ei_ext_bvar(2), ei_ext_arrow(ei_ext_bvar(1), ei_ext_bvar(0))),
1262 ei_ext_dpi(
1263 "ea",
1264 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(2)),
1265 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1266 ),
1267 ));
1268 ei_ext_axiom(env, "Either.ap", ty)
1269}
1270pub fn ei_applicative_hom(env: &mut Environment) -> Result<(), String> {
1272 ei_ext_axiom(env, "Either.ap_hom", ei_ext_prop())
1273}
1274pub fn ei_applicative_interchange(env: &mut Environment) -> Result<(), String> {
1276 ei_ext_axiom(env, "Either.ap_interchange", ei_ext_prop())
1277}
1278pub fn ei_alternative_alt(env: &mut Environment) -> Result<(), String> {
1281 let ty = ei_ext_forall_ab(ei_ext_dpi(
1282 "e1",
1283 ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0)),
1284 ei_ext_dpi(
1285 "e2",
1286 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1287 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(2)),
1288 ),
1289 ));
1290 ei_ext_axiom(env, "Either.alt", ty)
1291}
1292pub fn ei_iso_result_to(env: &mut Environment) -> Result<(), String> {
1294 let ty = ei_ext_forall_ab(ei_ext_arrow(
1295 ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0)),
1296 ei_ext_result(ei_ext_bvar(1), ei_ext_bvar(2)),
1297 ));
1298 ei_ext_axiom(env, "Either.toResult", ty)
1299}
1300pub fn ei_iso_result_from(env: &mut Environment) -> Result<(), String> {
1302 let ty = ei_ext_forall_ab(ei_ext_arrow(
1303 ei_ext_result(ei_ext_bvar(0), ei_ext_bvar(1)),
1304 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1305 ));
1306 ei_ext_axiom(env, "Either.fromResult", ty)
1307}
1308pub fn ei_iso_sum_to(env: &mut Environment) -> Result<(), String> {
1310 let ty = ei_ext_forall_ab(ei_ext_arrow(
1311 ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0)),
1312 ei_ext_sum(ei_ext_bvar(2), ei_ext_bvar(1)),
1313 ));
1314 ei_ext_axiom(env, "Either.toSum", ty)
1315}
1316pub fn ei_iso_sum_from(env: &mut Environment) -> Result<(), String> {
1318 let ty = ei_ext_forall_ab(ei_ext_arrow(
1319 ei_ext_sum(ei_ext_bvar(1), ei_ext_bvar(0)),
1320 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1321 ));
1322 ei_ext_axiom(env, "Either.fromSum", ty)
1323}
1324pub fn ei_traversable_traverse(env: &mut Environment) -> Result<(), String> {
1326 ei_ext_axiom(env, "Either.traverse", ei_ext_prop())
1327}
1328pub fn ei_traversable_law_pure(env: &mut Environment) -> Result<(), String> {
1330 ei_ext_axiom(env, "Either.traverse_pure", ei_ext_prop())
1331}
1332pub fn ei_traversable_law_naturality(env: &mut Environment) -> Result<(), String> {
1334 ei_ext_axiom(env, "Either.traverse_naturality", ei_ext_prop())
1335}
1336pub fn ei_foldable_foldl(env: &mut Environment) -> Result<(), String> {
1339 let ty = ei_ext_forall_abg(ei_ext_dpi(
1340 "f",
1341 ei_ext_arrow(ei_ext_bvar(0), ei_ext_arrow(ei_ext_bvar(1), ei_ext_bvar(1))),
1342 ei_ext_dpi(
1343 "z",
1344 ei_ext_bvar(1),
1345 ei_ext_dpi(
1346 "e",
1347 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1348 ei_ext_bvar(2),
1349 ),
1350 ),
1351 ));
1352 ei_ext_axiom(env, "Either.foldl", ty)
1353}
1354pub fn ei_foldable_foldr(env: &mut Environment) -> Result<(), String> {
1357 let ty = ei_ext_forall_abg(ei_ext_dpi(
1358 "f",
1359 ei_ext_arrow(ei_ext_bvar(1), ei_ext_arrow(ei_ext_bvar(1), ei_ext_bvar(1))),
1360 ei_ext_dpi(
1361 "z",
1362 ei_ext_bvar(1),
1363 ei_ext_dpi(
1364 "e",
1365 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1366 ei_ext_bvar(2),
1367 ),
1368 ),
1369 ));
1370 ei_ext_axiom(env, "Either.foldr", ty)
1371}
1372pub fn ei_profunctor_dimap(env: &mut Environment) -> Result<(), String> {
1375 let ty = ei_ext_forall_abgd(ei_ext_dpi(
1376 "fl",
1377 ei_ext_arrow(ei_ext_bvar(1), ei_ext_bvar(3)),
1378 ei_ext_dpi(
1379 "fr",
1380 ei_ext_arrow(ei_ext_bvar(3), ei_ext_bvar(1)),
1381 ei_ext_dpi(
1382 "e",
1383 ei_ext_either(ei_ext_bvar(5), ei_ext_bvar(4)),
1384 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(4)),
1385 ),
1386 ),
1387 ));
1388 ei_ext_axiom(env, "Either.dimap", ty)
1389}
1390pub fn ei_partition_lefts(env: &mut Environment) -> Result<(), String> {
1393 let ty = ei_ext_forall_ab(ei_ext_arrow(
1394 ei_ext_list(ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0))),
1395 ei_ext_list(ei_ext_bvar(2)),
1396 ));
1397 ei_ext_axiom(env, "Either.lefts", ty)
1398}
1399pub fn ei_partition_rights(env: &mut Environment) -> Result<(), String> {
1402 let ty = ei_ext_forall_ab(ei_ext_arrow(
1403 ei_ext_list(ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0))),
1404 ei_ext_list(ei_ext_bvar(1)),
1405 ));
1406 ei_ext_axiom(env, "Either.rights", ty)
1407}
1408pub fn ei_elim(env: &mut Environment) -> Result<(), String> {
1411 let ty = ei_ext_forall_abg(ei_ext_dpi(
1412 "fl",
1413 ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(0)),
1414 ei_ext_dpi(
1415 "fr",
1416 ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(1)),
1417 ei_ext_dpi(
1418 "e",
1419 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1420 ei_ext_bvar(3),
1421 ),
1422 ),
1423 ));
1424 ei_ext_axiom(env, "Either.elim", ty)
1425}
1426pub fn ei_swap_involution(env: &mut Environment) -> Result<(), String> {
1428 let ty = ei_ext_forall_ab(ei_ext_dpi(
1429 "e",
1430 ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0)),
1431 ei_ext_eq(
1432 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(2)),
1433 ei_ext_bvar(0),
1434 ei_ext_bvar(0),
1435 ),
1436 ));
1437 ei_ext_axiom(env, "Either.swap_involution", ty)
1438}
1439pub fn ei_tagged_union_tag(env: &mut Environment) -> Result<(), String> {
1442 let ty = ei_ext_forall_ab(ei_ext_arrow(
1443 ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0)),
1444 ei_ext_cst("Bool"),
1445 ));
1446 ei_ext_axiom(env, "Either.tag", ty)
1447}
1448pub fn ei_error_catch_left(env: &mut Environment) -> Result<(), String> {
1451 let ty = ei_ext_forall_abg(ei_ext_dpi(
1452 "e",
1453 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1454 ei_ext_dpi(
1455 "handler",
1456 ei_ext_arrow(
1457 ei_ext_bvar(3),
1458 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(3)),
1459 ),
1460 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(4)),
1461 ),
1462 ));
1463 ei_ext_axiom(env, "Either.catchLeft", ty)
1464}
1465pub fn ei_commutativity_iso(env: &mut Environment) -> Result<(), String> {
1467 ei_ext_axiom(env, "Either.comm_iso", ei_ext_prop())
1468}
1469pub fn ei_associativity_iso(env: &mut Environment) -> Result<(), String> {
1471 ei_ext_axiom(env, "Either.assoc_iso", ei_ext_prop())
1472}
1473pub fn ei_assoc_left(env: &mut Environment) -> Result<(), String> {
1475 let either_ab = ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1));
1476 let ty = ei_ext_forall_abg(ei_ext_dpi(
1477 "e",
1478 ei_ext_either(either_ab, ei_ext_bvar(0)),
1479 ei_ext_either(
1480 ei_ext_bvar(3),
1481 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(2)),
1482 ),
1483 ));
1484 ei_ext_axiom(env, "Either.assocLeft", ty)
1485}
1486pub fn ei_assoc_right(env: &mut Environment) -> Result<(), String> {
1488 let either_bg = ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0));
1489 let ty = ei_ext_forall_abg(ei_ext_dpi(
1490 "e",
1491 ei_ext_either(ei_ext_bvar(2), either_bg),
1492 ei_ext_either(
1493 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1494 ei_ext_bvar(2),
1495 ),
1496 ));
1497 ei_ext_axiom(env, "Either.assocRight", ty)
1498}
1499pub fn ei_void_elim_left(env: &mut Environment) -> Result<(), String> {
1502 let ty = ei_ext_ipi(
1503 "β",
1504 ei_ext_type0(),
1505 ei_ext_arrow(
1506 ei_ext_either(ei_ext_cst("Void"), ei_ext_bvar(0)),
1507 ei_ext_bvar(1),
1508 ),
1509 );
1510 ei_ext_axiom(env, "Either.elimVoidLeft", ty)
1511}
1512pub fn ei_void_intro_left(env: &mut Environment) -> Result<(), String> {
1514 let ty = ei_ext_ipi(
1515 "β",
1516 ei_ext_type0(),
1517 ei_ext_arrow(
1518 ei_ext_bvar(0),
1519 ei_ext_either(ei_ext_cst("Void"), ei_ext_bvar(1)),
1520 ),
1521 );
1522 ei_ext_axiom(env, "Either.introVoidLeft", ty)
1523}
1524pub fn ei_distrib_over_prod(env: &mut Environment) -> Result<(), String> {
1526 ei_ext_axiom(env, "Either.distrib_prod", ei_ext_prop())
1527}
1528pub fn ei_distrib_left(env: &mut Environment) -> Result<(), String> {
1530 let prod_bg = ei_ext_prod(ei_ext_bvar(1), ei_ext_bvar(0));
1531 let ty = ei_ext_forall_abg(ei_ext_dpi(
1532 "e",
1533 ei_ext_either(ei_ext_bvar(2), prod_bg),
1534 ei_ext_prod(
1535 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1536 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1537 ),
1538 ));
1539 ei_ext_axiom(env, "Either.distribLeft", ty)
1540}
1541pub fn ei_do_seq_bind(env: &mut Environment) -> Result<(), String> {
1544 let ty = ei_ext_forall_abg(ei_ext_dpi(
1545 "m",
1546 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1547 ei_ext_dpi(
1548 "f",
1549 ei_ext_arrow(
1550 ei_ext_bvar(1),
1551 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1552 ),
1553 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1554 ),
1555 ));
1556 ei_ext_axiom(env, "Either.seqBind", ty)
1557}
1558pub fn ei_kleisli_comp(env: &mut Environment) -> Result<(), String> {
1562 let ty = ei_ext_forall_abgd(ei_ext_dpi(
1563 "f",
1564 ei_ext_arrow(
1565 ei_ext_bvar(3),
1566 ei_ext_either(ei_ext_bvar(3), ei_ext_bvar(2)),
1567 ),
1568 ei_ext_dpi(
1569 "g",
1570 ei_ext_arrow(
1571 ei_ext_bvar(3),
1572 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1573 ),
1574 ei_ext_arrow(
1575 ei_ext_bvar(5),
1576 ei_ext_either(ei_ext_bvar(5), ei_ext_bvar(3)),
1577 ),
1578 ),
1579 ));
1580 ei_ext_axiom(env, "Either.kleisliComp", ty)
1581}
1582pub fn ei_kleisli_id(env: &mut Environment) -> Result<(), String> {
1584 ei_ext_axiom(env, "Either.kleisli_id_law", ei_ext_prop())
1585}
1586pub fn ei_eithert_run(env: &mut Environment) -> Result<(), String> {
1588 ei_ext_axiom(env, "EitherT.run", ei_ext_prop())
1589}
1590pub fn ei_eithert_lift(env: &mut Environment) -> Result<(), String> {
1592 ei_ext_axiom(env, "EitherT.lift", ei_ext_prop())
1593}
1594pub fn ei_eithert_bind(env: &mut Environment) -> Result<(), String> {
1596 ei_ext_axiom(env, "EitherT.bind", ei_ext_prop())
1597}
1598pub fn ei_sequence_list(env: &mut Environment) -> Result<(), String> {
1600 let ty = ei_ext_forall_ab(ei_ext_arrow(
1601 ei_ext_list(ei_ext_either(ei_ext_bvar(1), ei_ext_bvar(0))),
1602 ei_ext_either(ei_ext_bvar(2), ei_ext_list(ei_ext_bvar(1))),
1603 ));
1604 ei_ext_axiom(env, "Either.sequenceList", ty)
1605}
1606pub fn ei_traverse_list(env: &mut Environment) -> Result<(), String> {
1608 let ty = ei_ext_forall_abg(ei_ext_dpi(
1609 "f",
1610 ei_ext_arrow(
1611 ei_ext_bvar(1),
1612 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1613 ),
1614 ei_ext_dpi(
1615 "xs",
1616 ei_ext_list(ei_ext_bvar(2)),
1617 ei_ext_either(ei_ext_bvar(4), ei_ext_list(ei_ext_bvar(2))),
1618 ),
1619 ));
1620 ei_ext_axiom(env, "Either.traverseList", ty)
1621}
1622pub fn ei_select_combinator(env: &mut Environment) -> Result<(), String> {
1625 let ty = ei_ext_forall_abg(ei_ext_dpi(
1626 "e",
1627 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1628 ei_ext_dpi(
1629 "f",
1630 ei_ext_either(ei_ext_bvar(3), ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(1))),
1631 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(2)),
1632 ),
1633 ));
1634 ei_ext_axiom(env, "Either.select", ty)
1635}
1636pub fn ei_select_law_right(env: &mut Environment) -> Result<(), String> {
1638 ei_ext_axiom(env, "Either.select_right_law", ei_ext_prop())
1639}
1640pub fn ei_select_law_left(env: &mut Environment) -> Result<(), String> {
1642 ei_ext_axiom(env, "Either.select_left_law", ei_ext_prop())
1643}
1644pub fn ei_nat_sum(env: &mut Environment) -> Result<(), String> {
1647 let ty = ei_ext_arrow(
1648 ei_ext_nat_ty(),
1649 ei_ext_arrow(ei_ext_type0(), ei_ext_arrow(ei_ext_type0(), ei_ext_type0())),
1650 );
1651 ei_ext_axiom(env, "Either.natSum", ty)
1652}
1653pub fn ei_map_both(env: &mut Environment) -> Result<(), String> {
1655 let ty = ei_ext_forall_abg(ei_ext_dpi(
1656 "fl",
1657 ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(0)),
1658 ei_ext_dpi(
1659 "fr",
1660 ei_ext_arrow(ei_ext_bvar(2), ei_ext_bvar(1)),
1661 ei_ext_dpi(
1662 "e",
1663 ei_ext_either(ei_ext_bvar(4), ei_ext_bvar(3)),
1664 ei_ext_bvar(3),
1665 ),
1666 ),
1667 ));
1668 ei_ext_axiom(env, "Either.mapBoth", ty)
1669}
1670pub fn ei_join_with(env: &mut Environment) -> Result<(), String> {
1672 let ty = ei_ext_forall_ab(ei_ext_dpi(
1673 "f",
1674 ei_ext_arrow(ei_ext_bvar(1), ei_ext_bvar(0)),
1675 ei_ext_dpi(
1676 "e",
1677 ei_ext_either(ei_ext_bvar(2), ei_ext_bvar(1)),
1678 ei_ext_bvar(1),
1679 ),
1680 ));
1681 ei_ext_axiom(env, "Either.joinWith", ty)
1682}