[英]How do I idiomatically implement From<A<T>> for A<U> without conflict?
I have created a generic, monadic type -- call it A<T>
.我创建了一个通用的单子类型——称之为A<T>
。 I would like to be able to have this type convert safely between A<T>
to A<U>
if U: From<T>
, while still encapsulating it within an A<_>
, ideally without having to expose or use a T
directly.如果U: From<T>
,我希望能够在A<T>
到A<U>
之间安全地转换这种类型,同时仍然将它封装在A<_>
中,理想情况下不必公开或使用T
直接地。
What I would like to do, is to implement From<A<T>>
constrained with U: From<T>
;我想做的是实现From<A<T>>
受U: From<T>
约束; however the following code does not compile:但是以下代码无法编译:
struct A<T>{
val: T
}
impl<T, U> From<A<T>> for A<U>
where U: From<T>
{
fn from(other: A<T>) -> A<U> {
A{ val: U::from(other.val) }
}
}
The above fails to compile due to the generic implementation impl<T> From<T> for T
defined in core
.由于在core
中定义的 T 的通用实现impl<T> From<T> for T
上述代码无法编译。 The full error is:完整的错误是:
error[E0119]: conflicting implementations of trait `std::convert::From<A<_>>` for type `A<_>` --> src/lib.rs:5:1 | 5 | impl<T, U> From<A<T>> for A<U> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: conflicting implementation in crate `core`: - impl<T> From<T> for T;
The reason for why this fails is clear: this definition applies for cases where T == U
, which would make this impl From<A<T>> for A<T>
which is the same as From<T> for T
-- and thus, a conflict.失败的原因很明显:此定义适用于T == U
的情况,这将使impl From<A<T>> for A<T>
的From<T> for T
相同 -因此,冲突。 However what is not clear is what the idiomatic approach is to overcome this -- since I cannot imagine I am the only one to want to keep a type fully encapsulated.然而,尚不清楚克服这一问题的惯用方法是什么——因为我无法想象我是唯一一个想要完全封装类型的人。
Is this possible to achieve without needing unstable features like negative trait-bounds or trait-specializations?这是否有可能在不需要不稳定特征(如负面特征界限或特征专业化)的情况下实现? If not, what is the general, idiomatic approach to support a From
conversion while still encapsulating the type?如果不是,那么在封装类型的同时支持From
转换的一般惯用方法是什么? Am I stuck implementing a function that behaves exactly like fn from(...)
, but without implementing the trait?我是否坚持实施一个 function ,其行为与fn from(...)
完全一样,但没有实施该特征?
There is no way to make没有办法使
impl<T, U> From<A<T>> for A<U>
where U: From<T>
succeed.成功。 (Even if a future version of Rust offers specialization, it would only work here if the built-in From<T> for T
impl were marked as allowing specialization.) (即使 Rust 的未来版本提供专业化,它也只能在From<T> for T
被标记为允许专业化的情况下才能在这里工作。)
Your choices are:您的选择是:
Implement the conversion for concrete non-equal types — From<A<Bar>> for A<Foo>
.实现具体不等类型的转换—— From<A<Bar>> for A<Foo>
。 (I assume this is not desirable for your application, but you seem interested in a broad answer.) (我认为这不适合您的应用程序,但您似乎对广泛的答案感兴趣。)
As you already thought of, “implementing a function that behaves exactly like fn from(...)
, but without implementing the trait”.正如您已经想到的,“实现一个 function,它的行为与fn from(...)
完全一样,但没有实现 trait”。 I'd write it like:我会这样写:
impl<T> A<T> { fn convert<U>(self) -> A<U> where T: Into<U> { A { val: self.val.into() } } }
But note that if your monadic type has a map()
method, then this is just .map(Into::into)
.但请注意,如果你的 monadic 类型有一个map()
方法,那么这就是.map(Into::into)
。
Define your own conversion trait, that is not From
.定义您自己的转换特征,而不是From
。
There's probably no reason to do this in your case, unless you have other types similar to A
, but considered broadly, this is actually fairly common;在您的情况下可能没有理由这样做,除非您有其他类似于A
类型,但从广义上考虑,这实际上是相当普遍的; many libraries define IntoFoo
trait(s), for various reasons.出于各种原因,许多库都定义IntoFoo
特征。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.