1use core::marker::PhantomData;
5
6pub trait Justifies<Lhs, Rhs> {}
11
12pub struct Rewrite<Lhs, Rhs, Via> {
32 _phantom: PhantomData<(Lhs, Rhs, Via)>,
33}
34
35impl<Lhs, Rhs, Via> Rewrite<Lhs, Rhs, Via> {
36 pub fn witness() -> Self
40 where
41 Via: Justifies<Lhs, Rhs>,
42 {
43 Rewrite {
44 _phantom: PhantomData,
45 }
46 }
47
48 pub fn sym(self) -> Rewrite<Rhs, Lhs, BySymmetry<Via>> {
50 Rewrite {
51 _phantom: PhantomData,
52 }
53 }
54
55 pub fn then<Rhs2, V2>(
62 self,
63 _next: Rewrite<Rhs, Rhs2, V2>,
64 ) -> Rewrite<Lhs, Rhs2, ByTransitivity<Via, V2, Rhs>> {
65 Rewrite {
66 _phantom: PhantomData,
67 }
68 }
69}
70
71pub struct ByAssociativity;
77
78pub struct ByCommutativity;
80
81pub struct ByIdentity;
83
84pub struct ByInverse;
86
87pub struct ByDistribution;
89
90pub struct ByAnnihilation;
92
93pub struct ByTransitivity<V1, V2, Mid = ()>(PhantomData<(V1, V2, Mid)>);
96
97pub struct BySymmetry<V>(PhantomData<V>);
99
100pub struct AssocLeft;
106pub struct AssocRight;
108
109pub struct CombineAB;
111pub struct CombineBA;
113
114pub struct WithIdentity;
116pub struct JustA;
118
119pub struct WithInverse;
121pub struct Identity;
123
124pub struct Undistributed;
126pub struct Distributed;
128
129pub struct ZeroTimes;
131pub struct Zero;
133
134impl Justifies<AssocLeft, AssocRight> for ByAssociativity {}
140impl Justifies<AssocRight, AssocLeft> for ByAssociativity {}
141
142impl Justifies<CombineAB, CombineBA> for ByCommutativity {}
144impl Justifies<CombineBA, CombineAB> for ByCommutativity {}
145
146impl Justifies<WithIdentity, JustA> for ByIdentity {}
148impl Justifies<JustA, WithIdentity> for ByIdentity {}
149
150impl Justifies<WithInverse, Identity> for ByInverse {}
152impl Justifies<Identity, WithInverse> for ByInverse {}
153
154impl Justifies<Undistributed, Distributed> for ByDistribution {}
156impl Justifies<Distributed, Undistributed> for ByDistribution {}
157
158impl Justifies<ZeroTimes, Zero> for ByAnnihilation {}
160impl Justifies<Zero, ZeroTimes> for ByAnnihilation {}
161
162impl<V, Lhs, Rhs> Justifies<Rhs, Lhs> for BySymmetry<V> where V: Justifies<Lhs, Rhs> {}
164
165impl<V1, V2, Lhs, Mid, Rhs> Justifies<Lhs, Rhs> for ByTransitivity<V1, V2, Mid>
168where
169 V1: Justifies<Lhs, Mid>,
170 V2: Justifies<Mid, Rhs>,
171{
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn associativity_rewrite() {
180 let _: Rewrite<AssocLeft, AssocRight, ByAssociativity> = Rewrite::witness();
181 let _: Rewrite<AssocRight, AssocLeft, ByAssociativity> = Rewrite::witness();
182 }
183
184 #[test]
185 fn commutativity_rewrite() {
186 let _: Rewrite<CombineAB, CombineBA, ByCommutativity> = Rewrite::witness();
187 }
188
189 #[test]
190 fn identity_rewrite() {
191 let _: Rewrite<WithIdentity, JustA, ByIdentity> = Rewrite::witness();
192 let _: Rewrite<JustA, WithIdentity, ByIdentity> = Rewrite::witness();
193 }
194
195 #[test]
196 fn inverse_rewrite() {
197 let _: Rewrite<WithInverse, Identity, ByInverse> = Rewrite::witness();
198 }
199
200 #[test]
201 fn distribution_rewrite() {
202 let _: Rewrite<Undistributed, Distributed, ByDistribution> = Rewrite::witness();
203 }
204
205 #[test]
206 fn annihilation_rewrite() {
207 let _: Rewrite<ZeroTimes, Zero, ByAnnihilation> = Rewrite::witness();
208 }
209
210 #[test]
211 fn symmetry() {
212 let step: Rewrite<AssocLeft, AssocRight, ByAssociativity> = Rewrite::witness();
213 let _back: Rewrite<AssocRight, AssocLeft, BySymmetry<ByAssociativity>> = step.sym();
214 }
215
216 #[test]
217 fn transitivity_chain() {
218 let step1: Rewrite<WithIdentity, JustA, ByIdentity> = Rewrite::witness();
223 let step2: Rewrite<JustA, WithIdentity, ByIdentity> = Rewrite::witness();
224 let _chained: Rewrite<
225 WithIdentity,
226 WithIdentity,
227 ByTransitivity<ByIdentity, ByIdentity, JustA>,
228 > = step1.then(step2);
229 }
230
231 #[test]
232 fn three_step_chain() {
233 let s1: Rewrite<WithInverse, Identity, ByInverse> = Rewrite::witness();
235 let s2: Rewrite<Identity, WithInverse, ByInverse> = Rewrite::witness();
236 let s3: Rewrite<WithInverse, Identity, ByInverse> = Rewrite::witness();
237 let _: Rewrite<
238 WithInverse,
239 Identity,
240 ByTransitivity<ByTransitivity<ByInverse, ByInverse, Identity>, ByInverse, WithInverse>,
241 > = s1.then(s2).then(s3);
242 }
243}