1use std::marker::PhantomData;
30
31pub use type_proof_macros::N;
32
33pub trait Nat {
35 const VALUE: usize;
37
38 type Add<N: Nat>: Nat;
42
43 type Mul<N: Nat>: Nat;
47
48 type Pow<N: Nat>: Nat;
55}
56
57pub struct Succ<N>
59where
60 N: Nat,
61{
62 _n: PhantomData<N>,
63}
64
65impl<N> Nat for Succ<N>
66where
67 N: Nat,
68{
69 const VALUE: usize = N::VALUE + 1;
70
71 type Add<M: Nat> = Succ<N::Add<M>>;
72
73 type Mul<M: Nat> = <N::Mul<M> as Nat>::Add<M>;
74
75 type Pow<M: Nat> = <N::Pow<M> as Nat>::Mul<M>;
76}
77
78pub struct N0 {}
80
81impl Nat for N0 {
82 const VALUE: usize = 0;
83
84 type Add<N: Nat> = N;
85
86 type Mul<N: Nat> = N0;
87
88 type Pow<N: Nat> = N1;
89}
90
91pub type N1 = Succ<N0>;
93
94pub type N2 = Succ<N1>;
96
97pub type N3 = Succ<N2>;
99
100pub type N4 = Succ<N3>;
102
103pub type N5 = Succ<N4>;
105
106pub type N6 = Succ<N5>;
108
109pub type N7 = Succ<N6>;
111
112pub type N8 = Succ<N7>;
114
115pub type N9 = Succ<N8>;
117
118pub type N10 = Succ<N9>;
120
121#[allow(type_alias_bounds)]
124pub type Add<N, M>
125where
126 N: Nat,
127 M: Nat,
128= <N as Nat>::Add<M>;
129
130#[allow(type_alias_bounds)]
133pub type Mul<N, M>
134where
135 N: Nat,
136 M: Nat,
137= <N as Nat>::Mul<M>;
138
139#[allow(type_alias_bounds)]
144pub type Pow<N, M>
145where
146 N: Nat,
147 M: Nat,
148= <M as Nat>::Pow<N>;
149
150#[cfg(test)]
151mod tests {
152 use crate::type_utils::assert_type_eq;
153
154 use super::*;
155
156 #[test]
157 fn value() {
158 assert_eq!(N0::VALUE, 0);
159 assert_eq!(N1::VALUE, 1);
160 assert_eq!(N5::VALUE, 5);
161 assert_eq!(N8::VALUE, 8);
162 }
163
164 #[test]
165 fn add() {
166 assert_type_eq::<N0, Add<N0, N0>>();
167 assert_type_eq::<N3, Add<N3, N0>>();
168 assert_type_eq::<N2, Add<N0, N2>>();
169 assert_type_eq::<N5, Add<N3, N2>>();
170 }
171
172 #[test]
173 fn mul() {
174 assert_type_eq::<N0, Mul<N0, N0>>();
175 assert_type_eq::<N0, Mul<N3, N0>>();
176 assert_type_eq::<N0, Mul<N0, N2>>();
177 assert_type_eq::<N3, Mul<N3, N1>>();
178 assert_type_eq::<N2, Mul<N1, N2>>();
179 assert_type_eq::<N6, Mul<N3, N2>>();
180 }
181
182 #[test]
183 fn pow() {
184 assert_type_eq::<N1, Pow<N0, N0>>();
185 assert_type_eq::<N0, Pow<N0, N2>>();
186 assert_type_eq::<N1, Pow<N3, N0>>();
187 assert_type_eq::<N1, Pow<N1, N2>>();
188 assert_type_eq::<N9, Pow<N3, N2>>();
189 }
190
191 #[test]
192 fn nat_macro() {
193 assert_type_eq::<N!(0), N0>();
194 assert_type_eq::<N!(4), N4>();
195
196 type N15Macro = N!(15);
197 assert_eq!(N15Macro::VALUE, 15);
198 }
199}