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