如何满足 f32 的 `Sum<T>` 特征要求?
How can I satisfy the `Sum<T>` trait requirement for f32?
我正在努力实现以下特征:
pub trait CentralMoment<Output = f32>
where
Output: Copy,
{
fn mean(&self) -> Output;
}
impl<T> CentralMoment for [T] {
fn mean(&self) -> f32 {
let sum: f32 = self.iter().sum();
sum / self.len() as f32
}
}
我的问题是行 let sum: f32 = self.iter().sum()
。编译器告诉我:
the trait bound `f32: Sum<&T>` is not satisfied
--> src/lib.rs:45:36
|
45 | let sum: f32 = self.iter().sum();
| ^^^ the trait `Sum<&T>` is not implemented for `f32`
|
help: consider extending the `where` bound, but there might be an alternative better way to express this requirement
|
42 | T: Copy, f32: Sum<&T>
但即使我尝试包含 f32: Sum<&T>
,我仍然会遇到同样的错误。
我在这里做错了什么,我该如何解决这个问题?提前致谢,如果您需要进一步说明,请告诉我。
泛型的算术很棘手。正确设置所有约束和类型就像打地鼠游戏。每次您修复错误时,都会弹出另一个错误。我不想直接跳到答案;最好逐一完成每个步骤。也就是说,如果您只想查看底部的解决方案。
让我们开始吧。
1。复制数字
看看implementors for Sum
。它们看起来像这样:
impl Sum<f32> for f32
impl Sum<f64> for f64
impl Sum<i8> for i8
impl Sum<i16> for i16
impl Sum<i32> for i32
...
以此类推
一般模式很明显:
impl Sum<T> for T
None 个与您的代码匹配,因为它显然在尝试使用 Sum<&T>
。我们需要去掉引用,所以 Sum<&T>
可以是 Sum<T>
.
引用来自哪里? iter()
遍历项目引用。它这样做是为了避免修改集合或其项目。
我们可以使用 into_iter()
直接迭代项目。不过,我们不要。 into_iter()
将集合 转换为 迭代器。转化……就像摧毁一样。它移动所有项目并在此过程中消耗集合。哎呀!
相反,让我们复制带有 copied()
的项目:
This is useful when you have an iterator over &T
, but you need an iterator over T
.
let sum: f32 = self.iter().copied().sum();
我们还需要一个 T: Copy
约束:
impl<T> CentralMoment for [T]
where
T: Copy,
这会将错误更改为:
error[E0277]: the trait bound `f32: Sum<T>` is not satisfied
--> src/lib.rs:13:45
|
13 | let sum: f32 = self.iter().copied().sum();
| ^^^ the trait `Sum<T>` is not implemented for `f32`
2。求和结果为T
当你总结一堆 i32
时,你将得到一个 i32
。当您对一堆 f64
求和时,您将得到一个 f64
。此代码表示 sum()
的结果将是一个 f32
,但实际上要适当地通用,您应该将其称为 T
.
let sum: T = self.iter().copied().sum();
现在的错误是:
error[E0277]: the trait bound `T: Sum` is not satisfied
--> src/lib.rs:13:43
|
13 | let sum: T = self.iter().copied().sum();
| ^^^ the trait `Sum` is not implemented for `T`
3。 T
必须是可求和的
我们可以修复要求 T: Sum
:
where
T: Copy + Sum,
现在我们得到:
error[E0369]: cannot divide `T` by `f32`
--> src/lib.rs:16:13
|
16 | sum / self.len() as f32
| --- ^ ----------------- f32
| |
| T
4。 T
必须能被 f32
整除
我们很接近,对吧?让我们要求 T
可以被 f32
s:
整除
where
T: Copy + Sum + Div<f32>,
编译器,你开心吗?
error[E0308]: mismatched types
--> src/lib.rs:17:9
|
15 | fn mean(&self) -> f32 {
| --- expected `f32` because of return type
16 | let sum: T = self.iter().copied().sum();
17 | sum / self.len() as f32
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `f32`, found associated type
|
= note: expected type `f32`
found associated type `<T as Div<f32>>::Output`
= help: consider constraining the associated type `<T as Div<f32>>::Output` to `f32`
不,当然不是。很好很好,接下来呢?
5。除法必须 return 一个 f32
嗯,我们要求 T
可以被 f32
整除。不过,我们还没有告诉它结果是什么类型。操作数类型和结果类型不一定相同。他们可能不同。 Rust 非常灵活。
我们需要对操作的 ::Output
进行约束。让我们要求输出也是 f32
:
where
T: Copy + Sum + Div<f32, Output = f32>,
结果:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.91s
哈利路亚!公主不在别的城堡
解决方案
use std::iter::Sum;
use std::ops::Div;
pub trait CentralMoment<Output = f32>
where
Output: Copy,
{
fn mean(&self) -> Output;
}
impl<T> CentralMoment for [T]
where
T: Copy + Sum + Div<f32, Output = f32>,
{
fn mean(&self) -> f32 {
let sum: T = self.iter().copied().sum();
sum / self.len() as f32
}
}
我正在努力实现以下特征:
pub trait CentralMoment<Output = f32>
where
Output: Copy,
{
fn mean(&self) -> Output;
}
impl<T> CentralMoment for [T] {
fn mean(&self) -> f32 {
let sum: f32 = self.iter().sum();
sum / self.len() as f32
}
}
我的问题是行 let sum: f32 = self.iter().sum()
。编译器告诉我:
the trait bound `f32: Sum<&T>` is not satisfied
--> src/lib.rs:45:36
|
45 | let sum: f32 = self.iter().sum();
| ^^^ the trait `Sum<&T>` is not implemented for `f32`
|
help: consider extending the `where` bound, but there might be an alternative better way to express this requirement
|
42 | T: Copy, f32: Sum<&T>
但即使我尝试包含 f32: Sum<&T>
,我仍然会遇到同样的错误。
我在这里做错了什么,我该如何解决这个问题?提前致谢,如果您需要进一步说明,请告诉我。
泛型的算术很棘手。正确设置所有约束和类型就像打地鼠游戏。每次您修复错误时,都会弹出另一个错误。我不想直接跳到答案;最好逐一完成每个步骤。也就是说,如果您只想查看底部的解决方案。
让我们开始吧。
1。复制数字
看看implementors for Sum
。它们看起来像这样:
impl Sum<f32> for f32
impl Sum<f64> for f64
impl Sum<i8> for i8
impl Sum<i16> for i16
impl Sum<i32> for i32
...
以此类推
一般模式很明显:
impl Sum<T> for T
None 个与您的代码匹配,因为它显然在尝试使用 Sum<&T>
。我们需要去掉引用,所以 Sum<&T>
可以是 Sum<T>
.
引用来自哪里? iter()
遍历项目引用。它这样做是为了避免修改集合或其项目。
我们可以使用 into_iter()
直接迭代项目。不过,我们不要。 into_iter()
将集合 转换为 迭代器。转化……就像摧毁一样。它移动所有项目并在此过程中消耗集合。哎呀!
相反,让我们复制带有 copied()
的项目:
This is useful when you have an iterator over
&T
, but you need an iterator overT
.
let sum: f32 = self.iter().copied().sum();
我们还需要一个 T: Copy
约束:
impl<T> CentralMoment for [T]
where
T: Copy,
这会将错误更改为:
error[E0277]: the trait bound `f32: Sum<T>` is not satisfied
--> src/lib.rs:13:45
|
13 | let sum: f32 = self.iter().copied().sum();
| ^^^ the trait `Sum<T>` is not implemented for `f32`
2。求和结果为T
当你总结一堆 i32
时,你将得到一个 i32
。当您对一堆 f64
求和时,您将得到一个 f64
。此代码表示 sum()
的结果将是一个 f32
,但实际上要适当地通用,您应该将其称为 T
.
let sum: T = self.iter().copied().sum();
现在的错误是:
error[E0277]: the trait bound `T: Sum` is not satisfied
--> src/lib.rs:13:43
|
13 | let sum: T = self.iter().copied().sum();
| ^^^ the trait `Sum` is not implemented for `T`
3。 T
必须是可求和的
我们可以修复要求 T: Sum
:
where
T: Copy + Sum,
现在我们得到:
error[E0369]: cannot divide `T` by `f32`
--> src/lib.rs:16:13
|
16 | sum / self.len() as f32
| --- ^ ----------------- f32
| |
| T
4。 T
必须能被 f32
整除
我们很接近,对吧?让我们要求 T
可以被 f32
s:
where
T: Copy + Sum + Div<f32>,
编译器,你开心吗?
error[E0308]: mismatched types
--> src/lib.rs:17:9
|
15 | fn mean(&self) -> f32 {
| --- expected `f32` because of return type
16 | let sum: T = self.iter().copied().sum();
17 | sum / self.len() as f32
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `f32`, found associated type
|
= note: expected type `f32`
found associated type `<T as Div<f32>>::Output`
= help: consider constraining the associated type `<T as Div<f32>>::Output` to `f32`
不,当然不是。很好很好,接下来呢?
5。除法必须 return 一个 f32
嗯,我们要求 T
可以被 f32
整除。不过,我们还没有告诉它结果是什么类型。操作数类型和结果类型不一定相同。他们可能不同。 Rust 非常灵活。
我们需要对操作的 ::Output
进行约束。让我们要求输出也是 f32
:
where
T: Copy + Sum + Div<f32, Output = f32>,
结果:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 0.91s
哈利路亚!公主不在别的城堡
解决方案
use std::iter::Sum;
use std::ops::Div;
pub trait CentralMoment<Output = f32>
where
Output: Copy,
{
fn mean(&self) -> Output;
}
impl<T> CentralMoment for [T]
where
T: Copy + Sum + Div<f32, Output = f32>,
{
fn mean(&self) -> f32 {
let sum: T = self.iter().copied().sum();
sum / self.len() as f32
}
}