Skip to main content

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}