What is the right syntax to use std::iter::Iterator::reduce for summation?

Viewed 79

Among many codes I've tried for this one, this I think is the more concise code to show here:

fn summation<I>(nums: I) -> Option<I::Item>
where
    I: Iterator,
    I::Item: std::ops::Add,
{
    nums.reduce(|a, b| a + b)
}

fn main() {
    let numbers: Vec<f32> = vec![1f32, 2f32, 3f32];
    let result = summation(numbers.into_iter());
}

My goal is mainly tinkering with the Iterator::reduce's function to increase my understanding with Rust.

The code above spits out the following error when I run cargo check in the powershell:

    Checking code_demo v0.1.0 (C:\Users\miked\git\code_demo)
error[E0308]: mismatched types
 --> src\main.rs:6:24
  |
6 |     nums.reduce(|a, b| a + b)
  |                        ^^^^^ expected std::iter::Iterator::Item, found std::ops::Add::Output
  |
  = note: expected associated type `<I as Iterator>::Item`
             found associated type `<<I as Iterator>::Item as Add>::Output`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `code_demo`

To learn more, run the command again with --verbose.

I tried to replicate the code on docs.rs, but the code snippet over there is using Ord trait.

I tried this one as well:

fn summation<I>(nums: I) -> Option<I::Item>
where
    I: Iterator,
    I::Item: std::ops::Add::Output,
{
    nums.reduce(|a, b| a + b)
}

fn main() {
    let numbers: Vec<f32> = vec![1f32, 2f32, 3f32];
    let result = summation(numbers.into_iter());
}

And running cargo check would spit out:

    Checking code_demo v0.1.0 (C:\Users\miked\git\code_demo)
error[E0404]: expected trait, found associated type `std::ops::Add::Output`
 --> src\main.rs:4:14
  |
4 |     I::Item: std::ops::Add::Output,
  |              ^^^^^^^^^^^^^^^^^^^^^ not a trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0404`.
error: could not compile `code_demo`

To learn more, run the command again with --verbose.

Is there a way I can implement Add for the function to get the summation of vector of integers or vector of floats?

Or is it that what I'm trying to do impossible and just use use std::iter::Sum;? If so, how would that be implemented?

Thanks.

edits:
1st Sorry, forgot to remove the generic parameter T
2nd I added other solutions I tried

1 Answers

It seems like you got the general ideal of the issue. Since reduce requires that the reducer function returns I::Item, you need to explicitly set up the bounds of Add so that it is guaranteed to output the same type that it used as input. The syntax you're looking for is

I::Item: std::ops::Add<Output=I::Item>

so your code will compile with

fn summation<I>(nums: I) -> Option<I::Item>
where
    I: Iterator,
    I::Item: std::ops::Add<Output=I::Item>
{
    nums.reduce(|a, b| a + b)
}
Related