Types 为什么可以';t trust推断迭代器::sum的结果类型?

Types 为什么可以';t trust推断迭代器::sum的结果类型?,types,rust,type-inference,Types,Rust,Type Inference,此代码适用于: fn main() { let a: i32 = (1i32..10).sum(); let b = a.pow(2); } 如果从a中删除i32类型,则会出现以下错误: rustc 1.13.0(2c6933acc 2016-11-07) 错误:此值的类型在此上下文中必须是已知的 --> 我本以为锈蚀会将(1i32..10)变成i32迭代器,然后sum()知道返回i32。我错过了什么 然后sum()知道返回一个i32 这是关键缺失点。虽然“输入”类型已经是已知

此代码适用于:

fn main() {
    let a: i32 = (1i32..10).sum();
    let b = a.pow(2);
}
如果从
a
中删除
i32
类型,则会出现以下错误:

rustc 1.13.0(2c6933acc 2016-11-07)
错误:此值的类型在此上下文中必须是已知的
-->

我本以为锈蚀会将
(1i32..10)
变成
i32
迭代器,然后
sum()
知道返回
i32
。我错过了什么

然后
sum()
知道返回一个
i32

这是关键缺失点。虽然“输入”类型已经是已知的(它必须是实现
迭代器
的东西,以便
求和
可用),但“输出”类型非常灵活

退房:

没错!您可以将
u8的迭代器
&u8的迭代器相加!如果我们没有这个,那么这个代码就不起作用了:

fn main() {
    let a: i32 = (0..5).sum();
    let b: i32 = [0, 1, 2, 3, 4].iter().sum();
    assert_eq!(a, b);
}
,我们可以通过一个关联的类型来实现这一点,该类型将绑定
u8->u8
&'aU8->u8

但是,如果我们只有一个关联的类型,那么目标和类型将始终是固定的,我们将失去灵活性。有关更多详细信息,请参阅

例如,我们还可以为自己的类型实现
Sum
。在这里,我们对
u8
s进行求和,但要增加求和类型的大小,因为求和很可能会超过a
u8
。此实现是对标准库中现有实现的补充:

impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
#[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);
}
#[派生(调试、复制、克隆)]
结构点(i32);
impl std::iter::积分总和{
fn总和(国际热核实验堆:I)->点数
哪里
I:迭代器,
{
设mut pts=点(0);
iter中的v{
pts.0+=v为i32;
}
临时秘书处
}
}
fn main(){
总数:点数=(0u8..42u8).sum();
println!(“{:?}”,总计);
}
然后
sum()
知道返回一个
i32

这是关键缺失点。虽然“输入”类型已经是已知的(它必须是实现
迭代器
的东西,以便
求和
可用),但“输出”类型非常灵活

退房:

没错!您可以将
u8的迭代器
&u8的迭代器相加!如果我们没有这个,那么这个代码就不起作用了:

fn main() {
    let a: i32 = (0..5).sum();
    let b: i32 = [0, 1, 2, 3, 4].iter().sum();
    assert_eq!(a, b);
}
,我们可以通过一个关联的类型来实现这一点,该类型将绑定
u8->u8
&'aU8->u8

但是,如果我们只有一个关联的类型,那么目标和类型将始终是固定的,我们将失去灵活性。有关更多详细信息,请参阅

例如,我们还可以为自己的类型实现
Sum
。在这里,我们对
u8
s进行求和,但要增加求和类型的大小,因为求和很可能会超过a
u8
。此实现是对标准库中现有实现的补充:

impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
#[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);
}
#[派生(调试、复制、克隆)]
结构点(i32);
impl std::iter::积分总和{
fn总和(国际热核实验堆:I)->点数
哪里
I:迭代器,
{
设mut pts=点(0);
iter中的v{
pts.0+=v为i32;
}
临时秘书处
}
}
fn main(){
总数:点数=(0u8..42u8).sum();
println!(“{:?}”,总计);
}

定义
sum
的方式,返回值是开放的;不止一种类型可以实现trait
Sum
。下面是一个示例,其中使用了
a
的不同类型,这两种类型都可以编译:

#[derive(Clone, Copy)]
struct Summer {
    s: isize,
}

impl Summer {
    fn pow(&self, p: isize) {
        println!("pow({})", p);
    }
}

impl std::iter::Sum<i32> for Summer {
    fn sum<I>(iter: I) -> Self
    where
        I: Iterator<Item = i32>,
    {
        let mut result = 0isize;
        for v in iter {
            result += v as isize;
        }
        Summer { s: result }
    }
}

fn main() {
    let a1: i32 = (1i32..10).sum();
    let a2: Summer = (1i32..10).sum();
    let b1 = a1.pow(2);
    let b2 = a2.pow(2);
}
#[派生(克隆,复制)]
结构夏季{
s:isize,
}
夏天{
fn pow(&self,p:isize){
println!(“pow({})”,p);
}
}
impl std::iter::夏季总和{
fn sum(iter:I)->自
哪里
I:迭代器,
{
让mut result=0isize;
iter中的v{
结果+=v为isize;
}
夏季{s:result}
}
}
fn main(){
设a1:i32=(1i32..10).sum();
设a2:Summer=(1i32..10).sum();
设b1=a1.pow(2);
设b2=a2.pow(2);
}


由于两种结果类型都是可能的,因此无法推断该类型,必须通过turbofish(
sum::()
)或表达式的结果(
let x:x=…sum();
)显式指定该类型。

定义
sum
的方式,返回值是开放的;不止一种类型可以实现trait
Sum
。下面是一个示例,其中使用了
a
的不同类型,这两种类型都可以编译:

#[derive(Clone, Copy)]
struct Summer {
    s: isize,
}

impl Summer {
    fn pow(&self, p: isize) {
        println!("pow({})", p);
    }
}

impl std::iter::Sum<i32> for Summer {
    fn sum<I>(iter: I) -> Self
    where
        I: Iterator<Item = i32>,
    {
        let mut result = 0isize;
        for v in iter {
            result += v as isize;
        }
        Summer { s: result }
    }
}

fn main() {
    let a1: i32 = (1i32..10).sum();
    let a2: Summer = (1i32..10).sum();
    let b1 = a1.pow(2);
    let b2 = a2.pow(2);
}
#[派生(克隆,复制)]
结构夏季{
s:isize,
}
夏天{
fn pow(&self,p:isize){
println!(“pow({})”,p);
}
}
impl std::iter::夏季总和{
fn sum(iter:I)->自
哪里
I:迭代器,
{
让mut result=0isize;
iter中的v{
结果+=v为isize;
}
夏季{s:result}
}
}
fn main(){
设a1:i32=(1i32..10).sum();
设a2:Summer=(1i32..10).sum();
设b1=a1.pow(2);
设b2=a2.pow(2);
}


由于这两种结果类型都是可能的,因此无法推断该类型,必须通过turbofish(
sum::()
)或表达式的结果(
let x:x=…sum();
)显式指定该类型;仅仅因为多个类型想要求和到同一事物,并不意味着必须有另一个类型参数。它可以通过关联类型
&'a i8->i8
i8->i8
来解决。谢谢。我的意思是,这不是你的问题,它在图书馆里,但由于这个答案是通过一些步骤来合理化它,我想指出它。无论如何,合理化现有的impl可能是通往幸福的道路;-)我认为这是一个逻辑步骤缺失;仅仅因为多个类型想要求和到同一个东西,并不意味着一定要有