Consider a trait like:
trait Container<T> {
type ContainerFamily<A>;
fn map<A>(&self, mapper: &dyn Fn(&T) -> A) -> Self::ContainerFamily<A>;
}
It's ok to impl it for a struct like
struct Box<T> {
val: T
}
impl<T> Container<T> for Box<T> {
type ContainerFamily<A> = Box<A>;
fn map<A>(&self, mapper: &dyn Fn(&T) -> A) -> <Self as Container<T>>::ContainerFamily<A> {
return Box{val: mapper(&self.val)}
}
}
However it's not possible to impl on another struct with restrictions on type parameter T
struct Box2<T: Copy> {
val: T
}
impl<T: Copy> Container<T> for Box2<T> {
type ContainerFamily<A> = Box2<A>;
// ^^^^^^^^ the trait bound `A: Copy` is not satisfied
fn map<A>(&self, mapper: &dyn Fn(&T) -> A) -> <Self as Container<T>>::ContainerFamily<A> {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `A: Copy` is not satisfied
return Box2{val: mapper(&self.val)}
}
}
If add where clause, make it to Box2::ContainerFamily<A: Copy>, it will have stricter requirements than trait, add compilier forbids that for now.
It seems the only solution for now is create specilized trait manually like:
trait CopyableContainer<T: Copy> {
type ContainerFamily<A: Copy>;
fn map<A: Copy>(&self, mapper: &dyn Fn(&T) -> A) -> Self::ContainerFamily<A>;
}
But with accociated traits we may be able to rewrite Container and impl it for Box2<T: Copy>:
trait Container<T> {
trait Restriction;
type ContainerFamily<A: Self::Restrinction>;
fn map<A: Self::Restrinction>(&self, mapper: &dyn Fn(&T) -> A) -> Self::ContainerFamily<A>;
}
struct Box2<T: Copy + AsRef<String>> {
val: T
}
impl<T: Copy + AsRef<String>> Container<T> for Box2<T> {
trait Restriction = Copy + AsRef<String>;
type ContainerFamily<A: Self::Restriction> = Box2<A>;
fn map<A: Self::Restriction>(&self, mapper: &dyn Fn(&T) -> A) -> <Self as Container<T>>::ContainerFamily<A> {
return Box2{val: mapper(&self.val)}
}
}
Infact trait Container<T, Restriction = Copy> is same with trait CopyableContainer, but the former has better code reusage and shared abstraction.
Is there any other approach for now to impl Container for Box2<T: Copy> in current nightly Rust?