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