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`].
26impl<Brand> Applicative for Brand where Brand: Functor + Pure + Apply + ApplyFirst + ApplySecond {}
27
28#[cfg(test)]
29mod tests {
30	use crate::{
31		brands::OptionBrand,
32		typeclasses::Applicative,
33		types::{ResultWithErrBrand, ResultWithOkBrand, SoloBrand, VecBrand},
34	};
35
36	/// Asserts that a type implements [`Applicative`].
37	fn assert_applicative<T: Applicative>() {}
38
39	#[test]
40	/// Assert that brands implementing the required supertraits ([`Functor`],
41	/// [`Pure`], [`Apply`], [`ApplyFirst`], [`ApplySecond`]) also implement
42	/// [`Applicative`].
43	fn test_brands_implement_applicative() {
44		assert_applicative::<SoloBrand>();
45		assert_applicative::<OptionBrand>();
46		assert_applicative::<ResultWithErrBrand<()>>();
47		assert_applicative::<ResultWithOkBrand<()>>();
48		assert_applicative::<VecBrand>();
49	}
50}