//! 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, B: 'a>( f: impl 'a + 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, B: 'a>( f: impl 'a + FnOnce(A) -> T::F, ) -> 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( f: impl 'a + FnOnce(A, B) -> C, fa: Self::F, fb: Self::F, ) -> Self::F { 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( ff: Self::F B>, fa: Self::F, ) -> Self::F { 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((fa, fb): (Self::F, Self::F)) -> Self::F<(A, B)> { Self::la2(fa, fb, |a, b| (a, b)) } } impl<'a, T: ApplicativeLA2<'a>> ApplicativeTupleViaLA2<'a> for T {}