fp_library/classes/semigroupoid.rs
1use crate::{Apply, kinds::*};
2
3/// A type class for semigroupoids.
4///
5/// A `Semigroupoid` is a set of objects and composable relationships
6/// (morphisms) between them.
7///
8/// # Laws
9///
10/// Semigroupoid instances must satisfy the associative law:
11/// * Associativity: `compose(p, compose(q, r)) = compose(compose(p, q), r)`.
12pub trait Semigroupoid: Kind_fcf9d56b89a0b8b9 {
13 /// Takes morphisms `f` and `g` and returns the morphism `f . g` (`f` composed with `g`).
14 ///
15 /// # Type Signature
16 ///
17 /// `forall b c d. Semigroupoid a => (a c d, a b c) -> a b d`
18 ///
19 /// # Parameters
20 ///
21 /// * `f`: The second morphism to apply (from C to D).
22 /// * `g`: The first morphism to apply (from B to C).
23 ///
24 /// # Returns
25 ///
26 /// The composed morphism (from B to D).
27 ///
28 /// # Examples
29 ///
30 /// ```
31 /// use fp_library::classes::semigroupoid::Semigroupoid;
32 /// use fp_library::brands::RcFnBrand;
33 /// use fp_library::classes::clonable_fn::ClonableFn;
34 ///
35 /// let f = <RcFnBrand as ClonableFn>::new(|x: i32| x * 2);
36 /// let g = <RcFnBrand as ClonableFn>::new(|x: i32| x + 1);
37 /// let h = RcFnBrand::compose(f, g);
38 /// assert_eq!(h(5), 12); // (5 + 1) * 2
39 /// ```
40 fn compose<'a, B: 'a, C: 'a, D: 'a>(
41 f: Apply!(
42 brand: Self,
43 signature: ('a, C, D),
44 ),
45 g: Apply!(
46 brand: Self,
47 signature: ('a, B, C),
48 ),
49 ) -> Apply!(
50 brand: Self,
51 signature: ('a, B, D),
52 );
53}
54
55/// Takes morphisms `f` and `g` and returns the morphism `f . g` (`f` composed with `g`).
56///
57/// Free function version that dispatches to [the type class' associated function][`Semigroupoid::compose`].
58///
59/// # Type Signature
60///
61/// `forall b c d. Semigroupoid a => (a c d, a b c) -> a b d`
62///
63/// # Parameters
64///
65/// * `f`: The second morphism to apply (from C to D).
66/// * `g`: The first morphism to apply (from B to C).
67///
68/// # Returns
69///
70/// The composed morphism (from B to D).
71///
72/// # Examples
73///
74/// ```
75/// use fp_library::classes::semigroupoid::compose;
76/// use fp_library::brands::RcFnBrand;
77/// use fp_library::classes::clonable_fn::ClonableFn;
78///
79/// let f = <RcFnBrand as ClonableFn>::new(|x: i32| x * 2);
80/// let g = <RcFnBrand as ClonableFn>::new(|x: i32| x + 1);
81/// let h = compose::<RcFnBrand, _, _, _>(f, g);
82/// assert_eq!(h(5), 12); // (5 + 1) * 2
83/// ```
84pub fn compose<'a, Brand: Semigroupoid, B: 'a, C: 'a, D: 'a>(
85 f: Apply!(
86 brand: Brand,
87 signature: ('a, C, D),
88 ),
89 g: Apply!(
90 brand: Brand,
91 signature: ('a, B, C),
92 ),
93) -> Apply!(
94 brand: Brand,
95 signature: ('a, B, D),
96) {
97 Brand::compose(f, g)
98}