fp_library/typeclasses/
applicative.rs

1use crate::typeclasses::{Apply, ApplyFirst, ApplySecond, Functor, Pure};
2
3/// A typeclass for applicative functors.
4///
5/// `Applicative` extends `Functor` with the ability to lift values into a context
6/// (`pure`) and to apply functions within a context to values within a context
7/// (`apply`). It also provides additional operations for combining contexts
8/// (`apply_first`, `apply_second`).
9///
10/// Applicative functors are more powerful than functors but less powerful than
11/// monads. They allow for sequencing computations but with less flexibility
12/// than monads since the structure of the computation must be known in advance.
13///
14/// # Laws
15///
16/// Applicative instances must satisfy the following laws:
17/// * Identity: `apply(pure(identity))(v) = v`.
18/// * Composition: `apply(apply(apply(pure(compose))(u))(v))(w) = apply(u)(apply(v)(w))`.
19/// * Homomorphism: `apply(pure(f))(pure(x)) = pure(f(x))`.
20/// * Interchange: `apply(u)(pure(y)) = apply(pure(f => f(y)))(u)`.
21pub trait Applicative: Functor + Pure + Apply + ApplyFirst + ApplySecond {}
22
23/// Blanket implementation for the [`Applicative`] typeclass.
24///
25/// Any type that implements all the required supertraits automatically implements [`Applicative`].
26///
27/// The supertraits are:
28/// * [`Functor`]: for mapping functions over values in a context.
29/// * [`Pure`]: for lifting values into a context.
30/// * [`Apply`]: for applying functions in a context to values in a context.
31/// * [`ApplyFirst`]: for combining two contexts, keeping the first value.
32/// * [`ApplySecond`]: for combining two contexts, keeping the second value.
33impl<T> Applicative for T where T: Functor + Pure + Apply + ApplyFirst + ApplySecond {}
34
35#[cfg(test)]
36mod tests {
37	use crate::{
38		brands::OptionBrand,
39		typeclasses::Applicative,
40		types::{ResultWithErrBrand, ResultWithOkBrand, SoloBrand, VecBrand},
41	};
42
43	/// Asserts that a type implements [`Applicative`].
44	fn assert_applicative<T: Applicative>() {}
45
46	#[test]
47	/// Assert that brands implementing the required supertraits ([`Functor`],
48	/// [`Pure`], [`Apply`], [`ApplyFirst`], [`ApplySecond`]) also implement
49	/// [`Applicative`].
50	fn test_brands_implement_applicative() {
51		assert_applicative::<SoloBrand>();
52		assert_applicative::<OptionBrand>();
53		assert_applicative::<ResultWithErrBrand<()>>();
54		assert_applicative::<ResultWithOkBrand<()>>();
55		assert_applicative::<VecBrand>();
56	}
57}