I wanted to try to build a proper implementation of Peano numbers using struct
s, but it seems my generics game is not good enough yet and I could use some help. I read the docs on generics and some StackOverflow questions, but they don't fit my case.
I introduced a Peano
trait and Zero
and Succ
types:
trait Peano {}
struct Zero;
struct Succ<T: Peano>(T);
And implemented a Peano
trait for both types to be able to abstract over both:
impl Peano for Zero {}
impl<T> Peano for Succ<T> where T: Peano {}
At first I wanted to implement std::ops::Add
for Peano
, but I quickly saw that I was doing something very wrong, so I decided to start with something simpler - enumeration:
trait Enumerate<T: Peano> {
fn succ(&self) -> Succ<T>;
fn pred(&self) -> Option<T>;
}
impl<T> Enumerate<T> for Zero where T: Peano {
fn succ(&self) -> Succ<T> { Succ(*self) } // mismatched types: Zero instead of T
fn pred(&self) -> Option<T> { None }
}
impl<T> Enumerate<T> for Succ<T> where T: Peano {
fn succ(&self) -> Succ<T> { Succ(*self) } // mismatched types: Succ<T> instead of T
fn pred(&self) -> Option<T> { Some(self.0) }
}
What am I missing? I experimented with boxing the results (though I would want to avoid that if possible), but the error just changed to mismatched types: Box<Succ<T>> instead of Box<Peano>
, so I'm not sure this is helpful.
Full code below:
trait Peano {}
#[derive(Debug, Clone, Copy, PartialEq)]
struct Zero;
#[derive(Debug, Clone, Copy, PartialEq)]
struct Succ<T: Peano>(T);
impl Peano for Zero {}
impl<T> Peano for Succ<T> where T: Peano {}
trait Enumerate<T: Peano> {
fn succ(&self) -> Succ<T>;
fn pred(&self) -> Option<T>;
}
impl<T> Enumerate<T> for Zero where T: Peano {
fn succ(&self) -> Succ<T> { Succ(*self) }
fn pred(&self) -> Option<T> { None }
}
impl<T> Enumerate<T> for Succ<T> where T: Peano {
fn succ(&self) -> Succ<T> { Succ(*self) }
fn pred(&self) -> Option<T> { Some(self.0) }
}