1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use std::marker::PhantomData;

pub trait SealedNat {}

pub trait Nat: SealedNat + Send + Copy + 'static
{
  #[allow(non_upper_case_globals)]
  const Value: Self;

  fn nat() -> Self;
}

#[derive(Copy, Clone)]
pub struct Z;

#[derive(Copy, Clone)]
pub struct S<N>(pub PhantomData<N>);

impl SealedNat for Z {}

impl Nat for Z
{
  #[allow(non_upper_case_globals)]
  const Value: Z = Z;

  fn nat() -> Z
  {
    Z
  }
}

impl<N> SealedNat for S<N> where N: Nat {}

impl<N> Nat for S<N>
where
  N: Nat,
{
  #[allow(non_upper_case_globals)]
  const Value: S<N> = S(PhantomData);

  fn nat() -> S<N>
  {
    S(PhantomData)
  }
}

pub fn succ<N>(_: N) -> S<N>
{
  S(PhantomData)
}