exclusive_choice/
lib.rs

1pub mod derivatives;
2use derivatives::*;
3
4/// Dynamism bootstrapper for Choice
5pub trait DynChoice {
6    type Left;
7    type Right;
8    /// Convert into `A`
9    fn into_left(self: Box<Self>) -> Self::Left;
10
11    /// Convert into `B`
12    fn into_right(self: Box<Self>) -> Self::Right;
13}
14
15/// Represents the affine negation of `Either`.
16///
17/// It represents a conjunctive union.
18pub trait Choice: DynChoice + Sized {
19    /// Convert into `A`
20    fn left(self: Self) -> Self::Left;
21    /// Convert into `B`
22    fn right(self: Self) -> Self::Right;
23
24    /// Maps the left value.
25    ///
26    /// This treats Choice as a functor in the left type.
27    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    /// Maps the right value.
35    ///
36    /// This treats Choice as a functor in the right type.
37    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    /// Maps both values.
45    ///
46    /// This treats Choice as a functor in both the left and right types.
47    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    /// Composes a choice of values with a choice of functions to produce a choice of values.
56    ///
57    /// This sequences the choices in a way that is unique to the structure of a choice.
58    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    /// Sets the left value to a map from the current state to be ran if chosen.
70    ///
71    /// This treats Choice as a co-monad in the left type.
72    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    /// Sets the right value to a map from the current state to be ran if chosen.
80    ///
81    /// This treats Choice as a co-monad in the right type.
82    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    /// Swaps the left and right values.
90    fn swap(self) -> Swap<Self> {
91        Swap { choice: self }
92    }
93
94    /// Composes a choice of values with an either of functions to produce a single value.
95    ///
96    /// The composition of a choice with its linear negative annihilates both.
97    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/// A choice between filterning eithers by branch.
122#[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    /// Creates an iterator that filters for left.
138    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    /// Creates an iterator that filters for right.
147    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/// Stores a DynChoice with indirection so that Choice can be implemented
196#[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/// A choice with both branches identical.
221#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
222pub struct Same<A> {
223    val: A,
224}
225
226impl<A> Same<A> {
227    /// Constructs a choice with both branches identical.
228    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/// A choice with both branches already inhabited.
247#[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    /// Constructs a choice with both branches already inhabited.
255    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/// A choice using with lazy expressions.
274#[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    /// Constructs a choice using lazy expressions.
282    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/// A choice with a common resource.
301#[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    /// Constructs a choice with a common resource.
310    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
332/// An Exclusive choice implemented using function pointers.
333pub type ExclusiveFn<T, A, B> = Exclusive<T, fn(T) -> A, fn(T) -> B>;
334
335/// A type with two possile states, `Left` or `Right`.
336///
337/// It represents a disjunctive union.
338#[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    /// Chooses the branch of the either dependent on the boolean provided.
346    ///
347    /// - `true` creates `Left`.
348    /// - `false` creates `Right`.
349    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    /// Sets the left branch from a result assuming `Ok`, otherwise if `Err` sets the right branch instead.
362    pub fn ok_into_left(result: Result<A, B>) -> Either<A, B> {
363        result.map_or_else(Either::Right, Either::Left)
364    }
365
366    /// Sets the right branch from a result assuming `Ok`, otherwise if `Err` sets the left branch instead.
367    pub fn ok_into_right(result: Result<B, A>) -> Either<A, B> {
368        result.map_or_else(Either::Left, Either::Right)
369    }
370
371    /// Moves out of the either, if left then the result is `Ok`, otherwise the result is an `Err`.
372    pub fn left(self) -> Result<A, B> {
373        self.either(Result::Ok, Result::Err)
374    }
375
376    /// Moves out of the either, if right then the result is `Ok`, otherwise the result is an `Err`.
377    pub fn right(self) -> Result<B, A> {
378        self.either(Result::Err, Result::Ok)
379    }
380
381    /// Converts from `&Either<A, B>` to `Either<&A, &B>`
382    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    /// Converts from `&mut Either<A, B>` to `Either<&mut A, &mut B>`
390    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    /// Maps the left value.
398    ///
399    /// This treats Either as a functor in the left type.
400    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    /// Maps the left value.
405    ///
406    /// This treats Either as a functor in the right type.
407    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    /// Maps both values.
412    ///
413    /// This treats Either as a functor in both the left and right types.
414    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    /// Composes an either with a choice of functions to produce an either of values.
423    ///
424    /// This sequences the either and choice in a way that is unique to their structures.
425    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    /// Composes an either with a choice of values to produce an either of values.
436    ///
437    /// This sequences the either and choice in a way that is unique to their structures.
438    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    /// Maps the left if present to create a new either.
443    ///
444    /// This treats Either as a monad in the left type.
445    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    /// Maps the right if present to create a new either.
450    ///
451    /// This treats Either as a monad in the right type.
452    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    /// Swaps the left and right values.
457    pub fn swap(self) -> Either<B, A> {
458        self.either(Either::Right, Either::Left)
459    }
460
461    /// Handles each case of the either to produce a single value.
462    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    /// Composes an either with a choice of functions to produce a single value.
467    ///
468    /// The composition of an either with its linear negative annihilates both.
469    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    /// Converts a consumer of an either into a choice of consumers.
480    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    /// Converts a choice of consumers into a consumer of an either.
491    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    /// Consume an either with branches of same type to produce a single value.
503    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}