Skip to main content

yui_core/abst/
mon.rs

1//! Multiplicative monoid: a set with associative multiplication `·` and identity `1`.
2//!
3//! Unlike [`AddMon`](crate::AddMon), commutativity is **not** assumed here.
4//!
5//! See: <https://en.wikipedia.org/wiki/Monoid>
6
7use std::ops::{Mul, MulAssign};
8use num_traits::One;
9use crate::abst::MathType;
10
11/// Helper trait bundling `Mul` impls so [`Mon`] can require all four
12/// reference variants (`T * T`, `T * &T`, `&T * T`, `&T * &T`) via one HRTB.
13pub trait MonOps<T = Self>:
14    Sized +
15    Mul<T, Output = T> +
16    for<'a> Mul<&'a T, Output = T>
17{}
18
19/// A multiplicative monoid: a set with associative multiplication `·` and identity [`One`].
20///
21/// Not assumed commutative.
22///
23/// See: <https://en.wikipedia.org/wiki/Monoid>
24pub trait Mon:
25    MathType +
26    One +
27    MonOps +
28    MulAssign +
29    for<'a> MulAssign<&'a Self>
30where
31    for<'a> &'a Self: MonOps<Self>
32{
33    /// Multiply an iterator of factors into `Self`, folding with `*=`.
34    ///
35    /// `A` is any type for which `Self: MulAssign<A>` — typically `Self` or `&Self`.
36    fn product<A, I>(itr: I) -> Self
37    where
38        Self: MulAssign<A>,
39        I: IntoIterator<Item = A>
40    {
41        itr.into_iter().fold(Self::one(), |mut res, a| {
42            res *= a;
43            res
44        })
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51    #[test]
52    fn product() {
53        let a = i64::product([4,5,6]);
54        assert_eq!(a, 120);
55    }
56}