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<Brand> Monad for Brand where Brand: 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}