1use std::marker::PhantomData;
2use crate::*;
3use crate::classes::*;
4
5
6#[derive(Copy, Clone, Default)]
7pub struct Z;
8
9#[derive(Copy, Clone, Default)]
10pub struct S<T> (PhantomData<T>);
11
12#[derive(Copy, Clone, Default)]
13pub struct Nat;
14
15impl Type for Nat {}
16
17impl Eq for Nat {}
18
19impl Value for Z {
20 type Type = Nat;
21}
22
23impl<T: Value<Type=Nat>> Value for S<T> {
24 type Type = Nat;
25}
26
27impl App<Z> for EqTo<Z> {
30 type Result = True;
31}
32
33impl<T: Value<Type=Nat>> App<Z> for EqTo<S<T>> {
34 type Result = False;
35}
36
37impl<T: Value<Type=Nat>> App<S<T>> for EqTo<Z> {
38 type Result = False;
39}
40
41impl<L: Value<Type=Nat>, R: Value<Type=Nat>, Eq: Value<Type=Bool>> App<S<R>> for EqTo<S<L>>
42 where EqTo<L>: App<R, Result=Eq>
43{
44 type Result = Eq;
45}
46
47
48pub type Add<A, B> = Eval<AddOn<A>, B>;
50#[derive(Copy, Clone, Default)]
51pub struct AddOn<A: Value<Type=Nat>>(PhantomData<A>);
52
53impl<A: Value<Type=Nat>> Value for AddOn<A> {
54 type Type = Lambda<Nat, Nat>;
55}
56
57impl<A: Value<Type=Nat>> App<Z> for AddOn<A> {
58 type Result = A;
59}
60
61impl<A: Value<Type=Nat>, B: Value<Type=Nat>, R: Value<Type=Nat>> App<S<B>> for AddOn<A>
62 where
63 AddOn<A>: Value<Type=Lambda<Nat, Nat>> + App<B, Result=R>
64{
65 type Result = S<R>;
66}