1pub mod derivatives;
2use derivatives::*;
3
4pub trait DynChoice {
6 type Left;
7 type Right;
8 fn into_left(self: Box<Self>) -> Self::Left;
10
11 fn into_right(self: Box<Self>) -> Self::Right;
13}
14
15pub trait Choice: DynChoice + Sized {
19 fn left(self: Self) -> Self::Left;
21 fn right(self: Self) -> Self::Right;
23
24 fn map_left<C, F: FnOnce(Self::Left) -> C>(
28 self,
29 left: F,
30 ) -> ChooseMap<Self, Both<F, fn(Self::Right) -> Self::Right>> {
31 self.map_both(left, std::convert::identity)
32 }
33
34 fn map_right<C, G: FnOnce(Self::Right) -> C>(
38 self,
39 right: G,
40 ) -> ChooseMap<Self, Both<fn(Self::Left) -> Self::Left, G>> {
41 self.map_both(std::convert::identity, right)
42 }
43
44 fn map_both<C, D, F: FnOnce(Self::Left) -> C, G: FnOnce(Self::Right) -> D>(
48 self,
49 left: F,
50 right: G,
51 ) -> ChooseMap<Self, Both<F, G>> {
52 self.choose_map(Both::new(left, right))
53 }
54
55 fn choose_map<T: Choice, C, D>(self, choice: T) -> ChooseMap<Self, T>
59 where
60 T::Left: FnOnce(Self::Left) -> C,
61 T::Right: FnOnce(Self::Right) -> D,
62 {
63 ChooseMap {
64 choice: self,
65 other: choice,
66 }
67 }
68
69 fn cobind_left<C, F: FnOnce(Self) -> C>(self, left: F) -> LeftCoBind<Self, F> {
73 LeftCoBind {
74 choice: self,
75 cobind: left,
76 }
77 }
78
79 fn cobind_right<C, G: FnOnce(Self) -> C>(self, right: G) -> RightCoBind<Self, G> {
83 RightCoBind {
84 choice: self,
85 cobind: right,
86 }
87 }
88
89 fn swap(self) -> Swap<Self> {
91 Swap { choice: self }
92 }
93
94 fn choose<C, F: FnOnce(Self::Left) -> C, G: FnOnce(Self::Right) -> C>(
98 self,
99 either: Either<F, G>,
100 ) -> C {
101 match either {
102 Either::Left(f) => (f)(self.left()),
103 Either::Right(g) => (g)(self.right()),
104 }
105 }
106}
107
108impl<A, B> DynChoice for Box<dyn DynChoice<Left = A, Right = B>> {
109 type Left = A;
110 type Right = B;
111
112 fn into_left(self: Box<Self>) -> A {
113 (*self).into_left()
114 }
115
116 fn into_right(self: Box<Self>) -> B {
117 (*self).into_right()
118 }
119}
120
121#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
123pub struct IterChoice<I> {
124 iter: I,
125}
126
127impl<I> IterChoice<I> {
128 pub fn new(iter: I) -> IterChoice<I> {
129 IterChoice { iter }
130 }
131}
132
133impl<I: Iterator<Item = Either<A, B>>, A, B> DynChoice for IterChoice<I> {
134 type Left = LeftFilterIter<I, A, B>;
135 type Right = RightFilterIter<I, A, B>;
136
137 fn into_left(self: Box<Self>) -> LeftFilterIter<I, A, B> {
139 LeftFilterIter {
140 iter: self.iter,
141 _l: std::marker::PhantomData,
142 _r: std::marker::PhantomData,
143 }
144 }
145
146 fn into_right(self: Box<Self>) -> RightFilterIter<I, A, B> {
148 RightFilterIter {
149 iter: self.iter,
150 _l: std::marker::PhantomData,
151 _r: std::marker::PhantomData,
152 }
153 }
154}
155
156impl<A, B> DynChoice for Vec<Either<A, B>> {
157 type Left = Vec<A>;
158 type Right = Vec<B>;
159
160 fn into_left(self: Box<Self>) -> Vec<A> {
161 IterChoice::new((*self).into_iter()).left().collect()
162 }
163
164 fn into_right(self: Box<Self>) -> Vec<B> {
165 IterChoice::new((*self).into_iter()).right().collect()
166 }
167}
168
169impl<A, B> DynChoice for Box<[Either<A, B>]> {
170 type Left = Box<[A]>;
171 type Right = Box<[B]>;
172
173 fn into_left(self: Box<Self>) -> Box<[A]> {
174 (*self).into_vec().left().into_boxed_slice()
175 }
176
177 fn into_right(self: Box<Self>) -> Box<[B]> {
178 (*self).into_vec().right().into_boxed_slice()
179 }
180}
181
182impl<T> Choice for T
183where
184 T: DynChoice + Sized,
185{
186 fn left(self: Self) -> T::Left {
187 Box::new(self).into_left()
188 }
189
190 fn right(self: Self) -> T::Right {
191 Box::new(self).into_right()
192 }
193}
194
195#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
197pub struct BoxedChoice<C: ?Sized> {
198 choice: Box<C>,
199}
200
201impl<C: ?Sized> BoxedChoice<C> {
202 pub fn new(choice: Box<C>) -> BoxedChoice<C> {
203 BoxedChoice { choice }
204 }
205}
206
207impl<C: ?Sized + DynChoice> DynChoice for BoxedChoice<C> {
208 type Left = C::Left;
209 type Right = C::Right;
210
211 fn into_left(self: Box<Self>) -> C::Left {
212 self.choice.into_left()
213 }
214
215 fn into_right(self: Box<Self>) -> C::Right {
216 self.choice.into_right()
217 }
218}
219
220#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
222pub struct Same<A> {
223 val: A,
224}
225
226impl<A> Same<A> {
227 pub fn new(val: A) -> Same<A> {
229 Same { val }
230 }
231}
232
233impl<A> DynChoice for Same<A> {
234 type Left = A;
235 type Right = A;
236
237 fn into_left(self: Box<Self>) -> A {
238 self.val
239 }
240
241 fn into_right(self: Box<Self>) -> A {
242 self.val
243 }
244}
245
246#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
248pub struct Both<A, B> {
249 left: A,
250 right: B,
251}
252
253impl<A, B> Both<A, B> {
254 pub fn new(left: A, right: B) -> Both<A, B> {
256 Both { left, right }
257 }
258}
259
260impl<A, B> DynChoice for Both<A, B> {
261 type Left = A;
262 type Right = B;
263
264 fn into_left(self: Box<Self>) -> A {
265 self.left
266 }
267
268 fn into_right(self: Box<Self>) -> B {
269 self.right
270 }
271}
272
273#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
275pub struct Lazy<A, B, F: FnOnce() -> A, G: FnOnce() -> B> {
276 left: F,
277 right: G,
278}
279
280impl<A, B, F: FnOnce() -> A, G: FnOnce() -> B> Lazy<A, B, F, G> {
281 pub fn new(left: F, right: G) -> Lazy<A, B, F, G> {
283 Lazy { left, right }
284 }
285}
286
287impl<A, B, F: FnOnce() -> A, G: FnOnce() -> B> DynChoice for Lazy<A, B, F, G> {
288 type Left = A;
289 type Right = B;
290
291 fn into_left(self: Box<Self>) -> A {
292 (self.left)()
293 }
294
295 fn into_right(self: Box<Self>) -> B {
296 (self.right)()
297 }
298}
299
300#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
302pub struct Exclusive<T, F, G> {
303 common: T,
304 left: F,
305 right: G,
306}
307
308impl<T, A, B, F: FnOnce(T) -> A, G: FnOnce(T) -> B> Exclusive<T, F, G> {
309 pub fn new(common: T, left: F, right: G) -> Exclusive<T, F, G> {
311 Exclusive {
312 common,
313 left,
314 right,
315 }
316 }
317}
318
319impl<T, A, B, F: FnOnce(T) -> A, G: FnOnce(T) -> B> DynChoice for Exclusive<T, F, G> {
320 type Left = A;
321 type Right = B;
322
323 fn into_left(self: Box<Self>) -> A {
324 (self.left)(self.common)
325 }
326
327 fn into_right(self: Box<Self>) -> B {
328 (self.right)(self.common)
329 }
330}
331
332pub type ExclusiveFn<T, A, B> = Exclusive<T, fn(T) -> A, fn(T) -> B>;
334
335#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
339pub enum Either<A, B> {
340 Left(A),
341 Right(B),
342}
343
344impl<A, B> Either<A, B> {
345 pub fn branch(choice: bool) -> Either<A, B>
350 where
351 A: Default,
352 B: Default,
353 {
354 if choice {
355 Either::Left(Default::default())
356 } else {
357 Either::Right(Default::default())
358 }
359 }
360
361 pub fn ok_into_left(result: Result<A, B>) -> Either<A, B> {
363 result.map_or_else(Either::Right, Either::Left)
364 }
365
366 pub fn ok_into_right(result: Result<B, A>) -> Either<A, B> {
368 result.map_or_else(Either::Left, Either::Right)
369 }
370
371 pub fn left(self) -> Result<A, B> {
373 self.either(Result::Ok, Result::Err)
374 }
375
376 pub fn right(self) -> Result<B, A> {
378 self.either(Result::Err, Result::Ok)
379 }
380
381 pub fn as_ref(&self) -> Either<&A, &B> {
383 match self {
384 Either::Left(a) => Either::Left(a),
385 Either::Right(b) => Either::Right(b),
386 }
387 }
388
389 pub fn as_mut(&mut self) -> Either<&mut A, &mut B> {
391 match self {
392 Either::Left(a) => Either::Left(a),
393 Either::Right(b) => Either::Right(b),
394 }
395 }
396
397 pub fn map_left<C>(self, left: impl FnOnce(A) -> C) -> Either<C, B> {
401 self.map_either(left, std::convert::identity)
402 }
403
404 pub fn map_right<C>(self, right: impl FnOnce(B) -> C) -> Either<A, C> {
408 self.map_either(std::convert::identity, right)
409 }
410
411 pub fn map_either<C, D>(
415 self,
416 left: impl FnOnce(A) -> C,
417 right: impl FnOnce(B) -> D,
418 ) -> Either<C, D> {
419 self.choose_map(Both::new(left, right))
420 }
421
422 pub fn choose_map<C, D, F: FnOnce(A) -> C, G: FnOnce(B) -> D>(
426 self,
427 choice: impl Choice<Left = F, Right = G>,
428 ) -> Either<C, D> {
429 match self {
430 Either::Left(a) => Either::Left((choice.left())(a)),
431 Either::Right(b) => Either::Right((choice.right())(b)),
432 }
433 }
434
435 pub fn compose<C, D>(self, choice: impl Choice<Left = C, Right = D>) -> Either<(A, C), (B, D)> {
439 self.choose_map(choice.map_both(|c| move |a| (a, c), |d| move |b| (b, d)))
440 }
441
442 pub fn bind_left<C>(self, left: impl FnOnce(A) -> Either<C, B>) -> Either<C, B> {
446 self.either(left, Either::Right)
447 }
448
449 pub fn bind_right<C>(self, right: impl FnOnce(B) -> Either<A, C>) -> Either<A, C> {
453 self.either(Either::Left, right)
454 }
455
456 pub fn swap(self) -> Either<B, A> {
458 self.either(Either::Right, Either::Left)
459 }
460
461 pub fn either<C>(self, left: impl FnOnce(A) -> C, right: impl FnOnce(B) -> C) -> C {
463 self.choose_either(Both::new(left, right))
464 }
465
466 pub fn choose_either<C, F: FnOnce(A) -> C, G: FnOnce(B) -> C>(
470 self,
471 choice: impl Choice<Left = F, Right = G>,
472 ) -> C {
473 match self {
474 Either::Left(a) => (choice.left())(a),
475 Either::Right(b) => (choice.right())(b),
476 }
477 }
478
479 pub fn factor<C, F: FnOnce(Either<A, B>) -> C>(
481 consumer: F,
482 ) -> ExclusiveFn<F, impl FnOnce(A) -> C, impl FnOnce(B) -> C> {
483 Exclusive::new(
484 consumer,
485 |consumer| move |a| (consumer)(Either::Left(a)),
486 |consumer| move |b| (consumer)(Either::Right(b)),
487 )
488 }
489
490 pub fn distribute<C, F: FnOnce(A) -> C, G: FnOnce(B) -> C>(
492 choice: impl Choice<Left = F, Right = G>,
493 ) -> impl FnOnce(Either<A, B>) -> C {
494 move |either| match either {
495 Either::Left(a) => choice.left()(a),
496 Either::Right(b) => choice.right()(b),
497 }
498 }
499}
500
501impl<A> Either<A, A> {
502 pub fn converge(self) -> A {
504 self.either(std::convert::identity, std::convert::identity)
505 }
506}
507
508#[cfg(test)]
509mod test {
510 use super::*;
511
512 #[test]
513 fn test_swap() {
514 let a = Both::new(0, 1);
515 let b = Both::new(2, 3);
516 let ab = (a, b.swap());
517 assert_eq!(ab.left(), (0, 3))
518 }
519
520 #[test]
521 fn test_either_map() {
522 let mut a = Either::Left(0);
523 a = a.map_right(|x: i32| x + 1);
524 assert_eq!(a.as_ref(), Either::Left(&0));
525 a = a.map_left(|x: i32| x + 1);
526 assert_eq!(a.as_ref(), Either::Left(&1));
527 a = a.map_either(|x| x * 2, |x| x * 3);
528 assert_eq!(a, Either::Left(2));
529
530 let mut b = Either::Right(0);
531 b = b.map_left(|x: i32| x + 1);
532 assert_eq!(b.as_ref(), Either::Right(&0));
533 b = b.map_right(|x: i32| x + 1);
534 assert_eq!(b.as_ref(), Either::Right(&1));
535 b = b.map_either(|x| x * 2, |x| x * 3);
536 assert_eq!(b, Either::Right(3))
537 }
538
539 #[test]
540 fn test_choice_map() {
541 let a = Both::new(1, -1).map_right(|x: i32| x - 1);
542 assert_eq!(a.left(), 1);
543 assert_eq!(a.right(), -2);
544 let a = a.map_left(|x: i32| x + 1);
545 assert_eq!(a.left(), 2);
546 assert_eq!(a.right(), -2);
547 let a = a.map_both(|x| x * 2, |x| x * 3);
548 assert_eq!(a.left(), 4);
549 assert_eq!(a.right(), -6)
550 }
551
552 #[test]
553 fn test_composition() {
554 let a = Both::new(0, 1).choose_map(Both::new(|x| x + 1, |x| x - 1));
555 assert_eq!(a.left(), 1);
556 assert_eq!(a.right(), 0);
557 assert_eq!(
558 Both::new(0, 1).choose(Either::<fn(i32) -> i32, fn(i32) -> i32>::Left(
559 |x: i32| x + 1
560 )),
561 1
562 );
563 assert_eq!(
564 Both::new(0, 1).choose(Either::<fn(i32) -> i32, fn(i32) -> i32>::Right(
565 |x: i32| x - 1
566 )),
567 0
568 )
569 }
570
571 #[test]
572 fn test_bind() {
573 fn test_left(a: Either<i32, i32>, b: Either<i32, i32>) -> Either<i32, i32> {
574 a.bind_left(|x| b.map_left(move |y| x + y))
575 }
576 assert_eq!(test_left(Either::Left(1), Either::Left(2)), Either::Left(3));
577 assert_eq!(
578 test_left(Either::Left(1), Either::Right(-2)),
579 Either::Right(-2)
580 );
581 assert_eq!(
582 test_left(Either::Right(-1), Either::Left(2)),
583 Either::Right(-1)
584 );
585 assert_eq!(
586 test_left(Either::Right(-1), Either::Right(-2)),
587 Either::Right(-1)
588 );
589 fn test_right(a: Either<i32, i32>, b: Either<i32, i32>) -> Either<i32, i32> {
590 a.bind_right(|x| b.map_right(move |y| x + y))
591 }
592 assert_eq!(
593 test_right(Either::Right(-1), Either::Right(-2)),
594 Either::Right(-3)
595 );
596 assert_eq!(
597 test_right(Either::Right(-1), Either::Left(2)),
598 Either::Left(2)
599 );
600 assert_eq!(
601 test_right(Either::Left(1), Either::Right(-2)),
602 Either::Left(1)
603 );
604 assert_eq!(
605 test_right(Either::Left(1), Either::Left(2)),
606 Either::Left(1)
607 )
608 }
609
610 #[test]
611 fn test_cobind() {
612 let a = Both::new(1, -1);
613 assert_eq!(a.cobind_left(|x| x.left()).left(), 1);
614 assert_eq!(a.cobind_left(|x| x.left()).right(), -1);
615 assert_eq!(a.cobind_left(|x| x.right()).left(), -1);
616 assert_eq!(a.cobind_left(|x| x.right()).right(), -1);
617 assert_eq!(a.cobind_right(|x| x.left()).left(), 1);
618 assert_eq!(a.cobind_right(|x| x.left()).right(), 1);
619 assert_eq!(a.cobind_right(|x| x.right()).left(), 1);
620 assert_eq!(a.cobind_right(|x| x.right()).right(), -1)
621 }
622
623 #[test]
624 fn test_filtering() {
625 let a: Vec<Either<i32, i32>> = vec![
626 Either::Left(0),
627 Either::Right(1),
628 Either::Left(2),
629 Either::Right(3),
630 Either::Left(4),
631 ];
632 assert_eq!(
633 IterChoice::new(a.iter().map(|x| x.as_ref()))
634 .left()
635 .map(|x| x.clone())
636 .collect::<Vec<i32>>(),
637 vec![0, 2, 4]
638 );
639 assert_eq!(
640 IterChoice::new(a.iter().map(|x| x.as_ref()))
641 .right()
642 .map(|x| x.clone())
643 .collect::<Vec<i32>>(),
644 vec![1, 3]
645 );
646 assert_eq!(a.clone().left(), vec![0, 2, 4]);
647 assert_eq!(a.right(), vec![1, 3]);
648 }
649
650 #[test]
651 fn test_factor_distribute() {
652 assert_eq!(
653 Either::<i32, i32>::factor(std::convert::identity).left()(0),
654 Either::Left(0)
655 );
656 assert_eq!(
657 Either::<i32, i32>::factor(std::convert::identity).right()(1),
658 Either::Right(1)
659 );
660 assert_eq!(
661 Either::<i32, i32>::distribute(Either::<i32, i32>::factor(std::convert::identity))(
662 Either::Left(0)
663 ),
664 Either::Left(0)
665 );
666 assert_eq!(
667 Either::<i32, i32>::distribute(Either::<i32, i32>::factor(std::convert::identity))(
668 Either::Right(1)
669 ),
670 Either::Right(1)
671 );
672 }
673}