fp_library/typeclasses/monad.rs
1use crate::typeclasses::{Applicative, Bind};
2
3/// A typeclass for monads.
4///
5/// `Monad` combines the capabilities of [`Applicative`] and [`Bind`], providing
6/// a powerful abstraction for sequencing computations with context.
7///
8/// Monads are more powerful than applicative functors because they allow
9/// the structure of subsequent computations to depend on the results of
10/// previous computations.
11///
12/// # Laws
13///
14/// Monad instances must satisfy the following laws:
15/// * Left identity: `bind(pure(a))(f) = f(a)`.
16/// * Right identity: `bind(m)(pure) = m`.
17/// * Associativity: `bind(bind(m)(f))(g) = bind(m)(x => bind(f(x))(g))`.
18pub trait Monad: Applicative + Bind {}
19
20/// Blanket implementation for the `Monad` typeclass.
21///
22/// Any type that implements all the required supertraits automatically implements `Monad`.
23impl<Brand> Monad for Brand where Brand: Applicative + Bind {}
24
25#[cfg(test)]
26mod tests {
27 use crate::{
28 brands::OptionBrand,
29 typeclasses::Monad,
30 types::{ResultWithErrBrand, ResultWithOkBrand, SoloBrand, VecBrand},
31 };
32
33 /// Asserts that a type implements [`Monad`].
34 fn assert_monad<T: Monad>() {}
35
36 #[test]
37 /// Assert that brands implementing the required supertraits
38 /// ([`Applicative`][crate::typeclasses::Applicative], [`Bind`][crate::typeclasses::Bind])
39 /// also implement [`Monad`].
40 fn test_brands_implement_monad() {
41 assert_monad::<SoloBrand>();
42 assert_monad::<OptionBrand>();
43 assert_monad::<ResultWithErrBrand<()>>();
44 assert_monad::<ResultWithOkBrand<()>>();
45 assert_monad::<VecBrand>();
46 }
47}