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