I would like to implement a type level composition with rust.
It would be great if the resulting function of Add
have the signature (&F::A, &G::A) -> (F::A, G::A)
rather than, &(F::A, G::A) -> (F::A, G::A)
.
Here is the minimal concept.
use std::marker::PhantomData;
pub trait UnaryOp {
type A;
fn op(x: &Self::A) -> Self::A;
}
pub struct Add<F, G>
where
F: UnaryOp,
G: UnaryOp,
{
_p: PhantomData<(F, G)>,
}
impl<F, G> UnaryOp for Add<F, G>
where
F: UnaryOp,
G: UnaryOp,
{
type A = (<F as UnaryOp>::A, <G as UnaryOp>::A);
// ! Take &(F::A, G::A), not (&F::A, &G::A)
fn op(x: &Self::A) -> Self::A {
(<F as UnaryOp>::op(&x.0), <G as UnaryOp>::op(&x.1))
}
}
pub struct Product<F, G>
where
F: UnaryOp,
G: UnaryOp,
{
_p: PhantomData<(F, G)>,
}
impl<F, G> UnaryOp for Product<F, G>
where
F: UnaryOp,
G: UnaryOp<A = <F as UnaryOp>::A>,
{
type A = <F as UnaryOp>::A;
// ! Can't put &(F::A, G::A) as argument for a function takes (&F::A, &G::A)
fn op(x: &Self::A) -> Self::A {
<F as UnaryOp>::op(&<G as UnaryOp>::op(x))
}
}
Here is a related question I asked earlier.
@Jmb Suggested a quite promising approach. However, it has limitation; does not work with non-tuple case. Since rust does not have specialization, I can't figure out out to improve it.
Is there any good approach to solve this problem?
- This is a duplication of Stack Overflow question: Rust Tuple of Reference and Reference of Tuple for type level operation - Stack Overflow