radn-rs/src/func/derivations.rs

51 lines
1.5 KiB
Rust

//! 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: 'a + Functor, A: 'a, B: 'a>(
f: impl 'a + FnOnce(A) -> B,
) -> impl FnOnce(T::F<'a, A>) -> T::F<'a, B> {
move |fa| T::fmap(f, fa)
}
/// 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<'a, B>,
) -> impl FnOnce(T::F<'a, A>) -> T::F<'a, B> {
move |fa| T::bind(fa, f)
}
pub trait ApplicativeLA2ViaSeq<'a>: ApplicativeSeq<'a> {
fn _la2_via_seq<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C,
fa: Self::F<'a, A>,
fb: Self::F<'a, B>,
) -> Self::F<'a, C> {
Self::seq(Self::fmap(|a| |b| f(a, b), fa), fb)
}
}
impl<'a, T: ApplicativeSeq<'a>> ApplicativeLA2ViaSeq<'a> for T {}
pub trait ApplicativeSeqViaLA2<'a>: ApplicativeLA2<'a> {
fn _seq_via_la2<A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B> {
Self::la2(|f, a| f(a), ff, fa)
}
}
impl<'a, T: ApplicativeLA2<'a>> ApplicativeSeqViaLA2<'a> for T {}
pub trait ApplicativeTupleViaLA2<'a>: ApplicativeLA2<'a> {
fn _tuple_via_la2<A: 'a, B: 'a>(
(fa, fb): (Self::F<'a, A>, Self::F<'a, B>),
) -> Self::F<'a, (A, B)> {
Self::la2(|a, b| (a, b), fa, fb)
}
}
impl<'a, T: ApplicativeLA2<'a>> ApplicativeTupleViaLA2<'a> for T {}