fp_library/classes/semigroup.rs
1//! Semigroup type class.
2//!
3//! This module defines the [`Semigroup`] trait, which represents types that support an associative binary operation.
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::functions::*;
9//!
10//! let x = "Hello, ".to_string();
11//! let y = "World!".to_string();
12//! let z = append::<_>(x, y);
13//! assert_eq!(z, "Hello, World!".to_string());
14//! ```
15
16/// A type class for types that support an associative binary operation.
17///
18/// `Semigroup` instances must satisfy the associative law:
19/// * Associativity: `append(a, append(b, c)) = append(append(a, b), c)`.
20pub trait Semigroup {
21 /// The result of combining the two values using the semigroup operation.
22 ///
23 /// This method combines two values of the same type into a single value of that type.
24 ///
25 /// ### Type Signature
26 ///
27 /// `forall s. Semigroup s => (s, s) -> s`
28 ///
29 /// ### Parameters
30 ///
31 /// * `a`: The first value.
32 /// * `b`: The second value.
33 ///
34 /// ### Returns
35 ///
36 /// The combined value.
37 ///
38 /// ### Examples
39 ///
40 /// ```
41 /// use fp_library::functions::*;
42 ///
43 /// let x = "Hello, ".to_string();
44 /// let y = "World!".to_string();
45 /// let z = append::<_>(x, y);
46 /// assert_eq!(z, "Hello, World!".to_string());
47 /// ```
48 fn append(
49 a: Self,
50 b: Self,
51 ) -> Self;
52}
53
54/// The result of combining the two values using the semigroup operation.
55///
56/// Free function version that dispatches to [the type class' associated function][`Semigroup::append`].
57///
58/// ### Type Signature
59///
60/// `forall s. Semigroup s => (s, s) -> s`
61///
62/// ### Type Parameters
63///
64/// * `S`: The type of the semigroup.
65///
66/// ### Parameters
67///
68/// * `a`: The first value.
69/// * `b`: The second value.
70///
71/// ### Returns
72///
73/// The combined value.
74///
75/// ### Examples
76///
77/// ```
78/// use fp_library::functions::*;
79///
80/// let x = "Hello, ".to_string();
81/// let y = "World!".to_string();
82/// let z = append::<_>(x, y);
83/// assert_eq!(z, "Hello, World!".to_string());
84/// ```
85pub fn append<S: Semigroup>(
86 a: S,
87 b: S,
88) -> S {
89 S::append(a, b)
90}