Search code examples
rustrayon

Error calling iter().sum(): the trait bound `f64: std::iter::Sum<&std::vec::Vec<f64>>` is not satisfied


I am struggling with a function that is supposed to return either an f64 or an Error. I have tried many combinations, but no success.

fn_rayon_parallel(&self) -> Result<f64, Box<dyn Error + Send + Sync>>  {

    let all_payoffs = (0..10000).into_par_iter().map( 
        |_| {   //things could go very wrong here        
                match self.get_one_payoff() {
                    Ok(payoff) => {Ok(payoff)},
                    Err(e) => Err(e)
                }
            }
    ).collect::<Result<Vec<_>, _>>();

    //this is the part I am struggling with, does not compile
    //I need to return either f64 or Error

    match all_payoffs {
        Ok(_v) => Ok(2.34 * (1.0/10000.0) * (all_payoffs.iter().sum::<f64>())),
        Err(e) => Err(From::from("There was an error in calculating Discounted Payoffs."))
    }


}

Error:

error[E0277]: the trait bound `f64: std::iter::Sum<&std::vec::Vec<f64>>` is not satisfied
  --> src/main.rs:81:69
   |
81 |             Ok(_v) => Ok(2.34 * (1.0/10000.0) * (all_payoffs.iter().sum::<f64>())),
   |                                                                     ^^^ the trait `std::iter::Sum<&std::vec::Vec<f64>>` is not implemented for `f64`
   |
   = help: the following implementations were found:
             <f64 as std::iter::Sum<&'a f64>>
             <f64 as std::iter::Sum>

Playground


Solution

  • Your main problem lies here (simplified a bit):

    match all_payoffs {
        Ok(_v) => Ok(1.0 * (all_payoffs.iter().sum::<f64>())),
        Err(e) => { /*...*/ }
    }
    

    Note that your all_payoffs variable is of type Result<Vec<f64>, Box<dyn Error + Send>>. So when you do the .iter() you think that you are getting an iterator for the values of the vector, of type &f64, but you are instead getting an iterator for the ok-value of the Result!!

    This is handy in a lot of situations, for example you can use Iterator::flatten() to sum all the values if Ok() but return 0.0 if Err():

    let x = all_payoffs.iter().flatten().sum::<f64>();
    

    But here the compiler thinks that you are trying to sum vectors and that cannot be done, thus you get an error that says:

    the trait bound f64: std::iter::Sum<&std::vec::Vec<f64>> is not satisfied

    That basically means: you cannot sum a bunch of &Vec<f64> and get a f64 as a result.

    The solution is right there in plain sight, use that _v:

    Ok(v) => Ok(1.0 * v.iter().sum::<f64>()),
    

    And now it works!