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}