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}