1use core::marker::PhantomData;
2
3pub trait Justifies<Lhs, Rhs> {}
8
9pub struct Rewrite<Lhs, Rhs, Via> {
29 _phantom: PhantomData<(Lhs, Rhs, Via)>,
30}
31
32impl<Lhs, Rhs, Via> Rewrite<Lhs, Rhs, Via> {
33 pub fn witness() -> Self
37 where
38 Via: Justifies<Lhs, Rhs>,
39 {
40 Rewrite {
41 _phantom: PhantomData,
42 }
43 }
44
45 pub fn sym(self) -> Rewrite<Rhs, Lhs, BySymmetry<Via>> {
47 Rewrite {
48 _phantom: PhantomData,
49 }
50 }
51
52 pub fn then<Rhs2, V2>(
59 self,
60 _next: Rewrite<Rhs, Rhs2, V2>,
61 ) -> Rewrite<Lhs, Rhs2, ByTransitivity<Via, V2, Rhs>> {
62 Rewrite {
63 _phantom: PhantomData,
64 }
65 }
66}
67
68pub struct ByAssociativity;
74
75pub struct ByCommutativity;
77
78pub struct ByIdentity;
80
81pub struct ByInverse;
83
84pub struct ByDistribution;
86
87pub struct ByAnnihilation;
89
90pub struct ByTransitivity<V1, V2, Mid = ()>(PhantomData<(V1, V2, Mid)>);
93
94pub struct BySymmetry<V>(PhantomData<V>);
96
97pub struct AssocLeft;
103pub struct AssocRight;
105
106pub struct CombineAB;
108pub struct CombineBA;
110
111pub struct WithIdentity;
113pub struct JustA;
115
116pub struct WithInverse;
118pub struct Identity;
120
121pub struct Undistributed;
123pub struct Distributed;
125
126pub struct ZeroTimes;
128pub struct Zero;
130
131impl Justifies<AssocLeft, AssocRight> for ByAssociativity {}
137impl Justifies<AssocRight, AssocLeft> for ByAssociativity {}
138
139impl Justifies<CombineAB, CombineBA> for ByCommutativity {}
141impl Justifies<CombineBA, CombineAB> for ByCommutativity {}
142
143impl Justifies<WithIdentity, JustA> for ByIdentity {}
145impl Justifies<JustA, WithIdentity> for ByIdentity {}
146
147impl Justifies<WithInverse, Identity> for ByInverse {}
149impl Justifies<Identity, WithInverse> for ByInverse {}
150
151impl Justifies<Undistributed, Distributed> for ByDistribution {}
153impl Justifies<Distributed, Undistributed> for ByDistribution {}
154
155impl Justifies<ZeroTimes, Zero> for ByAnnihilation {}
157impl Justifies<Zero, ZeroTimes> for ByAnnihilation {}
158
159impl<V, Lhs, Rhs> Justifies<Rhs, Lhs> for BySymmetry<V> where V: Justifies<Lhs, Rhs> {}
161
162impl<V1, V2, Lhs, Mid, Rhs> Justifies<Lhs, Rhs> for ByTransitivity<V1, V2, Mid>
165where
166 V1: Justifies<Lhs, Mid>,
167 V2: Justifies<Mid, Rhs>,
168{
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[test]
176 fn associativity_rewrite() {
177 let _: Rewrite<AssocLeft, AssocRight, ByAssociativity> = Rewrite::witness();
178 let _: Rewrite<AssocRight, AssocLeft, ByAssociativity> = Rewrite::witness();
179 }
180
181 #[test]
182 fn commutativity_rewrite() {
183 let _: Rewrite<CombineAB, CombineBA, ByCommutativity> = Rewrite::witness();
184 }
185
186 #[test]
187 fn identity_rewrite() {
188 let _: Rewrite<WithIdentity, JustA, ByIdentity> = Rewrite::witness();
189 let _: Rewrite<JustA, WithIdentity, ByIdentity> = Rewrite::witness();
190 }
191
192 #[test]
193 fn inverse_rewrite() {
194 let _: Rewrite<WithInverse, Identity, ByInverse> = Rewrite::witness();
195 }
196
197 #[test]
198 fn distribution_rewrite() {
199 let _: Rewrite<Undistributed, Distributed, ByDistribution> = Rewrite::witness();
200 }
201
202 #[test]
203 fn annihilation_rewrite() {
204 let _: Rewrite<ZeroTimes, Zero, ByAnnihilation> = Rewrite::witness();
205 }
206
207 #[test]
208 fn symmetry() {
209 let step: Rewrite<AssocLeft, AssocRight, ByAssociativity> = Rewrite::witness();
210 let _back: Rewrite<AssocRight, AssocLeft, BySymmetry<ByAssociativity>> = step.sym();
211 }
212
213 #[test]
214 fn transitivity_chain() {
215 let step1: Rewrite<WithIdentity, JustA, ByIdentity> = Rewrite::witness();
220 let step2: Rewrite<JustA, WithIdentity, ByIdentity> = Rewrite::witness();
221 let _chained: Rewrite<
222 WithIdentity,
223 WithIdentity,
224 ByTransitivity<ByIdentity, ByIdentity, JustA>,
225 > = step1.then(step2);
226 }
227
228 #[test]
229 fn three_step_chain() {
230 let s1: Rewrite<WithInverse, Identity, ByInverse> = Rewrite::witness();
232 let s2: Rewrite<Identity, WithInverse, ByInverse> = Rewrite::witness();
233 let s3: Rewrite<WithInverse, Identity, ByInverse> = Rewrite::witness();
234 let _: Rewrite<
235 WithInverse,
236 Identity,
237 ByTransitivity<ByTransitivity<ByInverse, ByInverse, Identity>, ByInverse, WithInverse>,
238 > = s1.then(s2).then(s3);
239 }
240}