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`].
23///
24/// The supertraits are:
25/// * [`Applicative`]: which combines [`Functor`][crate::typeclasses::Functor],
26///   [`Pure`][crate::typeclasses::Pure], [`Apply`][crate::typeclasses::Apply],
27///   [`ApplyFirst`][crate::typeclasses::ApplyFirst],
28///   and [`ApplySecond`][crate::typeclasses::ApplySecond].
29/// * [`Bind`]: for sequencing computations where the second depends on the result of the first.
30impl<T> Monad for T where T: Applicative + Bind {}
31
32#[cfg(test)]
33mod tests {
34	use crate::{
35		brands::OptionBrand,
36		typeclasses::Monad,
37		types::{ResultWithErrBrand, ResultWithOkBrand, SoloBrand, VecBrand},
38	};
39
40	/// Asserts that a type implements [`Monad`].
41	fn assert_monad<T: Monad>() {}
42
43	#[test]
44	/// Assert that brands implementing the required supertraits
45	/// ([`Applicative`], [`Bind`]) also implement [`Monad`].
46	fn test_brands_implement_monad() {
47		assert_monad::<SoloBrand>();
48		assert_monad::<OptionBrand>();
49		assert_monad::<ResultWithErrBrand<()>>();
50		assert_monad::<ResultWithOkBrand<()>>();
51		assert_monad::<VecBrand>();
52	}
53}