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}