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}