1use crate::abstraction::*;
2use core::ops::*;
3
4#[derive(Clone, Copy, Debug)]
6pub struct Prop(bool);
7
8pub mod constructors {
11 use super::Prop;
12 pub fn from_bool(b: bool) -> Prop {
13 Prop(b)
14 }
15 pub fn and(lhs: Prop, other: Prop) -> Prop {
16 Prop(lhs.0 && other.0)
17 }
18 pub fn or(lhs: Prop, other: Prop) -> Prop {
19 Prop(lhs.0 || other.0)
20 }
21 pub fn not(lhs: Prop) -> Prop {
22 Prop(!lhs.0)
23 }
24 pub fn eq(lhs: Prop, other: Prop) -> Prop {
25 Prop(lhs.0 == other.0)
26 }
27 pub fn ne(lhs: Prop, other: Prop) -> Prop {
28 Prop(lhs.0 != other.0)
29 }
30 pub fn implies(lhs: Prop, other: Prop) -> Prop {
31 Prop(lhs.0 || !other.0)
32 }
33 pub fn forall<A, F: Fn(A) -> Prop>(_pred: F) -> Prop {
34 Prop(true)
35 }
36 pub fn exists<A, F: Fn(A) -> Prop>(_pred: F) -> Prop {
37 Prop(true)
38 }
39}
40
41impl Prop {
42 pub fn from_bool(b: bool) -> Self {
44 constructors::from_bool(b)
45 }
46 pub fn and(self, other: impl Into<Self>) -> Self {
48 constructors::and(self, other.into())
49 }
50 pub fn or(self, other: impl Into<Self>) -> Self {
52 constructors::or(self, other.into())
53 }
54 pub fn not(self) -> Self {
56 constructors::not(self)
57 }
58 pub fn eq(self, other: impl Into<Self>) -> Self {
60 constructors::eq(self, other.into())
61 }
62 pub fn ne(self, other: impl Into<Self>) -> Self {
64 constructors::ne(self, other.into())
65 }
66 pub fn implies(self, other: impl Into<Self>) -> Self {
68 constructors::implies(self, other.into())
69 }
70}
71
72impl Abstraction for bool {
73 type AbstractType = Prop;
74 fn lift(self) -> Self::AbstractType {
75 Prop(self)
76 }
77}
78
79pub trait ToProp {
80 fn to_prop(self) -> Prop;
81}
82impl ToProp for bool {
83 fn to_prop(self) -> Prop {
84 self.lift()
85 }
86}
87
88impl From<bool> for Prop {
89 fn from(value: bool) -> Self {
90 Prop(value)
91 }
92}
93
94impl<T: Into<Prop>> BitAnd<T> for Prop {
95 type Output = Prop;
96 fn bitand(self, rhs: T) -> Self::Output {
97 Prop(self.0 & rhs.into().0)
98 }
99}
100
101impl<T: Into<Prop>> BitOr<T> for Prop {
102 type Output = Prop;
103 fn bitor(self, rhs: T) -> Self::Output {
104 Prop(self.0 | rhs.into().0)
105 }
106}
107
108impl Not for Prop {
109 type Output = Prop;
110 fn not(self) -> Self::Output {
111 Prop(!self.0)
112 }
113}
114
115pub fn forall<T, U: Into<Prop>>(f: impl Fn(T) -> U) -> Prop {
122 constructors::forall(|x| f(x).into())
123}
124
125pub fn exists<T, U: Into<Prop>>(f: impl Fn(T) -> U) -> Prop {
132 constructors::exists(|x| f(x).into())
133}
134
135pub fn implies(lhs: impl Into<Prop>, rhs: impl Into<Prop>) -> Prop {
137 constructors::implies(lhs.into(), rhs.into())
138}