fp_library/classes/
applicative.rs

1use crate::classes::{ApplyFirst, ApplySecond, Functor, Pointed, Semiapplicative};
2
3/// A type class 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 + Pointed + Semiapplicative + ApplyFirst + ApplySecond {}
22
23/// Blanket implementation for the [`Applicative`] type class.
24///
25/// Any type that implements all the required supertraits automatically implements [`Applicative`].
26impl<Brand> Applicative for Brand where
27	Brand: Functor + Pointed + Semiapplicative + ApplyFirst + ApplySecond
28{
29}
30
31#[cfg(test)]
32mod tests {
33	use crate::{
34		brands::{IdentityBrand, OptionBrand, ResultWithErrBrand, ResultWithOkBrand, VecBrand},
35		classes::Applicative,
36	};
37
38	/// Asserts that a type implements [`Applicative`].
39	fn assert_applicative<T: Applicative>() {}
40
41	#[test]
42	/// Assert that brands implementing the required supertraits ([`Functor`],
43	/// [`Pointed`], [`Semiapplicative`], [`ApplyFirst`], [`ApplySecond`]) also implement
44	/// [`Applicative`].
45	fn test_brands_implement_applicative() {
46		assert_applicative::<IdentityBrand>();
47		assert_applicative::<OptionBrand>();
48		assert_applicative::<ResultWithErrBrand<()>>();
49		assert_applicative::<ResultWithOkBrand<()>>();
50		assert_applicative::<VecBrand>();
51	}
52}