Skip to main content

fp_library/types/
conjunctive.rs

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