pub mod classes;
pub mod clone_func;
pub mod copy_func;
#[cfg(test)]
pub mod test_suite;
#[cfg(test)]
pub mod tests;
pub trait WeakFunctor {
type F<'a, A: 'a> : 'a;
}
/// Rust-specific implementation of [Functor], respecting `move` semantics.
///
/// Cannot insantiate for e.g. multi-element collections:
/// ```compile_fail
/// use radn_rs::func::*;
///
/// struct VecClass;
///
/// impl WeakFunctor for VecClass {
/// type F<'a, A> = Vec;
/// }
///
/// impl Functor for VecClass {
/// fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B>
/// fa.into_iter().map(f).collect()
/// }
/// }
/// ```
/// Why does it fail to compile? `.map` expects `FnMut` (or we can think of it being `Fn`, doesn't matter here). But what we provide it (`f`) is
///
/// For Haskell-style Functors, use [clone_func::CloneFunctor] instead.
/// ```
/// use radn_rs::func::clone_func::*;
///
/// struct VecClass;
///
/// impl CloneWeakFunctor for VecClass {
/// type ClF<'a, A: Clone> = Vec;
/// }
///
/// impl CloneFunctor for VecClass {
/// fn clone_fmap<'a, A: 'a + Clone, B: 'a + Clone>(
/// f: impl 'a + Fn(A) -> B,
/// fa: Self::ClF<'a, A>,
/// ) -> Self::ClF<'a, B> {
/// fa.into_iter().map(f).collect()
/// }
/// }
/// ```
pub trait Functor: WeakFunctor {
fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B>
where
Self: 'a;
fn replace<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, b: B) -> Self::F<'a, B>
where
Self: 'a,
{
Self::fmap(|_| b, fa)
}
fn void<'a, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'a, ()>
where
Self: 'a,
{
Self::replace(fa, ())
}
}
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)
}
pub trait ApplicativeSeq: Functor {
fn seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
fn _la2<'a, 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>
where
Self: 'a,
{
Self::seq(Self::fmap(|a| |b| f(a, b), fa), fb)
}
}
pub trait ApplicativeLA2: Functor {
fn la2<'a, 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>
where
Self: 'a;
fn _seq<'a, A: 'a, B: 'a>(
ff: Self::F<'a, impl 'a + FnOnce(A) -> B>,
fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a,
{
Self::la2(|f, a| f(a), ff, fa)
}
}
pub trait Applicative: Functor + ApplicativeSeq + ApplicativeLA2 {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>;
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B>
where
Self: 'a,
{
Self::seq(Self::replace(fa, |b| b), fb)
}
fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A>
where
Self: 'a,
{
Self::la2(|a, _| a, fa, fb)
}
}
pub trait Monad: Applicative {
fn bind<'a, A: 'a, B: 'a>(
fa: Self::F<'a, A>,
f: impl 'a + FnOnce(A) -> Self::F<'a, B>,
) -> Self::F<'a, B>
where
Self: 'a;
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
where
Self::F<'a, A>: 'a,
Self: 'a,
{
Self::bind(ffa, |fa| fa)
}
}
pub trait MonadFail: Monad {
fn fail<'a, A>(e: E) -> Self::F<'a, A>;
}
pub trait Alternative: Applicative {
fn empty<'a, A>() -> Self::F<'a, A>;
fn add<'a, A>(fa: Self::F<'a, A>, fb: Self::F<'a, A>) -> Self::F<'a, A>;
}