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, ResultWithErrBrand, ResultWithOkBrand, SoloBrand, VecBrand},
29		typeclasses::Monad,
30	};
31
32	/// Asserts that a type implements [`Monad`].
33	fn assert_monad<T: Monad>() {}
34
35	#[test]
36	/// Assert that brands implementing the required supertraits
37	/// ([`Applicative`][crate::typeclasses::Applicative], [`Bind`][crate::typeclasses::Bind])
38	/// also implement [`Monad`].
39	fn test_brands_implement_monad() {
40		assert_monad::<SoloBrand>();
41		assert_monad::<OptionBrand>();
42		assert_monad::<ResultWithErrBrand<()>>();
43		assert_monad::<ResultWithOkBrand<()>>();
44		assert_monad::<VecBrand>();
45	}
46}