fn main() {
println!("{}", (1, (2, (4, Empty()))).get::<Succ<Succ<Zero>>>());
}
struct Empty ();
trait Cons<T> {
type Tail: Cons<T>;
fn get_head(&self) -> &T;
fn get_tail(&self) -> &Self::Tail;
fn get<P: Peano>(&self) -> &T where Self: std::marker::Sized {
P::get(self)
}
}
impl<T, C:Cons<T>> Cons<T> for (T, C) {
type Tail = C;
fn get_head(&self) -> &T {
&self.0
}
fn get_tail(&self) -> &Self::Tail {
&self.1
}
}
impl<T> Cons<T> for Empty {
type Tail = Empty;
fn get_head(&self) -> &T {
panic!()
}
fn get_tail(&self) -> &Self::Tail {
panic!()
}
}
enum Zero {}
trait Peano {
fn get<T, C: Cons<T>>(cons: &C) -> &T;
}
impl Peano for Zero {
fn get<T, C: Cons<T>>(cons: &C) -> &T {
cons.get_head()
}
}
struct Succ<T>(T);
impl<P: Peano> Peano for Succ<P> {
fn get<T, C: Cons<T>>(cons: &C) -> &T {
P::get(cons.get_tail())
}
}
Comments