1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/// Semigroup defines some associative operation that can be done
/// to 2 instances of a type.
///
/// # Examples
/// - `String`'s semigroup implementation concatenates the two strings.
/// - `Vec`'s semigroup implementation concatenates the two Vecs.
///
/// # Laws
/// Implementations of `Semigroup` must be associative, e.g.
///
/// ```
/// use naan::prelude::*;
///
/// let a = || vec![1u8, 2];
/// let b = || vec![3u8, 4];
/// let c = || vec![5u8, 6];
///
/// assert_eq!(a().append(b().append(c())), a().append(b()).append(c()));
/// ```
pub trait Semigroup {
  /// See [`Semigroup`]
  fn append(self, b: Self) -> Self;
}

/// Monoid extends [`Semigroup`] with the an "identity" value
/// that [`append`](Semigroup::append)ing to a Semigroup will
/// result in the same value.
///
/// # Laws
/// The Monoid identity value must be a no-op on either side
/// of an [`append`](Semigroup::append), e.g.
///
/// ```
/// use naan::prelude::*;
///
/// assert_eq!(String::from("hello").append(String::identity()),
///            String::identity().append(String::from("hello")));
///
/// // Generalized:
/// fn assert_monoid_identity<T>(t: T)
///   where T: PartialEq + core::fmt::Debug + Clone + Monoid
/// {
///   assert_eq!(t.clone().append(T::identity()), t.clone());
///   assert_eq!(T::identity().append(t.clone()), t);
/// }
///
/// assert_monoid_identity(String::from("hello"));
/// assert_monoid_identity(vec!["hello"]);
/// ```
pub trait Monoid: Semigroup {
  /// See [`Monoid`]
  fn identity() -> Self;
}