use crate::{
boolean::{And, False, True},
define,
primitives::{Composed, Constant, Identity},
Function,
};
pub type Zero = crate::primitives::SecondOf;
define! {
pub fn Successor ::= {
N. F. X. { F, { N, F, X }}
} where
N: F,
{N, F}: X,
F: {N, F, X};
pub fn Add ::= { M. N. { M, Successor, N }} where
M: Successor,
{M, Successor}: N;
pub fn Multiply ::= { X. Y. (Composed<X, Y>) };
pub fn Predecessor ::= { N. F. X. { N, Pred_1<F>, Constant<X>, Identity }} where
N: (Pred_1<F>),
{N, Pred_1<F>}: (Constant<X>),
{N, Pred_1<F>, Constant<X>}: Identity;
fn Pred_1<F> ::= { G. H. { H, { G, F }}} where
H: {G, F},
G: F;
pub fn Subtract ::= { M. N. { N, Predecessor, M }} where
N: Predecessor,
{N, Predecessor}: M;
pub fn Exponent ::= { M. N. { N, M }} where N: M;
pub fn IsZero ::= { N. { N, Constant<False>, True }} where
N: (Constant<False>),
{N, Constant<False>}: True;
pub fn Leq ::= { M. N. { IsZero, { Subtract, M, N }}} where
Subtract: M,
{Subtract, M}: N,
IsZero: { Subtract, M, N };
pub fn Eq ::= { M. N. { And, { Leq, M, N }, { Leq, N, M }}} where
Leq: M, Leq: N,
{Leq, M}: N, {Leq, N}: M,
And: {Leq, M, N},
{And, { Leq, M, N }}: { Leq, N, M };
@[cfg(any(doc, feature = "const-numeral"))]
pub fn ToNumber ::= { N. { N, ConstIncrement, ConstNumber<0> }} where
N: ConstIncrement,
ConstIncrement: (ConstNumber<0>),
{N, ConstIncrement}: (ConstNumber<0>);
}
#[cfg(any(doc, feature = "const-numeral"))]
pub struct ConstIncrement;
#[cfg(any(doc, feature = "const-numeral"))]
pub struct ConstNumber<const N: u64>;
#[cfg(any(doc, feature = "const-numeral"))]
impl<const N: u64> Function<ConstNumber<N>> for ConstIncrement
where
ConstNumber<{ N + 1 }>: Sized,
{
type Output = ConstNumber<{ N + 1 }>;
}
#[cfg(any(doc, feature = "const-numeral"))]
impl<const N: u64> ConstNumber<N> {
#[inline]
pub const fn value() -> u64 { N }
}
#[cfg(test)]
mod test {
#![allow(dead_code)]
use crate::prelude::*;
type Two = call!{Successor, { Successor, Zero }};
type Three = call!{Successor, Two};
#[test]
fn main() {
let _: call!{
Eq, {Multiply, Two, Three}, {Add, Three, Three}
} = <True>::default();
}
}