pub struct Zero;
pub struct Succ<T: NonNeg>;
pub struct Pred<T: NonPos>;
pub type One = Succ<Zero>;
pub trait Peano {}
pub trait NonZero: Peano {}
pub trait NonNeg: Peano {}
pub trait NonPos: Peano {}
pub trait Pos: Peano + NonZero + NonNeg {}
pub trait Neg: Peano + NonZero + NonPos {}
impl Peano for Zero {}
impl NonNeg for Zero {}
impl NonPos for Zero {}
impl<T: NonNeg> Peano for Succ<T> {}
impl<T: NonNeg> NonNeg for Succ<T> {}
impl<T: NonNeg> NonZero for Succ<T> {}
impl<T: NonNeg> Pos for Succ<T> {}
impl<T: NonPos> Peano for Pred<T> {}
impl<T: NonPos> NonPos for Pred<T> {}
impl<T: NonPos> NonZero for Pred<T> {}
impl<T: NonPos> Neg for Pred<T> {}
pub trait PInt: Peano + AddPeano + SubPeano + MulPeano + Negate + ToInt {}
impl PInt for Zero {}
impl PInt for One {}
impl PInt for Pred<Zero> {}
impl Copy for Zero {}
pub trait AddPeano<RHS = Self> {
type Output;
}
impl<RHS: Peano> AddPeano<RHS> for Zero {
type Output = RHS;
}
impl<T: NonNeg + AddPeano<Succ<RHS>>, RHS: NonNeg> AddPeano<Succ<RHS>> for Succ<T> {
type Output = Succ<<T as AddPeano<Succ<RHS>>>::Output>;
}
impl<T: NonNeg> AddPeano<Zero> for Succ<T> {
type Output = Succ<T>;
}
impl<T: NonNeg + AddPeano<RHS>, RHS: NonPos> AddPeano<Pred<RHS>> for Succ<T> {
type Output = <T as AddPeano<RHS>>::Output;
}
impl<T: NonPos + AddPeano<Pred<RHS>>, RHS: NonPos> AddPeano<Pred<RHS>> for Pred<T> {
type Output = Pred<<T as AddPeano<Pred<RHS>>>::Output>;
}
impl<T: NonPos> AddPeano<Zero> for Pred<T> {
type Output = Pred<T>;
}
impl<T: NonPos + AddPeano<RHS>, RHS: NonNeg> AddPeano<Succ<RHS>> for Pred<T> {
type Output = <T as AddPeano<RHS>>::Output;
}
pub trait Negate {
type Output;
}
impl Negate for Zero {
type Output = Zero;
}
impl<T: NonNeg + Negate> Negate for Succ<T> {
type Output = Pred<<T as Negate>::Output>;
}
impl<T: NonPos + Negate> Negate for Pred<T> {
type Output = Succ<<T as Negate>::Output>;
}
pub trait SubPeano<RHS = Self> {
type Output;
}
impl<RHS: Peano + Negate> SubPeano<RHS> for Zero {
type Output = <RHS as Negate>::Output;
}
impl<T: NonNeg + SubPeano<RHS>, RHS: NonNeg> SubPeano<Succ<RHS>> for Succ<T> {
type Output = <T as SubPeano<RHS>>::Output;
}
impl<T: NonNeg> SubPeano<Zero> for Succ<T> {
type Output = Succ<T>;
}
impl<T: NonNeg + SubPeano<RHS>, RHS: NonPos> SubPeano<Pred<RHS>> for Succ<T> {
type Output = Succ<Succ<<T as SubPeano<RHS>>::Output>>;
}
impl<T: NonPos + SubPeano<RHS>, RHS: NonNeg> SubPeano<Succ<RHS>> for Pred<T> {
type Output = Pred<Pred<<T as SubPeano<RHS>>::Output>>;
}
impl<T: NonPos> SubPeano<Zero> for Pred<T> {
type Output = Pred<T>;
}
impl<T: NonPos + SubPeano<RHS>, RHS: NonPos> SubPeano<Pred<RHS>> for Pred<T> {
type Output = <T as SubPeano<RHS>>::Output;
}
pub trait MulPeano<RHS = Self> {
type Output;
}
impl<RHS: Peano> MulPeano<RHS> for Zero {
type Output = Zero;
}
impl<T, RHS> MulPeano<RHS> for Succ<T>
where T: NonNeg + MulPeano<RHS>, RHS: AddPeano<<T as MulPeano<RHS>>::Output> {
type Output = <RHS as AddPeano<<T as MulPeano<RHS>>::Output>>::Output;
}
impl<T, RHS> MulPeano<RHS> for Pred<T>
where T: NonPos + MulPeano<RHS>, RHS: Peano, <T as MulPeano<RHS>>::Output: SubPeano<RHS> {
type Output = <<T as MulPeano<RHS>>::Output as SubPeano<RHS>>::Output;
}
pub trait ToInt {
fn to_int() -> i32;
}
impl ToInt for Zero {
fn to_int() -> i32 { 0 }
}
impl<T:NonNeg + ToInt> ToInt for Succ<T> {
fn to_int() -> i32 { 1 + <T as ToInt>::to_int() }
}
impl<T:NonPos + ToInt> ToInt for Pred<T> {
fn to_int() -> i32 { -1 + <T as ToInt>::to_int() }
}
#[test]
fn test_peano() {
type Two = Succ<One>;
type Three = Succ<Two>;
type Four = Succ<Three>;
type NegOne = Pred<Zero>;
type NegTwo = Pred<NegOne>;
type NegThree = Pred<NegTwo>;
assert_eq!( 0, <Zero as ToInt>::to_int() );
assert_eq!( 2, <Two as ToInt>::to_int() );
assert_eq!( -2, <NegTwo as ToInt>::to_int() );
assert_eq!( 0, <<Zero as AddPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( 3, <<Zero as AddPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( -3, <<Zero as AddPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( 2, <<Two as AddPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( 5, <<Two as AddPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( -1, <<Two as AddPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( 1, <<Three as AddPeano<NegTwo>>::Output as ToInt>::to_int() );
assert_eq!( -2, <<NegTwo as AddPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( -5, <<NegTwo as AddPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( 1, <<NegTwo as AddPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( -1, <<NegThree as AddPeano<Two>>::Output as ToInt>::to_int() );
assert_eq!( -3, <<Three as Negate>::Output as ToInt>::to_int() );
assert_eq!( 3, <<NegThree as Negate>::Output as ToInt>::to_int() );
assert_eq!( 0, <<Zero as Negate>::Output as ToInt>::to_int() );
assert_eq!( 0, <<Zero as SubPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( -3, <<Zero as SubPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( 3, <<Zero as SubPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( 2, <<Two as SubPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( -1, <<Two as SubPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( 5, <<Two as SubPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( 5, <<Three as SubPeano<NegTwo>>::Output as ToInt>::to_int() );
assert_eq!( -2, <<NegTwo as SubPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( 1, <<NegTwo as SubPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( -5, <<NegTwo as SubPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( -5, <<NegThree as SubPeano<Two>>::Output as ToInt>::to_int() );
assert_eq!( 0, <<Zero as MulPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( 0, <<Zero as MulPeano<Two>>::Output as ToInt>::to_int() );
assert_eq!( 0, <<Two as MulPeano<Zero>>::Output as ToInt>::to_int() );
assert_eq!( 6, <<Two as MulPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( -6, <<Two as MulPeano<NegThree>>::Output as ToInt>::to_int() );
assert_eq!( -6, <<NegTwo as MulPeano<Three>>::Output as ToInt>::to_int() );
assert_eq!( 6, <<NegTwo as MulPeano<NegThree>>::Output as ToInt>::to_int() );
}