//! 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; #[cfg(test)] pub mod test_suite; #[cfg(test)] pub mod tests; pub use std::ops::ControlFlow; pub use radn_derive::SharedFunctorAny; 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; pub trait WeakFunctorAny { /// Type of the wrapped value. type FAny<'a, A: 'a>: 'a where Self: 'a; } /// Part of Haskell's `Functor f` responsible for having `f a`. /// /// pub trait WeakFunctor<'a>: 'a { type F: 'a; } impl<'a, T: ?Sized + 'a + WeakFunctorAny> WeakFunctor<'a> for T { type F = T::FAny<'a, A>; } pub type Wrap<'a, A, T> = >::F; /// Rust-specific implementation of [`Functor`], respecting `move` semantics. /// /// pub trait Functor<'a>: WeakFunctor<'a> { /// Equivalent or Haskell's `fmap`. /// Due to Rust limitations, it's not a `function->function` conversion. /// For that see [`derivations::fmap`]. fn fmap(f: impl 'a + FnOnce(A) -> B, fa: Self::F) -> Self::F; /// Equivalent of Haskell's `$>`/`<$`. fn replace(fa: Self::F, b: B) -> Self::F { Self::fmap(|_| b, fa) } /// Equivalent of Haskell's `void`. fn void(fa: Self::F) -> Self::F<()> { Self::replace(fa, ()) } } /// Part of [`Applicative`] responsible for Haskell's value lifting, `pure`. pub trait Pure<'a>: Functor<'a> { /// Equivalent of Haskell's `pure`/`return`. fn pure(a: A) -> Self::F; } /// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`. pub trait ApplicativeSeq<'a>: Functor<'a> { /// Equivalent of Haskell's `<*>`. fn seq(ff: Self::F B>, fa: Self::F) -> Self::F; } /// Part of [`Applicative`] responsible for Haskell's result combination `listA2`. pub trait ApplicativeLA2<'a>: Functor<'a> { /// Equivalent of Haskell's `listA2`. fn la2( fa: Self::F, fb: Self::F, f: impl 'a + FnOnce(A, B) -> C, ) -> Self::F; } /// Part of [`Applicative`] responsible for Rust-style result combination, specifically for tuples. pub trait ApplicativeTuple<'a>: Functor<'a> { /// Similar to Haskell's `listA2` but with [Iterator::collect]-ish semantics. fn tuple(fab: (Self::F, Self::F)) -> Self::F<(A, B)>; } /// Equivalent of Haskell's `Applicative`. /// Split into [`Pure`], [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations. /// /// pub trait Applicative<'a>: Pure<'a> + ApplicativeSeq<'a> + ApplicativeLA2<'a> + ApplicativeTuple<'a> + ApplicativeSelect<'a> { /// Equivalent of Haskell's `*>`/`>>`. fn discard_first(fa: Self::F, fb: Self::F) -> Self::F { Self::seq(Self::replace(fa, |b| b), fb) } /// Equivalent of Haskell's `<*`. fn discard_second(fa: Self::F, fb: Self::F) -> Self::F { Self::la2(fa, fb, |a, _| a) } } /// Equivalent of Haskell's `Monad`. /// /// pub trait Monad<'a>: Applicative<'a> { /// Equivalent of Haskell's `>==`. /// Due to Rust limitations, it's not a `function->function` conversion. /// For that see [`derivations::bind`]. fn bind(fa: Self::F, f: impl 'a + FnOnce(A) -> Self::F) -> Self::F; /// 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(f: impl Iterative<'a, T = Self, B = B>) -> Self::F; /// Equivalent of Haskell's `join`. fn join(ffa: Self::F>) -> Self::F { Self::bind(ffa, |fa| fa) } } pub trait MonadExt<'a>: Monad<'a> { /// [`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>, ) -> Self::F { Self::iterate(BindableMut::new(a, f)) } fn bind2( fa: Self::F, fb: Self::F, f: impl 'a + FnOnce(A, B) -> Self::F, ) -> Self::F { Self::join(Self::la2(fa, fb, f)) } } impl<'a, T: Monad<'a>> MonadExt<'a> for T {} /// Part of [`MonadFail`] responsible for Haskell's `fail`. pub trait Fail<'a, E: 'a>: WeakFunctor<'a> { /// Equivalent of Haskell's `fail`. fn fail(e: E) -> Self::F; } /// Equivalent of Haskell's `MonadFail`. Auto-implemented for all [`Fail`]`+`[`Monad`]. /// /// pub trait MonadFail<'a, E: 'a>: Monad<'a> + Fail<'a, E> {} impl<'a, E: 'a, T: Monad<'a> + Fail<'a, E>> MonadFail<'a, E> for T {} /// Represents wrapped results which are instantly available. pub trait LocalFunctor<'a>: WeakFunctor<'a> { /// Extract iteration state, if successful. fn unstuff(state: Self::F>) -> ControlFlow, A> { Self::stuff::<_, ControlFlowInstance>(state) } /// Stuff wrapped result into another functor. fn stuff>(fa: Self::F>) -> T::F>; } /// Represents a (collection of) [Monad]\(s) that can hold any type of error. pub trait MonadFailAny<'a>: 'a { /// [`MonadFail`] for a specific error type. type W: MonadFail<'a, E> where E: 'a; /// Associated infallible [`Monad`]. type T: Monad<'a>; fn unstuff(wa: WrapE<'a, A, E, Self>) -> Wrap<'a, Result, Self::T>; fn stuff(fa: Wrap<'a, Result, Self::T>) -> WrapE<'a, A, E, Self>; /// Equivalent of [`Result::map_err`]. fn map_err( wa: WrapE<'a, A, E0, Self>, f: impl 'a + FnOnce(E0) -> E1, ) -> WrapE<'a, A, E1, Self> { Self::bind_err(wa, |e0| Self::fail(f(e0))) } /// Equivalent of `catch`/`except`. To inject errors on success, see [`MonadFailAny::bind`]. fn bind_err( wa: WrapE<'a, A, E0, Self>, f: impl 'a + FnOnce(E0) -> WrapE<'a, A, E1, Self>, ) -> WrapE<'a, A, E1, Self> { 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( wa: WrapE<'a, A, E0, Self>, f: impl 'a + FnOnce(Result) -> WrapE<'a, B, E1, Self>, ) -> WrapE<'a, B, E1, Self> { 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( wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>, ) -> WrapE<'a, A, Result, Self> { 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( wa: WrapE<'a, Result, E0, Self>, ) -> WrapE<'a, A, Result, Self> { > 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>: MonadFailAny<'a> { 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) } } impl<'a, Fallible: ?Sized + MonadFailAny<'a>> MonadFailAnyExt<'a> for Fallible {} pub trait SharedFunctorAny: WeakFunctorAny { type SharedAny<'a, A: 'a + Clone>: 'a + Clone where Self: 'a; fn share<'a, A: 'a + Clone>(fa: Self::FAny<'a, A>) -> Self::SharedAny<'a, A> where Self: 'a; fn unshare<'a, A: 'a + Clone>(sa: Self::SharedAny<'a, A>) -> Self::FAny<'a, A> where Self: 'a; } pub trait SharedFunctor<'a>: WeakFunctor<'a> { type Shared: 'a + Clone; fn share(fa: Self::F) -> Self::Shared; fn unshare(sa: Self::Shared) -> Self::F; } impl<'a, T: 'a + SharedFunctorAny> SharedFunctor<'a> for T { type Shared = T::SharedAny<'a, A>; fn share(fa: Self::F) -> Self::Shared { T::share(fa) } fn unshare(sa: Self::Shared) -> Self::F { T::unshare(sa) } }