#![cfg_attr(feature = "specialization", feature(specialization))] #[macro_use] extern crate type_operators; #[cfg(feature = "specialization")] mod test { use std::default::Default; use std::fmt::Debug; type_operators! { [A, B, C, D, E] data Nat: Default + Debug where #[derive(Default, Debug)] { P, I(Nat = P), O(Nat = P), Undefined, Error, DEFAULT, } data Bool where #[derive(Default, Debug)] { False, True, DEFAULT, } (Pred) Predecessor(Nat): Nat { [Undefined] => Undefined [P] => Undefined forall (N: Nat) { [(O N)] => (I (# N)) [(I N)] => (O N) {N} => Error } } (Succ) Successor(Nat): Nat { [Undefined] => Undefined [P] => I forall (N: Nat) { [(O N)] => (I N) [(I N)] => (O (# N)) {N} => Error } } (Sum) Adding(Nat, Nat): Nat { [P, P] => P forall (N: Nat) { [(O N), P] => (O N) [(I N), P] => (I N) [P, (O N)] => (O N) [P, (I N)] => (I N) } forall (N: Nat, M: Nat) { [(O M), (O N)] => (O (# M N)) [(I M), (O N)] => (I (# M N)) [(O M), (I N)] => (I (# M N)) [(I M), (I N)] => (O (# (# M N) I)) {M, N} => Error } } (Difference) Subtracting(Nat, Nat): Nat { forall (N: Nat) { [N, P] => N } forall (N: Nat, M: Nat) { [(O M), (O N)] => (O (# M N)) [(I M), (O N)] => (I (# M N)) [(O M), (I N)] => (I (# (# M N) I)) [(I M), (I N)] => (O (# M N)) {M, N} => Error } } (Product) Multiplying(Nat, Nat): Nat { forall (N: Nat) { [P, N] => P } forall (N: Nat, M: Nat) { [(O M), N] => (# M (O N)) [(I M), N] => (@Adding N (# M (O N))) {M, N} => Error } } (If) NatIf(Bool, Nat, Nat): Nat { forall (T: Nat, U: Nat) { [True, T, U] => T [False, T, U] => U } forall (B: Bool, T: Nat, U: Nat) { {B, T, U} => Error } } (NatIsUndef) NatIsUndefined(Nat): Bool { [Undefined] => True [P] => False forall (M: Nat) { [(O M)] => False [(I M)] => False {M} => Error } } (NatUndef) NatUndefined(Nat, Nat): Nat { forall (M: Nat) { [Undefined, M] => Undefined [P, M] => M } forall (M: Nat, N: Nat) { [(O N), M] => M [(I N), M] => M {M, N} => Error } } (TotalDifference) TotalSubtracting(Nat, Nat): Nat { [P, P] => P [Undefined, P] => Undefined forall (N: Nat) { [N, Undefined] => Undefined [P, (O N)] => (# P N) [P, (I N)] => Undefined [(O N), P] => (O N) [(I N), P] => (I N) [Undefined, (O N)] => Undefined [Undefined, (I N)] => Undefined } forall (N: Nat, M: Nat) { [(O M), (O N)] => (@NatUndefined (# M N) (O (# M N))) [(I M), (O N)] => (@NatUndefined (# M N) (I (# M N))) [(O M), (I N)] => (@NatUndefined (# (# M N) I) (I (# (# M N) I))) [(I M), (I N)] => (@NatUndefined (# M N) (O (# M N))) {M, N} => Error } } (Quotient) Quotienting(Nat, Nat): Nat { forall (D: Nat) { [Undefined, D] => Undefined [P, D] => (@NatIf (@NatIsUndefined (@TotalSubtracting P D)) O (@Successor (# (@TotalSubtracting P D) D))) } forall (N: Nat, D: Nat) { [(O N), D] => (@NatIf (@NatIsUndefined (@TotalSubtracting (O N) D)) O (@Successor (# (@TotalSubtracting (O N) D) D))) [(I N), D] => (@NatIf (@NatIsUndefined (@TotalSubtracting (I N) D)) O (@Successor (# (@TotalSubtracting (I N) D) D))) {N, D} => Error } } (Remainder) Remaindering(Nat, Nat): Nat { forall (D: Nat) { [Undefined, D] => Undefined [P, D] => (@NatIf (@NatIsUndefined (@TotalSubtracting P D)) P (# (@TotalSubtracting P D) D)) } forall (N: Nat, D: Nat) { [(O N), D] => (@NatIf (@NatIsUndefined (@TotalSubtracting (O N) D)) (O N) (# (@TotalSubtracting (O N) D) D)) [(I N), D] => (@NatIf (@NatIsUndefined (@TotalSubtracting (I N) D)) (I O) (# (@TotalSubtracting (I N) D) D)) {N, D} => Error } } } #[test] fn invariants() { let _ = as Default>::default(); let _ = > as Default>::default(); let _ = >, I> as Default>::default(); let _ = , O> as Default>::default(); let _ = >>, I> as Default>::default(); let _ = , I>> as Default>::default(); let _ = , O> as Default>::default(); let _ = >>, O>> as Default>::default(); } }