1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
//! 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>
use self::applicative_select::ApplicativeSelect;
use self::controlflow::{ControlFlow, Iterative};
pub use self::extensions::MonadExt;
pub mod applicative_select;
pub mod class_prelude;
pub mod context;
pub mod controlflow;
pub mod derivations;
pub 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;
/// 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 + Send {
type F<A: 'a + Send>: 'a + Send;
}
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 + Send, B: 'a + Send>(
fa: Self::F<A>,
f: impl 'a + Send + FnOnce(A) -> B,
) -> Self::F<B>;
/// Equivalent of Haskell's `$>`/`<$`.
fn replace<A: 'a + Send, B: 'a + Send>(fa: Self::F<A>, b: B) -> Self::F<B> {
Self::fmap(fa, |_| b)
}
/// Equivalent of Haskell's `void`.
fn void<A: 'a + Send>(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 + Send>(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 + Send, B: 'a + Send>(
ff: Self::F<impl 'a + Send + 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 + Send, B: 'a + Send, C: 'a + Send>(
fa: Self::F<A>,
fb: Self::F<B>,
f: impl 'a + Send + 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 + Send, B: 'a + Send>(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 + Send, B: 'a + Send>(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 + Send, B: 'a + Send>(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 + Send, B: 'a + Send>(
fa: Self::F<A>,
f: impl 'a + Send + 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.
///
/// [`StacklessInstance::iterate`]: instances::stackless::StacklessInstance::iterate
fn iterate<B: 'a + Send>(f: impl Iterative<'a, T = Self, B = B>) -> Self::F<B>;
/// Equivalent of Haskell's `join`.
fn join<A: 'a + Send>(ffa: Self::F<Self::F<A>>) -> Self::F<A> {
Self::bind(ffa, |fa| fa)
}
}