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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//! Useful helper functions/methods to extrapolate the existing behaviour.

use super::*;

/// Equivalent of Haskell's `fmap`. `function-function` equivalent of [Functor::fmap].
pub fn fmap<'a, T: Functor<'a>, A: 'a + Send, B: 'a + Send>(
    f: impl 'a + Send + FnOnce(A) -> B,
) -> impl FnOnce(Wrap<'a, A, T>) -> Wrap<'a, B, T> {
    move |fa| T::fmap(fa, f)
}

/// Equivalent of Haskell's `fmap`. `function-function` equivalent of [Monad::bind].
pub fn bind<'a, T: Monad<'a>, A: 'a + Send, B: 'a + Send>(
    f: impl 'a + Send + FnOnce(A) -> T::F<B>,
) -> impl FnOnce(Wrap<'a, A, T>) -> Wrap<'a, B, T> {
    move |fa| T::bind(fa, f)
}

pub trait ApplicativeLA2ViaSeq<'a>: ApplicativeSeq<'a> {
    fn la2_via_seq<A: 'a + Send, B: 'a + Send, C: 'a + Send>(
        f: impl 'a + Send + FnOnce(A, B) -> C,
        fa: Self::F<A>,
        fb: Self::F<B>,
    ) -> Self::F<C> {
        Self::seq(Self::fmap(fa, |a| |b| f(a, b)), fb)
    }
}

impl<'a, T: ApplicativeSeq<'a>> ApplicativeLA2ViaSeq<'a> for T {}

pub trait ApplicativeSeqViaLA2<'a>: ApplicativeLA2<'a> {
    fn seq_via_la2<A: 'a + Send, B: 'a + Send>(
        ff: Self::F<impl 'a + Send + FnOnce(A) -> B>,
        fa: Self::F<A>,
    ) -> Self::F<B> {
        Self::la2(ff, fa, |f, a| f(a))
    }
}

impl<'a, T: ApplicativeLA2<'a>> ApplicativeSeqViaLA2<'a> for T {}

pub trait ApplicativeTupleViaLA2<'a>: ApplicativeLA2<'a> {
    fn tuple_via_la2<A: 'a + Send, B: 'a + Send>(
        (fa, fb): (Self::F<A>, Self::F<B>),
    ) -> Self::F<(A, B)> {
        Self::la2(fa, fb, |a, b| (a, b))
    }
}

impl<'a, T: ApplicativeLA2<'a>> ApplicativeTupleViaLA2<'a> for T {}