//! Generic functional concepts implemented in Rust. //! Some choices are intentionally less generic due to specifics of the domain. //! That, for example, includes the almost exclusive focus on [`FnOnce`] category. //! //! Sources: //! * //! * //! * mod applicative_select; pub mod clone_func; mod controlflow; pub mod copy_func; pub mod derivations; pub mod instances; mod speculative; #[cfg(test)] pub mod test_suite; #[cfg(test)] pub mod tests; pub use std::ops::ControlFlow; pub use radn_derive::{CovariantFunctor, SharedFunctor}; pub use self::applicative_select::{ ApplicativeSelect, ApplicativeSelectExt, Selected, SelectedWrapped, }; use self::controlflow::{BindableMut, ControlFlowInstance}; pub use self::controlflow::{Iterative, IterativeWrapped}; #[cfg(doc)] use self::instances::stackless::StacklessInstance; /// Part of Haskell's `Functor f` responsible for having `f a`. /// /// pub trait WeakFunctor { /// Type of the wrapped value. type F<'a, A: 'a>: 'a where Self: 'a; } pub trait WeakFunctorA<'a>: 'a { type Fa: 'a; } impl<'a, T: 'a + WeakFunctor> WeakFunctorA<'a> for T { type Fa = T::F<'a, A>; } pub type Wrap<'a, A, T> = ::F<'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 VecInstance; /// /// impl WeakFunctor for VecInstance { /// type F<'a, A> = Vec; /// } /// /// impl Functor for VecInstance { /// 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 only `FnOnce`. /// /// For Haskell-style Functors, use [`clone_func::CloneFunctor`] instead. /// ``` /// use radn_rs::func::clone_func::*; /// /// struct VecInstance; /// /// impl CloneWeakFunctor for VecInstance { /// type ClF<'a, A: Clone> = Vec; /// } /// /// impl CloneFunctor for VecInstance { /// 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 { /// Equivalent or Haskell's `fmap`. /// Due to Rust limitations, it's not a `function->function` conversion. /// For that see [`derivations::fmap`]. 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; /// Equivalent of Haskell's `$>`/`<$`. 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) } /// Equivalent of Haskell's `void`. fn void<'a, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'a, ()> where Self: 'a, { Self::replace(fa, ()) } } /// Part of [`Applicative`] responsible for Haskell's value lifting, `pure`. pub trait Pure: Functor { /// Equivalent of Haskell's `pure`/`return`. fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> where Self: 'a; } /// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`. pub trait ApplicativeSeq: Functor { /// Equivalent of Haskell's `<*>`. 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; } /// Part of [`Applicative`] responsible for Haskell's result combination `listA2`. pub trait ApplicativeLA2: Functor { /// Equivalent of Haskell's `listA2`. 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; } /// Part of [`Applicative`] responsible for Rust-style result combination, specifically for tuples. pub trait ApplicativeTuple: Functor { /// Similar to Haskell's `listA2` but with [Iterator::collect]-ish semantics. fn tuple<'a, A: 'a, B: 'a>(fab: (Self::F<'a, A>, Self::F<'a, B>)) -> Self::F<'a, (A, B)> where Self: 'a; } /// Equivalent of Haskell's `Applicative`. /// Split into [`Pure`], [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations. /// /// pub trait Applicative: Pure + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple + ApplicativeSelect { /// Equivalent of Haskell's `*>`/`>>`. 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) } /// Equivalent of Haskell's `<*`. 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) } } /// Equivalent of Haskell's `Monad`. /// /// pub trait Monad: Applicative { /// Equivalent of Haskell's `>==`. /// Due to Rust limitations, it's not a `function->function` conversion. /// For that see [`derivations::bind`]. 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; /// Included for optimisation and clarity. /// Generally, [`Monad::bind`] should be enough implement it. /// See [`StacklessInstance::iterate`] for a generic, though less-than ideal, blanket implementation. /// On practice, you generally shouldn't be using [`Monad::bind`]/[`Pure::pure`]/[`Functor::fmap`] here. fn iterate<'a, B: 'a>(f: impl Iterative<'a, T = Self, B = B>) -> Self::F<'a, B> where Self: 'a; /// Equivalent of Haskell's `join`. fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> where Self: 'a, { Self::bind(ffa, |fa| fa) } } pub trait MonadExt<'a>: 'a + Monad { /// [`FnMut`] version of [`Monad::iterate`]. /// Reasoning for this method existing at all is that /// most usecases are better modelled with [`FnMut`] /// rather than some dedicated state type. fn iterate_mut( a: A, f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> { Self::iterate(BindableMut::new(a, f)) } } impl<'a, T: 'a + Monad> MonadExt<'a> for T {} /// Part of [`MonadFail`] responsible for Haskell's `fail`. pub trait Fail: WeakFunctor { /// Equivalent of Haskell's `fail`. fn fail<'a, A: 'a>(e: E) -> Self::F<'a, A> where Self: 'a, E: 'a; } /// Equivalent of Haskell's `MonadFail`. Auto-implemented for all [`Fail`]`+`[`Monad`]. /// /// pub trait MonadFail: Monad + Fail {} impl> MonadFail for T {} /// Represents wrapped results which are instantly available. pub trait LocalFunctor: WeakFunctor { /// Extract iteration state, if successful. fn unstuff<'a, A: 'a, B: 'a>( state: Self::F<'a, ControlFlow>, ) -> ControlFlow, A> where Self: 'a, { Self::stuff::<_, ControlFlowInstance>(state) } /// Stuff wrapped result into another functor. fn stuff<'a, A: 'a, T: 'a + Pure>(fa: Self::F<'a, T::F<'a, A>>) -> T::F<'a, Self::F<'a, A>> where Self: 'a; } /// Represents a (collection of) [Monad]\(s) that can hold any type of error. pub trait MonadFailAny { /// [`MonadFail`] for a specific error type. type W: MonadFail; /// Associated infallible [`Monad`]. type T: Monad; fn unstuff<'a, A: 'a, E: 'a>(wa: WrapE<'a, A, E, Self>) -> Wrap<'a, Result, Self::T> where Self: 'a; fn stuff<'a, A: 'a, E: 'a>(fa: Wrap<'a, Result, Self::T>) -> WrapE<'a, A, E, Self> where Self: 'a; /// Equivalent of [`Result::map_err`]. fn map_err<'a, A: 'a, E0: 'a, E1: 'a>( wa: WrapE<'a, A, E0, Self>, f: impl 'a + FnOnce(E0) -> E1, ) -> WrapE<'a, A, E1, Self> where Self: 'a, { Self::bind_err(wa, |e0| Self::fail(f(e0))) } /// Equivalent of `catch`/`except`. To inject errors on success, see [`MonadFailAny::bind`]. fn bind_err<'a, A: 'a, E0: 'a, E1: 'a>( wa: WrapE<'a, A, E0, Self>, f: impl 'a + FnOnce(E0) -> WrapE<'a, A, E1, Self>, ) -> WrapE<'a, A, E1, Self> where Self: 'a, { Self::bind(wa, |result| match result { Ok(a) => Self::pure(a), Err(e0) => f(e0), }) } /// Bind the result, an equivalent of `catch`/`except` with ability to "raise" extra errors /// on success too, unlike [`MonadFailAny::bind_err`]. /// /// Note: Reasonably it is expected to lack fail semantics for the underlying result. /// Therefore the default implementation descends into the non-fail monad [`MonadFailAny::T`]. fn bind<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( wa: WrapE<'a, A, E0, Self>, f: impl 'a + FnOnce(Result) -> WrapE<'a, B, E1, Self>, ) -> WrapE<'a, B, E1, Self> where Self: 'a, { Self::stuff(::bind(Self::unstuff(wa), |result| { Self::unstuff(f(result)) })) } /// Equivalent of [`Monad::join`], flattening the errors. /// /// Note: default implementation doesn't depend on [`Monad::join`]. fn join<'a, A: 'a, E0: 'a, E1: 'a>( wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>, ) -> WrapE<'a, A, Result, Self> where Self: 'a, { Self::bind(wwa, |result| match result { Ok(wa) => Self::map_err(wa, Ok), Err(e1) => Self::fail(Err(e1)), }) } /// Lift the error. fn rotate_out<'a, A: 'a, E0: 'a, E1: 'a>( wa: WrapE<'a, Result, E0, Self>, ) -> WrapE<'a, A, Result, Self> where Self: 'a, { > as Monad>::bind(Self::map_err(wa, Err), |fa| match fa { Ok(a) => Self::pure(a), Err(e) => Self::fail(Ok(e)), }) } } pub type WrapE<'a, A, E, Fallible> = Wrap<'a, A, ::W>; pub trait MonadFailAnyExt<'a>: 'a + MonadFailAny { fn pure(a: A) -> WrapE<'a, A, E, Self> { as Pure>::pure(a) } fn fail(e: E) -> WrapE<'a, A, E, Self> { as Fail>::fail(e) } fn speculative( wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>, wwb: WrapE<'a, WrapE<'a, B, E0, Self>, E1, Self>, ) -> WrapE<'a, (A, B), Result, Self> { >::speculative(wwa, wwb) } } impl<'a, Fallible: ?Sized + 'a + MonadFailAny> MonadFailAnyExt<'a> for Fallible {} pub trait SharedFunctor: WeakFunctor { type Shared<'a, A: 'a + Clone>: 'a + Clone where Self: 'a; fn share<'a, A: 'a + Clone>(fa: Self::F<'a, A>) -> Self::Shared<'a, A> where Self: 'a; fn unshare<'a, A: 'a + Clone>(sa: Self::Shared<'a, A>) -> Self::F<'a, A> where Self: 'a; } pub trait CovariantFunctor: WeakFunctor { fn variate<'a: 'b, 'b, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'b, A> where Self: 'a; }