#![doc(html_root_url = "http://paholg.com/peano/peano/index.html")]
#![warn(missing_docs)]
#![crate_type="lib"]
use std::marker::PhantomData;
use std::ops::{Add, Sub, Mul, Div, Neg};
#[derive(Copy, Clone)]
pub struct Zero;
#[derive(Copy, Clone)]
pub struct Succ<N: NonNeg> {
_marker: PhantomData<N>
}
#[derive(Copy, Clone)]
pub struct Pred<N: NonPos> {
_marker: PhantomData<N>
}
pub type P1 = Succ<Zero>;
pub type P2 = Succ<P1>;
pub type P3 = Succ<P2>;
pub type P4 = Succ<P3>;
pub type P5 = Succ<P4>;
pub type P6 = Succ<P5>;
pub type P7 = Succ<P6>;
pub type P8 = Succ<P7>;
pub type P9 = Succ<P8>;
pub type N1 = Pred<Zero>;
pub type N2 = Pred<N1>;
pub type N3 = Pred<N2>;
pub type N4 = Pred<N3>;
pub type N5 = Pred<N4>;
pub type N6 = Pred<N5>;
pub type N7 = Pred<N6>;
pub type N8 = Pred<N7>;
pub type N9 = Pred<N8>;
pub trait Peano {}
pub trait NonZero: Peano {}
pub trait NonNeg: Peano {}
pub trait NonPos: Peano {}
impl Peano for Zero {}
impl NonNeg for Zero {}
impl NonPos for Zero {}
impl<N: NonNeg> Peano for Succ<N> {}
impl<N: NonNeg> NonNeg for Succ<N> {}
impl<N: NonNeg> NonZero for Succ<N> {}
impl<N: NonPos> Peano for Pred<N> {}
impl<N: NonPos> NonPos for Pred<N> {}
impl<N: NonPos> NonZero for Pred<N> {}
impl<Rhs> Add<Rhs> for Zero where Rhs: Peano {
type Output = Rhs;
#[allow(unused_variables)]
fn add(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Add<Rhs> for Succ<Lhs> where Lhs: NonNeg + Add<Rhs>, Rhs: NonNeg, <Lhs as Add<Rhs>>::Output: NonNeg {
type Output = Succ<<Lhs as Add<Rhs>>::Output>;
#[allow(unused_variables)]
fn add(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Add<Rhs> for Pred<Lhs> where Lhs: NonPos + Add<Rhs>, Rhs: NonPos, <Lhs as Add<Rhs>>::Output: NonPos {
type Output = Pred<<Lhs as Add<Rhs>>::Output>;
#[allow(unused_variables)]
fn add(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Add<Succ<Rhs>> for Pred<Lhs> where Lhs: NonPos + Add<Rhs>, Rhs: NonNeg {
type Output = <Lhs as Add<Rhs>>::Output;
#[allow(unused_variables)]
fn add(self, rhs: Succ<Rhs>) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Add<Pred<Rhs>> for Succ<Lhs> where Lhs: NonNeg + Add<Rhs>, Rhs: NonPos {
type Output = <Lhs as Add<Rhs>>::Output;
#[allow(unused_variables)]
fn add(self, rhs: Pred<Rhs>) -> Self::Output { unreachable!() }
}
impl Neg for Zero {
type Output = Zero;
fn neg(self) -> Self::Output { unreachable!() }
}
impl<N> Neg for Succ<N> where N: NonNeg + Neg, <N as Neg>::Output: NonPos {
type Output = Pred<<N as Neg>::Output>;
fn neg(self) -> Self::Output { unreachable!() }
}
impl<N> Neg for Pred<N> where N: NonPos + Neg, <N as Neg>::Output: NonNeg {
type Output = Succ<<N as Neg>::Output>;
fn neg(self) -> Self::Output { unreachable!() }
}
impl<Rhs> Sub<Rhs> for Zero where Rhs: Neg{
type Output = <Rhs as Neg>::Output;
#[allow(unused_variables)]
fn sub(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs> Sub<Zero> for Succ<Lhs> where Lhs: NonNeg {
type Output = Succ<Lhs>;
#[allow(unused_variables)]
fn sub(self, rhs: Zero) -> Self::Output { unreachable!() }
}
impl<Lhs> Sub<Zero> for Pred<Lhs> where Lhs: NonPos {
type Output = Pred<Lhs>;
#[allow(unused_variables)]
fn sub(self, rhs: Zero) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Sub<Succ<Rhs>> for Succ<Lhs> where Lhs: NonNeg + Sub<Rhs>, Rhs: NonNeg {
type Output = <Lhs as Sub<Rhs>>::Output;
#[allow(unused_variables)]
fn sub(self, rhs: Succ<Rhs>) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Sub<Pred<Rhs>> for Pred<Lhs> where Lhs: NonPos + Sub<Rhs>, Rhs: NonPos {
type Output = <Lhs as Sub<Rhs>>::Output;
#[allow(unused_variables)]
fn sub(self, rhs: Pred<Rhs>) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Sub<Pred<Rhs>> for Succ<Lhs> where Lhs: NonNeg + Sub<Rhs>, Rhs: NonPos, <Lhs as Sub<Rhs>>::Output: NonNeg {
type Output = Succ<Succ<<Lhs as Sub<Rhs>>::Output>>;
#[allow(unused_variables)]
fn sub(self, rhs: Pred<Rhs>) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Sub<Succ<Rhs>> for Pred<Lhs> where Lhs: NonPos + Sub<Rhs>, Rhs: NonNeg, <Lhs as Sub<Rhs>>::Output: NonPos {
type Output = Pred<Pred<<Lhs as Sub<Rhs>>::Output>>;
#[allow(unused_variables)]
fn sub(self, rhs: Succ<Rhs>) -> Self::Output { unreachable!() }
}
impl<Rhs> Mul<Rhs> for Zero where Rhs: Peano {
type Output = Zero;
#[allow(unused_variables)]
fn mul(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Mul<Rhs> for Succ<Lhs> where Lhs: NonNeg + Mul<Rhs>, Rhs: Add<<Lhs as Mul<Rhs>>::Output> {
type Output = <Rhs as Add<<Lhs as Mul<Rhs>>::Output>>::Output;
#[allow(unused_variables)]
fn mul(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Mul<Rhs> for Pred<Lhs> where Lhs: NonPos + Mul<Rhs>, Rhs: Peano, <Lhs as Mul<Rhs>>::Output: Sub<Rhs> {
type Output = <<Lhs as Mul<Rhs>>::Output as Sub<Rhs>>::Output;
#[allow(unused_variables)]
fn mul(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Rhs> Div<Rhs> for Zero where Rhs: Peano {
type Output = Zero;
#[allow(unused_variables)]
fn div(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Div<Rhs> for Succ<Lhs> where Lhs: NonNeg, Succ<Lhs>: DivPrivate<Rhs> {
type Output = <Succ<Lhs> as DivPrivate<Rhs>>::Output;
#[allow(unused_variables)]
fn div(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
impl<Lhs, Rhs> Div<Rhs> for Pred<Lhs> where Lhs: NonPos + Neg, Rhs: Neg, Succ<<Lhs as Neg>::Output>: DivPrivate<<Rhs as Neg>::Output>, <Lhs as Neg>::Output: NonNeg {
type Output = <<Pred<Lhs> as Neg>::Output as DivPrivate<<Rhs as Neg>::Output>>::Output;
#[allow(unused_variables)]
fn div(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
mod detail {
pub trait DivPrivate<Rhs>: ::Peano {
type Output;
}
}
use detail::DivPrivate;
impl<Rhs: NonZero> DivPrivate<Rhs> for Zero {
type Output = Zero;
}
impl<Lhs, Rhs> DivPrivate<Succ<Rhs>> for Succ<Lhs>
where Lhs: NonNeg, Rhs: NonNeg,
Succ<Lhs>: DivPrivate<Succ<Rhs>> + Sub<Succ<Rhs>>,
<Succ<Lhs> as Sub<Succ<Rhs>>>::Output: DivPrivate<Succ<Rhs>>,
<<Succ<Lhs> as Sub<Succ<Rhs>>>::Output as DivPrivate<Succ<Rhs>>>::Output: NonNeg
{
type Output = <P1 as Add<<<Succ<Lhs> as Sub<Succ<Rhs>>>::Output as DivPrivate<Succ<Rhs>>>::Output>>::Output;
}
impl<Lhs, Rhs> DivPrivate<Pred<Rhs>> for Succ<Lhs>
where Lhs: NonNeg, Rhs: NonPos,
Succ<Lhs>: DivPrivate<Pred<Rhs>> + Add<Pred<Rhs>>,
<Succ<Lhs> as Add<Pred<Rhs>>>::Output: DivPrivate<Pred<Rhs>>,
<<Succ<Lhs> as Add<Pred<Rhs>>>::Output as DivPrivate<Pred<Rhs>>>::Output: NonPos
{
type Output = <N1 as Add<<<Succ<Lhs> as Add<Pred<Rhs>>>::Output as DivPrivate<Pred<Rhs>>>::Output>>::Output;
}
impl<Lhs: Peano> DivPrivate<Zero> for Lhs {
type Output = P1;
}
pub trait Same<Rhs = Self> {
type Output;
}
impl<N> Same<N> for N where N: Peano {
type Output = N;
}
pub trait ToInt: Peano {
#[allow(missing_docs)]
fn to_int() -> i32;
}
impl ToInt for Zero {
fn to_int() -> i32 { 0 }
}
impl<N: NonNeg + ToInt> ToInt for Succ<N> {
fn to_int() -> i32 { 1 + N::to_int() }
}
impl<N: NonPos + ToInt> ToInt for Pred<N> {
fn to_int() -> i32 { -1 + N::to_int() }
}