pub trait Nat {} pub struct Succ(T); // Inductively define naturals pub type _0 = (); impl Nat for _0 {} impl Nat for Succ {} pub mod prelude { pub type _1 = Succ<_0>; pub type _2 = Succ<_1>; pub type _3 = Succ<_2>; pub type _4 = Succ<_3>; pub type _5 = Succ<_4>; pub type _6 = Succ<_5>; pub type _7 = Succ<_6>; pub type _8 = Succ<_7>; pub type _9 = Succ<_8>; pub type _10 = Succ<_9>; pub use super::{ Nat, Succ, _0, eq::Eq, leq::Leq, geq::Geq, add::Add, mul::Mul, exp::Exp, parity::Even, parity::Odd }; } pub mod eq { use super::prelude::*; pub trait Eq { fn equal() -> () {} } // Define equality of naturals impl Eq for A {} } pub mod leq { use super::prelude::*; pub trait Leq { fn leq() -> () {} } // Base case // 0 <= N for every N impl Leq for _0 {} // Induction // A <= B means S(A) <= S(B) impl Leq> for Succ where A: Leq {} } pub mod geq { use super::prelude::*; pub trait Geq { fn geq() -> () {} } // If A <= B then B => A impl Geq for B where A: Leq {} } pub mod add { use super::prelude::*; pub trait Add { type Sum: Nat; } // Base case // N + 0 = N impl Add<_0> for T { type Sum = T; } // Induction // A + S(B) = S(A + B) impl Add> for A where A: Add { type Sum = Succ<>::Sum>; } } pub mod mul { use super::prelude::*; pub trait Mul { type Prod: Nat; } // Base case // N * 0 = 0 impl Mul<_0> for T { type Prod = _0; } // Induction // A * S(B) = A * B + A impl Mul> for A where A: Mul, >::Prod: Add { type Prod = <>::Prod as Add>::Sum; } } pub mod exp { use super::prelude::*; pub trait Exp { type Pow: Nat; } // Base case // N ^ 0 = 1 impl Exp<_0> for T { type Pow = _1; } // Induction // A ^ S(B) = A ^ B * A impl Exp> for A where A: Exp, >::Pow: Mul { type Pow = <>::Pow as Mul>::Prod; } } pub mod parity { use super::prelude::*; pub trait Even { fn even() -> () {} } pub trait Odd { fn odd() -> () {} } impl Even for _0 {} impl Even for Succ> {} impl Odd for _1 {} impl Odd for Succ> {} }