Rust Tuple of Reference and Reference of Tuple for type level operation

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?

I'm still not quite following what you're trying to do here, but I did manage to make something compile:

2 Likes

Interesting! I also end up making something similar, implementing the trait for the tuple and all other non-tuple types by macro! Thank you so much for your time. I got a bit more confidence on this issue :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.