partial_functional/monoid/
all.rs

1use crate::semigroup::Semigroup;
2
3/// Boolean semigroup over the operator &&.
4/// ```
5/// # use partial_functional::{All, Semigroup};
6/// assert_eq!(All(false), All(false).combine(All(true)));
7/// assert_eq!(All(true), All(true).combine(All(true)));
8/// assert_eq!(All(false), All(true).combine(All(false)));
9/// ```
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct All(pub bool);
12
13impl Semigroup for All {
14    fn combine(self, rhs: Self) -> Self {
15        Self(self.0 && rhs.0)
16    }
17}
18
19impl Default for All {
20    fn default() -> Self {
21        Self(true)
22    }
23}
24
25impl PartialEq<bool> for All {
26    fn eq(&self, other: &bool) -> bool {
27        self.0 == *other
28    }
29}
30
31impl PartialOrd<bool> for All {
32    fn partial_cmp(&self, other: &bool) -> Option<std::cmp::Ordering> {
33        self.0.partial_cmp(other)
34    }
35}
36
37impl From<bool> for All {
38    fn from(value: bool) -> Self {
39        Self(value)
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use crate::monoid::Monoid;
46
47    use super::*;
48
49    use quickcheck::Arbitrary;
50    use quickcheck_macros::quickcheck;
51
52    impl Arbitrary for All {
53        fn arbitrary(g: &mut quickcheck::Gen) -> Self {
54            All(<bool>::arbitrary(g))
55        }
56
57        fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
58            Box::new(<bool>::shrink(&self.0).map(|x| x.into()))
59        }
60    }
61
62    #[test]
63    fn equality_with_primitive() {
64        let any = All::from(true);
65
66        assert_eq!(any, true);
67    }
68
69    #[test]
70    fn ordering_with_primitive() {
71        let any = All::from(true);
72
73        assert_eq!(any > true, false);
74    }
75
76    #[quickcheck]
77    fn identity_property() {
78        assert_eq!(All(true), All::empty())
79    }
80
81    #[quickcheck]
82    fn any_is_true_if_atleast_one_is_true(vec: Vec<All>) -> bool {
83        let left: All = vec
84            .iter()
85            .copied()
86            .all(|x| x == All(true))
87            .into();
88        let right = vec
89            .iter()
90            .copied()
91            .fold(All::default(), |a, x| a.combine(x));
92
93        left == right
94    }
95
96    #[quickcheck]
97    fn associativity_property(x: All, y: All, z: All) -> bool {
98        x.combine(y.combine(z)) == x.combine(y).combine(z)
99    }
100}