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}