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}