1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use super::*;

pub enum Selected<'a, A: 'a + Send, B: 'a + Send, T: ?Sized + WeakFunctor<'a>> {
    A(A, T::F<B>),
    B(T::F<A>, B),
}

/// See [`ApplicativeSelect::select`].
pub type SelectedWrapped<'a, A, B, T> = Wrap<'a, Selected<'a, A, B, T>, T>;

/// Part of [`Applicative`] responsible for choosing the first value.
pub trait ApplicativeSelect<'a>: Functor<'a> {
    fn select<A: 'a + Send, B: 'a + Send>(
        fa: Self::F<A>,
        fb: Self::F<B>,
    ) -> SelectedWrapped<'a, A, B, Self> {
        Self::fmap(fa, |a| Selected::A(a, fb))
    }
}

pub trait ApplicativeSelectExt<'a>: ApplicativeSelect<'a> {
    /// Shorthand for [`Functor::fmap`]&#8728;[`ApplicativeSelect::select`].
    fn select_map<A: 'a + Send, B: 'a + Send, C: 'a + Send>(
        fa: Self::F<A>,
        fb: Self::F<B>,
        f: impl 'a + Send + FnOnce(Selected<'a, A, B, Self>) -> C,
    ) -> Self::F<C> {
        Self::fmap(Self::select(fa, fb), f)
    }
}

impl<'a, T: ApplicativeSelect<'a>> ApplicativeSelectExt<'a> for T {}