fp_library/typeclasses/bind.rs
1use crate::hkt::{Apply, Kind};
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`.
8///
9/// Note that `Bind` is a separate typeclass from [`Monad`][`crate::typeclasses::Monad`]. In this library's
10/// hierarchy, [`Monad`][`crate::typeclasses::Monad`] is a typeclass that extends both
11/// [`Applicative`][`crate::typeclasses::Applicative`] and `Bind`.
12pub trait Bind {
13 /// Sequences two computations, allowing the second to depend on the value computed by the first.
14 ///
15 /// # Type Signature
16 ///
17 /// `forall m a b. Bind m => m a -> (a -> m b) -> m b`
18 ///
19 /// # Parameters
20 ///
21 /// * `ma`: The first computation in the context.
22 /// * `f`: A function that takes the result of the first computation and returns the second computation in the context.
23 ///
24 /// # Returns
25 ///
26 /// A computation that sequences the two operations.
27 fn bind<F, A, B>(ma: Apply<Self, (A,)>) -> impl Fn(F) -> Apply<Self, (B,)>
28 where
29 Self: Kind<(A,)> + Kind<(B,)> + Sized,
30 Apply<Self, (A,)>: Clone,
31 F: Fn(A) -> Apply<Self, (B,)>;
32}
33
34/// Sequences two computations, allowing the second to depend on the value computed by the first.
35///
36/// Free function version that dispatches to [the typeclass method][`Bind::bind`].
37///
38/// # Type Signature
39///
40/// `forall m a b. Bind m => m a -> (a -> m b) -> m b`
41///
42/// # Parameters
43///
44/// * `ma`: The first computation in the context.
45/// * `f`: A function that takes the result of the first computation and returns the second computation in the context.
46///
47/// # Returns
48///
49/// A computation that sequences the two operations.
50///
51/// # Examples
52///
53/// ```
54/// use fp_library::{brands::OptionBrand, functions::{bind, pure}};
55///
56/// assert_eq!(bind::<OptionBrand, _, _, _>(Some(5))(|x| Some(x * 2)), Some(10));
57/// ```
58pub fn bind<Brand, F, A, B>(ma: Apply<Brand, (A,)>) -> impl Fn(F) -> Apply<Brand, (B,)>
59where
60 Brand: Kind<(A,)> + Kind<(B,)> + Bind,
61 Apply<Brand, (A,)>: Clone,
62 F: Fn(A) -> Apply<Brand, (B,)>,
63{
64 Brand::bind::<F, A, B>(ma)
65}