partial_functional/monoid/
max.rs1use crate::semigroup::Semigroup;
2use num_traits::Bounded;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
10pub struct Max<T>(pub T);
11
12impl<T: Default + Semigroup + Bounded> Default for Max<T> {
13 fn default() -> Self {
14 Self(Bounded::min_value())
15 }
16}
17
18impl<T: PartialEq> PartialEq<T> for Max<T> {
19 fn eq(&self, other: &T) -> bool {
20 self.0 == *other
21 }
22}
23
24impl<T: PartialOrd> PartialOrd<T> for Max<T> {
25 fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
26 self.0.partial_cmp(other)
27 }
28}
29
30impl<T> From<T> for Max<T> {
31 fn from(value: T) -> Self {
32 Self(value)
33 }
34}
35
36impl<T: Ord> Semigroup for Max<T> {
37 fn combine(self, rhs: Self) -> Self {
38 Self(self.0.max(rhs.0))
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use crate::monoid::Monoid;
45
46 use super::*;
47
48 use quickcheck::Arbitrary;
49 use quickcheck_macros::quickcheck;
50
51 impl Arbitrary for Max<u32> {
52 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
53 Max(u32::arbitrary(g).into())
54 }
55
56 fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
57 Box::new(u32::shrink(&self.0).map(|x| x.into()))
58 }
59 }
60
61 #[quickcheck]
62 fn identity_property() {
63 assert_eq!(Max::<u32>(u32::MIN), Max::empty())
64 }
65
66 #[quickcheck]
67 fn max_of_vec_is_same_as_max_combine(vec: Vec<Max<u32>>) -> bool {
68 let left: Max<u32> = vec
69 .iter()
70 .copied()
71 .map(|x| x.0)
72 .max()
73 .unwrap_or(u32::MIN)
74 .into();
75 let right = vec
76 .iter()
77 .copied()
78 .fold(Max::default(), |a, x| a.combine(x));
79
80 left == right
81 }
82
83 #[quickcheck]
84 fn associativity_property(x: Max<u32>, y: Max<u32>, z: Max<u32>) -> bool {
85 x.combine(y.combine(z)) == x.combine(y).combine(z)
86 }
87}