Something like this.
use predicates::reflection;
use predicates::Predicate;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Tuple0<T>(T);
fn tuple0<T>(inner: T) -> Tuple0<T> {
Tuple0(inner)
}
impl<T: fmt::Display> fmt::Display for Tuple0<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{let var = var.0; {}}}", self.0)
}
}
impl<T: fmt::Display> reflection::PredicateReflection for Tuple0<T> {}
impl<T0, U0> Predicate<(U0,)> for Tuple0<T0>
where
T0: fmt::Display + Predicate<U0>,
{
fn eval(&self, variable: &(U0,)) -> bool {
self.0.eval(&variable.0)
}
}
impl<T, U, U1> Predicate<(U, U1)> for Tuple0<T>
where
T: fmt::Display + Predicate<U>,
{
fn eval(&self, variable: &(U, U1)) -> bool {
self.0.eval(&variable.0)
}
}
// impl<T, U, U1, U2> Predicate<(U, U1, U2)> for Tuple0<T>
// impl<T, U, U1, U2, U3> Predicate<(U, U1, U2, U3)> for Tuple0<T>
// ...
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Tuple1<T>(T);
fn tuple1<T>(inner: T) -> Tuple1<T> {
Tuple1(inner)
}
impl<T: fmt::Display> fmt::Display for Tuple1<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{let var = var.1; {}}}", self.0)
}
}
impl<T: fmt::Display> reflection::PredicateReflection for Tuple1<T> {}
impl<T, U0, U> Predicate<(U0, U)> for Tuple1<T>
where
T: fmt::Display + Predicate<U>,
{
fn eval(&self, variable: &(U0, U)) -> bool {
self.0.eval(&variable.1)
}
}
// impl<T, U0, U, U2> Predicate<(U0, U, U2)> for Tuple1<T>
// impl<T, U0, U, U2, U3> Predicate<(U0, U, U2, U3)> for Tuple1<T>
// ...
fn main() {
use predicates::prelude::*;
let t1 = (0,);
let t2 = (0, 1);
let p0 = tuple0(predicates::ord::eq(0));
let p1 = tuple1(predicates::ord::eq(2));
assert_eq!(p0.eval(&t1), true);
assert_eq!(p0.eval(&t2), true);
assert_eq!(p1.eval(&t2), false);
assert_eq!(p0.and(p1).eval(&t2), false);
assert_eq!(p0.or(p1).eval(&t2), true);
}