My dream is this: I want to have traits `AlgebraAdd<A,B,Output=C>`

etc. that mirror the standard operations, but where `&self`

is some carrier/domain/"context" type which performs the algebraic operation with additional information that the "element" types might not have access to. (For example element types might be `rug::Integer`

but the "algebra" might have context like a modulus that should be applied to all values).

So I naively set out and define:

```
pub trait AlgebraAdd<T,U> {
type Output;
fn algebra_add(&self, a: T, b: U) -> Self::Output;
}
pub trait AlgebraRem<T,U> {
type Output;
fn algebra_rem(&self, a: T, b: U) -> Self::Output;
}
```

I might want to start making a naive quotient ring that works over any base ring that has `AlgebraRem`

.

```
pub struct NaiveQuotient<A,M> {
domain: A,
modulus: M,
}
```

(To make this concrete, the base ring might for example be univariate polynomials over the integers -- `Z[X]`

-- so `A`

might be `UnivariatePolynomials<K>`

and `M`

might be some specific polynomial in the form of `Vec<K>`

.)

Now, basically what I *want* to have is this super-generic definition of addition on `NaiveQuotient<A,M>`

:

```
impl<A,L,R,M,T> // Is it OK to have T only appear on the right-hand side of later type class constraints?
AlgebraAdd<L,R>
for NaiveQuotient<A,M>
where
A: AlgebraAdd<L,R,Output=T> + AlgebraRem<T,???> // <- I've tried for<'a> AlgebraRem<T,&'a M> but then how do I refer to its ::Output?
{
type Output = ???; // anything like <A as for<'a> ..>::Output doesn't parse.
fn algebra_add(&self, a: L, b: R) -> Self::Output {
let r = self.domain.algebra_add(a, b);
self.domain.algebra_rem(r, &self.modulus) // <- most of my problems stem from wanting to pass this as a reference.
}
}
```

(In general, for most of these types, I want to have at least `AlgebraBinaryOp<T,&T,Output=T>`

or something similar.)

The introduction of `&self.modulus`

(i.e. `&M`

) seems to force me to introduce lifetimes, which is the first thing that confuses me. The `AlgebraRem`

trait is defined in terms of generic parameters `<T,U>`

(where `U=&M`

just "happens" to be a reference here) -- how could there ever be an issue of worrying about the "lifetime" of `U`

? What I *want* to say is that `A`

fulfills the trait `AlgebraRem<T,&M>`

where `&M`

will "obviously" outlive my usage of the trait (i.e. the call to `AlgebraRem::algebra_rem()`

) so the compiler shouldn't have to worry about it?

When I try to tell the compiler to not worry about it with `for<'a> AlgebraRem<T,&'a M>`

I couldn't figure out how to refer to this type class' associated `Output`

type, since now it's a family of types, not just one?

I might just be super confused. Any sort of input on where I'm going wrong or how to implement this would be appreciated.

Or even links to libraries that have already done this sort of stuff before.