fp_library/classes/
semimonad.rs

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