//! 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: //! * <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html> //! * <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html> //! * <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html> mod applicative_select; pub mod class_prelude; pub mod context; pub mod controlflow; pub mod derivations; mod extensions; pub mod fail; pub mod instances; pub mod local; pub mod shared; #[cfg(test)] pub mod test_suite; #[cfg(test)] pub mod tests; pub mod weakfunctorany; pub use self::applicative_select::{ ApplicativeSelect, ApplicativeSelectExt, Selected, SelectedWrapped, }; use self::controlflow::{ControlFlow, Iterative}; pub use self::extensions::MonadExt; #[cfg(doc)] use self::instances::stackless::StacklessInstance; /// Part of Haskell's `Functor f` responsible for having `f a`. /// /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html> pub trait WeakFunctor<'a>: 'a { type F<A: 'a>: 'a; } pub type Wrap<'a, A, T> = <T as WeakFunctor<'a>>::F<A>; /// Rust-specific implementation of [`Functor`], respecting `move` semantics. /// /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html> 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<A: 'a, B: 'a>(fa: Self::F<A>, f: impl 'a + FnOnce(A) -> B) -> Self::F<B>; /// Equivalent of Haskell's `$>`/`<$`. fn replace<A: 'a, B: 'a>(fa: Self::F<A>, b: B) -> Self::F<B> { Self::fmap(fa, |_| b) } /// Equivalent of Haskell's `void`. fn void<A: 'a>(fa: Self::F<A>) -> 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>(a: A) -> Self::F<A>; } /// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`. pub trait ApplicativeSeq<'a>: Functor<'a> { /// Equivalent of Haskell's `<*>`. fn seq<A: 'a, B: 'a>(ff: Self::F<impl 'a + FnOnce(A) -> B>, fa: Self::F<A>) -> Self::F<B>; } /// Part of [`Applicative`] responsible for Haskell's result combination `listA2`. pub trait ApplicativeLA2<'a>: Functor<'a> { /// Equivalent of Haskell's `listA2`. fn la2<A: 'a, B: 'a, C: 'a>( fa: Self::F<A>, fb: Self::F<B>, f: impl 'a + FnOnce(A, B) -> C, ) -> Self::F<C>; } /// 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<A: 'a, B: 'a>(fab: (Self::F<A>, Self::F<B>)) -> Self::F<(A, B)>; } /// Equivalent of Haskell's `Applicative`. /// Split into [`Pure`], [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations. /// /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html> pub trait Applicative<'a>: Pure<'a> + ApplicativeSeq<'a> + ApplicativeLA2<'a> + ApplicativeTuple<'a> + ApplicativeSelect<'a> { /// Equivalent of Haskell's `*>`/`>>`. fn discard_first<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<B> { Self::seq(Self::replace(fa, |b| b), fb) } /// Equivalent of Haskell's `<*`. fn discard_second<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<A> { Self::la2(fa, fb, |a, _| a) } } /// Equivalent of Haskell's `Monad`. /// /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html> 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<A: 'a, B: 'a>(fa: Self::F<A>, f: impl 'a + FnOnce(A) -> Self::F<B>) -> Self::F<B>; /// 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<B: 'a>(f: impl Iterative<'a, T = Self, B = B>) -> Self::F<B>; /// Equivalent of Haskell's `join`. fn join<A: 'a>(ffa: Self::F<Self::F<A>>) -> Self::F<A> { Self::bind(ffa, |fa| fa) } } impl<'a, T: Monad<'a>> MonadExt<'a> for T {}