yui_core/abst/add_mon.rs
1//! Additive monoid: a set with associative, commutative addition `+` and identity `0`.
2//!
3//! See: <https://en.wikipedia.org/wiki/Monoid>,
4//! <https://en.wikipedia.org/wiki/Commutative_monoid>
5
6use std::ops::{Add, AddAssign};
7use num_traits::Zero;
8use crate::abst::MathType;
9
10/// Helper trait bundling `Add` impls so [`AddMon`] can require all four
11/// reference variants (`T + T`, `T + &T`, `&T + T`, `&T + &T`) via one HRTB.
12pub trait AddMonOps<T = Self>:
13 Sized +
14 Add<T, Output = T> + // S + T -> T
15 for<'a> Add<&'a T, Output = T> // S + &T -> T
16{}
17
18/// An additive monoid: a set with associative, commutative addition `+` and identity [`Zero`].
19///
20/// See: <https://en.wikipedia.org/wiki/Monoid>,
21/// <https://en.wikipedia.org/wiki/Commutative_monoid>
22pub trait AddMon:
23 MathType +
24 Zero +
25 AddMonOps + // T + T -> T, T + &T -> T
26 AddAssign + // T += T
27 for<'a> AddAssign<&'a Self> // T += &T
28where
29 for<'a> &'a Self: AddMonOps<Self> // &T + T -> T, &T + &T -> T
30{
31 /// Sum an iterator into `Self`, folding with `+=`.
32 ///
33 /// `A` is any type for which `Self: AddAssign<A>` — typically `Self` or `&Self`.
34 fn sum<A, I>(itr: I) -> Self
35 where
36 Self: AddAssign<A>,
37 I: IntoIterator<Item = A>
38 {
39 itr.into_iter().fold(Self::zero(), |mut res, a| {
40 res += a;
41 res
42 })
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 #[test]
50 fn sum() {
51 let a = i64::sum([4,5,6]);
52 assert_eq!(a, 15);
53 }
54}