1use crate::{
2 boolean::{And, False, True},
3 define,
4 primitives::{Composed, Constant, Identity},
5 Function,
6};
7
8pub type Zero = crate::primitives::SecondOf;
10
11define! {
12 pub fn Successor ::= {
17 N. F. X. { F, { N, F, X }}
18 } where
19 N: F,
20 {N, F}: X,
21 F: {N, F, X};
22
23 pub fn Add ::= { M. N. { M, Successor, N }} where
29 M: Successor,
30 {M, Successor}: N;
31
32 pub fn Multiply ::= { X. Y. (Composed<X, Y>) };
34
35 pub fn Predecessor ::= { N. F. X. { N, Pred_1<F>, Constant<X>, Identity }} where
40 N: (Pred_1<F>),
41 {N, Pred_1<F>}: (Constant<X>),
42 {N, Pred_1<F>, Constant<X>}: Identity;
43
44 fn Pred_1<F> ::= { G. H. { H, { G, F }}} where
45 H: {G, F},
46 G: F;
47
48 pub fn Subtract ::= { M. N. { N, Predecessor, M }} where
54 N: Predecessor,
55 {N, Predecessor}: M;
56
57 pub fn Exponent ::= { M. N. { N, M }} where N: M;
62
63
64 pub fn IsZero ::= { N. { N, Constant<False>, True }} where
71 N: (Constant<False>),
72 {N, Constant<False>}: True;
73
74
75 pub fn Leq ::= { M. N. { IsZero, { Subtract, M, N }}} where
82 Subtract: M,
83 {Subtract, M}: N,
84 IsZero: { Subtract, M, N };
85
86
87 pub fn Eq ::= { M. N. { And, { Leq, M, N }, { Leq, N, M }}} where
94 Leq: M, Leq: N,
95 {Leq, M}: N, {Leq, N}: M,
96 And: {Leq, M, N},
97 {And, { Leq, M, N }}: { Leq, N, M };
98
99 @[cfg(any(doc, feature = "const-numeral"))]
104 pub fn ToNumber ::= { N. { N, ConstIncrement, ConstNumber<0> }} where
105 N: ConstIncrement,
106 ConstIncrement: (ConstNumber<0>),
107 {N, ConstIncrement}: (ConstNumber<0>);
108
109
110}
111
112#[cfg(any(doc, feature = "const-numeral"))]
118pub struct ConstIncrement;
119#[cfg(any(doc, feature = "const-numeral"))]
121pub struct ConstNumber<const N: u64>;
122
123#[cfg(any(doc, feature = "const-numeral"))]
124impl<const N: u64> Function<ConstNumber<N>> for ConstIncrement
125where
126 ConstNumber<{ N + 1 }>: Sized,
127{
128 type Output = ConstNumber<{ N + 1 }>;
129}
130
131#[cfg(any(doc, feature = "const-numeral"))]
132impl<const N: u64> ConstNumber<N> {
133 #[inline]
135 pub const fn value() -> u64 { N }
136}
137
138#[cfg(test)]
139mod test {
140 #![allow(dead_code)]
141 use crate::prelude::*;
142
143 type Two = call!{Successor, { Successor, Zero }};
144 type Three = call!{Successor, Two};
145
146 #[test]
147 fn main() {
148 let _: call!{
149 Eq, {Multiply, Two, Three}, {Add, Three, Three}
150 } = <True>::default();
151 }
152}