op_add/
lib.rs

1use std::{
2    iter::Sum,
3    ops::{Add, Neg},
4};
5
6use monoid::{Associative, BinaryOp, Commutative, Identity, Recip};
7
8#[derive(Clone, Debug)]
9pub struct OpAdd<T>(std::marker::PhantomData<fn(&T) -> T>);
10
11impl<T> Default for OpAdd<T> {
12    fn default() -> Self { Self(std::marker::PhantomData) }
13}
14
15impl<T> BinaryOp for OpAdd<T>
16where
17    for<'a> &'a T: Add<&'a T, Output = T>,
18{
19    type Set = T;
20    fn op(&self, lhs: &T, rhs: &T) -> T { lhs + rhs }
21}
22
23impl<T> Identity for OpAdd<T>
24where
25    for<'a> &'a T: Add<&'a T, Output = T>,
26    T: for<'a> Sum<&'a T>,
27{
28    fn id(&self) -> T { None.into_iter().sum() }
29}
30
31impl<T> Recip for OpAdd<T>
32where
33    for<'a> &'a T: Add<&'a T, Output = T> + Neg<Output = T>,
34    T: for<'a> Sum<&'a T>,
35{
36    fn recip(&self, elt: &T) -> T { elt.neg() }
37}
38
39impl<T> Associative for OpAdd<T> where for<'a> &'a T: Add<&'a T, Output = T> {}
40impl<T> Commutative for OpAdd<T> where for<'a> &'a T: Add<&'a T, Output = T> {}
41
42#[test]
43fn sanity_check() {
44    let op_add: OpAdd<i32> = Default::default();
45    assert_eq!(op_add.op(&1, &2), 3);
46    assert_eq!(op_add.id(), 0);
47    assert_eq!(op_add.recip(&1), -1);
48}