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