fp_library/types/disjunctive.rs
1//! A newtype wrapper whose [`Semigroup`](crate::classes::Semigroup) and [`Monoid`](crate::classes::Monoid) instances use
2//! disjunction from [`HeytingAlgebra`](crate::classes::HeytingAlgebra).
3//!
4//! ### Examples
5//!
6//! ```
7//! use fp_library::{
8//! functions::*,
9//! types::Disjunctive,
10//! };
11//!
12//! assert_eq!(append(Disjunctive(false), Disjunctive(true)), Disjunctive(true));
13//! assert_eq!(empty::<Disjunctive<bool>>(), Disjunctive(false));
14//! ```
15
16#[fp_macros::document_module]
17mod inner {
18 use {
19 crate::classes::*,
20 fp_macros::*,
21 };
22
23 /// A newtype wrapper whose [`Semigroup`] instance uses
24 /// [`HeytingAlgebra::disjoin`].
25 ///
26 /// This provides a [`Monoid`] based on logical disjunction (OR),
27 /// with [`HeytingAlgebra::false_value`] as the identity element.
28 #[document_examples]
29 ///
30 /// ```
31 /// use fp_library::{
32 /// functions::*,
33 /// types::Disjunctive,
34 /// };
35 ///
36 /// assert_eq!(append(Disjunctive(false), Disjunctive(false)), Disjunctive(false));
37 /// assert_eq!(append(Disjunctive(false), Disjunctive(true)), Disjunctive(true));
38 /// assert_eq!(empty::<Disjunctive<bool>>(), Disjunctive(false));
39 /// ```
40 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
41 pub struct Disjunctive<A>(
42 /// The wrapped value.
43 pub A,
44 );
45
46 #[document_type_parameters("The Heyting algebra type.")]
47 impl<A: HeytingAlgebra> Semigroup for Disjunctive<A> {
48 /// Combines two values using [`HeytingAlgebra::disjoin`].
49 #[document_signature]
50 ///
51 #[document_parameters("The first disjunctive value.", "The second disjunctive value.")]
52 ///
53 #[document_returns("The disjunction wrapped in `Disjunctive`.")]
54 #[document_examples]
55 ///
56 /// ```
57 /// use fp_library::{
58 /// functions::*,
59 /// types::Disjunctive,
60 /// };
61 ///
62 /// assert_eq!(append(Disjunctive(false), Disjunctive(true)), Disjunctive(true));
63 /// ```
64 fn append(
65 a: Self,
66 b: Self,
67 ) -> Self {
68 Disjunctive(A::disjoin(a.0, b.0))
69 }
70 }
71
72 #[document_type_parameters("The Heyting algebra type.")]
73 impl<A: HeytingAlgebra> Monoid for Disjunctive<A> {
74 /// Returns `Disjunctive(false_value())`.
75 #[document_signature]
76 ///
77 #[document_returns("The bottom element wrapped in `Disjunctive`.")]
78 #[document_examples]
79 ///
80 /// ```
81 /// use fp_library::{
82 /// functions::*,
83 /// types::Disjunctive,
84 /// };
85 ///
86 /// assert_eq!(empty::<Disjunctive<bool>>(), Disjunctive(false));
87 /// ```
88 fn empty() -> Self {
89 Disjunctive(A::false_value())
90 }
91 }
92}
93
94pub use inner::*;
95
96#[cfg(test)]
97mod tests {
98 use {
99 super::*,
100 crate::functions::*,
101 quickcheck_macros::quickcheck,
102 };
103
104 #[quickcheck]
105 fn semigroup_associativity(
106 a: bool,
107 b: bool,
108 c: bool,
109 ) -> bool {
110 let x = Disjunctive(a);
111 let y = Disjunctive(b);
112 let z = Disjunctive(c);
113 append(x, append(y, z)) == append(append(x, y), z)
114 }
115
116 #[quickcheck]
117 fn monoid_left_identity(a: bool) -> bool {
118 let x = Disjunctive(a);
119 append(empty::<Disjunctive<bool>>(), x) == x
120 }
121
122 #[quickcheck]
123 fn monoid_right_identity(a: bool) -> bool {
124 let x = Disjunctive(a);
125 append(x, empty::<Disjunctive<bool>>()) == x
126 }
127}