and then sum()
knows to return an i32
Это то место, где вы поступили не так. Проверьте Iterator::sum
:
fn sum<S>(self) -> S
where S: Sum<Self::Item>
возвращает общий тип S
, который должен реализовать Sum
. S
не должны соответствовать Self::Item
. Поэтому для компилятора необходимо указать тип .
Почему это полезно? Ознакомьтесь с этими двумя примерами из стандартной библиотеки:
impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
Это верно! Вы можете суммировать итератор u8
или итератор &u8
! Если этого не было, то этот код не будет работать:
fn main() {
let a: i32 = (0..5).sum();
let b: i32 = [0, 1, 2, 3, 4].iter().sum();
assert_eq!(a, b);
}
As bluss points out, мы могли бы сделать это, имея ассоциированный тип который бы связать u8 -> u8
и &'a u8 -> u8
.
Если у нас был только связанный тип, тогда тип целевой суммы всегда был бы исправлен, и мы потеряли бы гибкость. Например, мы можем также реализовать Sum
для наших собственных типов.
Здесь мы подытожим u8
s, но увеличьте размер суммируемого типа, так как, вероятно, сумма превысит u8
. Эта реализация в дополнения к существующим реализациям из стандартной библиотеки:
#[derive(Debug, Copy, Clone)]
struct Points(i32);
impl std::iter::Sum<u8> for Points {
fn sum<I>(iter: I) -> Points
where I: Iterator<Item = u8>
{
let mut pts = Points(0);
for v in iter {
pts.0 += v as i32;
}
pts
}
}
fn main() {
let total: Points = (0u8..42u8).sum();
println!("{:?}", total);
}
Связанный вопрос: http: // stackoverflow.com/q/40243061/1233251 –