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