pub trait PrismMonoid: Sized {
fn identity() -> Self;
fn compose(self, other: Self) -> Self;
}
#[derive(Debug, Clone, PartialEq)]
pub struct CountMonoid {
count: u64,
}
impl CountMonoid {
pub fn new(count: u64) -> Self {
CountMonoid { count }
}
pub fn count(&self) -> u64 {
self.count
}
}
impl PrismMonoid for CountMonoid {
fn identity() -> Self {
CountMonoid { count: 0 }
}
fn compose(self, other: Self) -> Self {
CountMonoid {
count: self.count + other.count,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn count_monoid_identity_left() {
let p = CountMonoid::new(3);
let id = CountMonoid::identity();
let composed = id.compose(p.clone());
assert_eq!(composed.count(), p.count());
}
#[test]
fn count_monoid_identity_right() {
let p = CountMonoid::new(3);
let id = CountMonoid::identity();
let composed = p.clone().compose(id);
assert_eq!(composed.count(), p.count());
}
#[test]
fn count_monoid_associativity() {
let a = CountMonoid::new(1);
let b = CountMonoid::new(2);
let c = CountMonoid::new(3);
let left = a.clone().compose(b.clone()).compose(c.clone());
let right = a.compose(b.compose(c));
assert_eq!(left.count(), right.count());
assert_eq!(left.count(), 6);
}
#[test]
fn count_monoid_identity_is_zero() {
let id = CountMonoid::identity();
assert_eq!(id.count(), 0);
}
}