I’ve also found there to be a lot of boilerplate when implementing traits. For example:
struct Merge<A, I, J> where
A: Ord,
I: Iterator<A>,
J: Iterator<A>
{
a: Peekable<A, I>,
b: Peekable<A, J>,
}
fn merge<A, I, J>(a: I, b: J) -> Merge<A, I, J> where
A: Ord,
I: Iterator<A>,
J: Iterator<A>,
{
Merge { a: a.peekable(), b: b.peekable() }
}
impl<A, I, J> Iterator<A> for Merge<A, I, J> where
A: Ord,
I: Iterator<A>,
J: Iterator<A>
{
// ...
}
I was hoping for a way to abstract away the type parameter and constants, maybe like the following (this is just off the top of my head, haven’t really thought it through):
typeparams MergeType<A, I, J> where
A: Ord,
I: Iterator<A>,
J: Iterator<A>;
struct Merge<M: MergeType> {
{
a: Peekable<M.A, M.I>,
b: Peekable<M.A, M.J>,
}
I don’t think you could simply elide them from the constraint like @nicoxx suggests, as it’s possible that a trait is only implemented for a further constrained type than what the struct defines, but I think that it would help considerably if you could just share the type parameters and constrains so you could reuse them when appropriate.