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}