fp_library/classes/
semimonad.rs

1//! Semimonad type class.
2//!
3//! This module defines the [`Semimonad`] trait, which allows for sequencing computations where the second computation depends on the result of the first.
4
5use crate::{Apply, kinds::*};
6
7/// Sequences two computations, allowing the second to depend on the value computed by the first.
8///
9/// If `x` has type `m a` and `f` has type `a -> m b`, then `bind(x, f)` has type `m b`,
10/// representing the result of executing `x` to get a value of type `a` and then
11/// passing it to `f` to get a computation of type `m b`.
12pub trait Semimonad: Kind_cdc7cd43dac7585f {
13	/// Sequences two computations, allowing the second to depend on the value computed by the first.
14	///
15	/// This method chains two computations, where the second computation depends on the result of the first.
16	///
17	/// ### Type Signature
18	///
19	/// `forall a b. Semimonad m => (m a, a -> m b) -> m b`
20	///
21	/// ### Type Parameters
22	///
23	/// * `F`: The type of the function to apply.
24	/// * `A`: The type of the result of the first computation.
25	/// * `B`: The type of the result of the second computation.
26	///
27	/// ### Parameters
28	///
29	/// * `ma`: The first computation.
30	/// * `f`: The function to apply to the result of the first computation.
31	///
32	/// ### Returns
33	///
34	/// The result of the second computation.
35	///
36	/// ### Examples
37	///
38	/// ```
39	/// use fp_library::classes::semimonad::Semimonad;
40	/// use fp_library::brands::OptionBrand;
41	///
42	/// let x = Some(5);
43	/// let y = OptionBrand::bind(x, |i| Some(i * 2));
44	/// assert_eq!(y, Some(10));
45	/// ```
46	fn bind<'a, F, A: 'a, B: 'a>(
47		ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
48		f: F,
49	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
50	where
51		F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a;
52}
53
54/// Sequences two computations, allowing the second to depend on the value computed by the first.
55///
56/// Free function version that dispatches to [the type class' associated function][`Semimonad::bind`].
57///
58/// ### Type Signature
59///
60/// `forall a b. Semimonad m => (m a, a -> m b) -> m b`
61///
62/// ### Type Parameters
63///
64/// * `Brand`: The brand of the semimonad.
65/// * `F`: The type of the function to apply.
66/// * `A`: The type of the result of the first computation.
67/// * `B`: The type of the result of the second computation.
68///
69/// ### Parameters
70///
71/// * `ma`: The first computation.
72/// * `f`: The function to apply to the result of the first computation.
73///
74/// ### Returns
75///
76/// The result of the second computation.
77///
78/// ### Examples
79///
80/// ```
81/// use fp_library::classes::semimonad::bind;
82/// use fp_library::brands::OptionBrand;
83///
84/// let x = Some(5);
85/// let y = bind::<OptionBrand, _, _, _>(x, |i| Some(i * 2));
86/// assert_eq!(y, Some(10));
87/// ```
88pub fn bind<'a, Brand: Semimonad, F, A: 'a, B: 'a>(
89	ma: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
90	f: F,
91) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
92where
93	F: Fn(A) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
94{
95	Brand::bind(ma, f)
96}