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}