在 Rust 中一般乘以不同类型的值
Generically multiply values of different type in Rust
假设我想编写一个通用函数,它采用 K
类型的某些值并将其与 f64
可交换相乘。以下作品:
fn generic1<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Copy,
f64: Mul<K, Output = K>,
{
a * b + b * a
}
但是,我现在不能再在同一个函数中乘以两个浮点数。实际上,绑定 f64: Mul<K, Output = K>
似乎是 overriding/hiding (?) impl impl Mul<f64> for f64
。这是一个例子:
fn generic2<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Add<f64, Output = K> + Copy,
f64: Mul<K, Output = K>,
{
a * b + b * a + b * b
}
这给出了以下编译器错误:
|
16 | a * b + b * a + b * b
| ^ expected type parameter, found f64
|
= note: expected type `K`
found type `f64`
(playground link),即 f64 * <whatever>
现在仅适用于类型为 K
.
的 <whatever>
作为变通方法,我可以使用完全限定语法 <f64 as Mul<f64>>::mul(b, b)
,但那非常难看。感觉编译器应该能够看到它可以使用类型 f64
的输出,因此使用 f64 * f64
的实现而不是 f64 * K
.
我想要做的事情的一个不太抽象的例子:K
可以是向量类型,也可以是标量类型,我希望能够以通用的方式用它进行交换标量乘法。
这是怎么回事?为什么我不能再乘 b * b
?
更新:@Ömer-erden 注意到它在显式指定 f64: Mul<f64, Output = f64>
时也有效。不幸的是,在导入 alga
crate - see the updated playground link.
时,解决方法失效了
我不太确定藻类会做什么来打破已经很奇怪的行为。正如 Ömer 已经指出的那样,这看起来更像是类型检查器的错误或限制,而不是 alga/whatever 中的错误,因为理想情况下没有代码应该能够破坏 impl Mul<f64, Output = f64>
或类似的解析任何内置类型。
这是一个约束条件,它告诉当 K
是右操作数时,您可以将 f64
与 K
相乘,输出将是 K
。还告诉 f64
必须执行 Mul<K, Output = K>
f64: Mul<K, Output = K>,
我还不知道,这可能是因为类型检查器的能力有限或错误,但由于约束 Mul<K, Output = K>
.
如果您明确说明在您的情况下 Mul<f64, Output = f64>
的预期行为:
fn generic2<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Add<f64, Output = K> + Copy,
f64: Mul<K, Output = K> + Mul<f64, Output = f64>,
{
a * b + b * a + b * b
}
它将按预期工作。
假设我想编写一个通用函数,它采用 K
类型的某些值并将其与 f64
可交换相乘。以下作品:
fn generic1<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Copy,
f64: Mul<K, Output = K>,
{
a * b + b * a
}
但是,我现在不能再在同一个函数中乘以两个浮点数。实际上,绑定 f64: Mul<K, Output = K>
似乎是 overriding/hiding (?) impl impl Mul<f64> for f64
。这是一个例子:
fn generic2<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Add<f64, Output = K> + Copy,
f64: Mul<K, Output = K>,
{
a * b + b * a + b * b
}
这给出了以下编译器错误:
|
16 | a * b + b * a + b * b
| ^ expected type parameter, found f64
|
= note: expected type `K`
found type `f64`
(playground link),即 f64 * <whatever>
现在仅适用于类型为 K
.
<whatever>
作为变通方法,我可以使用完全限定语法 <f64 as Mul<f64>>::mul(b, b)
,但那非常难看。感觉编译器应该能够看到它可以使用类型 f64
的输出,因此使用 f64 * f64
的实现而不是 f64 * K
.
我想要做的事情的一个不太抽象的例子:K
可以是向量类型,也可以是标量类型,我希望能够以通用的方式用它进行交换标量乘法。
这是怎么回事?为什么我不能再乘 b * b
?
更新:@Ömer-erden 注意到它在显式指定 f64: Mul<f64, Output = f64>
时也有效。不幸的是,在导入 alga
crate - see the updated playground link.
我不太确定藻类会做什么来打破已经很奇怪的行为。正如 Ömer 已经指出的那样,这看起来更像是类型检查器的错误或限制,而不是 alga/whatever 中的错误,因为理想情况下没有代码应该能够破坏 impl Mul<f64, Output = f64>
或类似的解析任何内置类型。
这是一个约束条件,它告诉当 K
是右操作数时,您可以将 f64
与 K
相乘,输出将是 K
。还告诉 f64
必须执行 Mul<K, Output = K>
f64: Mul<K, Output = K>,
我还不知道,这可能是因为类型检查器的能力有限或错误,但由于约束 Mul<K, Output = K>
.
如果您明确说明在您的情况下 Mul<f64, Output = f64>
的预期行为:
fn generic2<K>(a: K, b: f64) -> K
where
K: Mul<f64, Output = K> + Add<K, Output = K> + Add<f64, Output = K> + Copy,
f64: Mul<K, Output = K> + Mul<f64, Output = f64>,
{
a * b + b * a + b * b
}
它将按预期工作。