Why is a type annotation needed for this addition/sum?

The following code doesn't work unless I annotate s (or sum).

let s : f64 = us.samples.iter().map(|&sample| {
	if !sample.is_diagnosed() {
		f64::from(sample.rank)
	} else if !us.can_fulfill( &sample ) {
		10f64 //we want to discard
	} else {
		0f64
	}
}).sum();
s + (MAX_SAMPLES - us.samples.len()) as f64

I can't figure out why it needs an annotation as all the output of the map appears to be an f64, and both sides of the addition are f64.

All calls to sum need type annotation.

(maybe not correct explanation, can see someone else giving different.)

To avoid type annotation the compiler has to find a single data type to substitute for generic S. Since data types can be made from generic (or there can be generic implementation of Sum) there is potentially infinite types to search.

It is easy enough to make an alternate.

struct Foo;
impl ::std::iter::Sum<f64> for Foo {
    fn sum<I>(iter: I) -> Self where I: Iterator<Item = f64> {
        Foo
    }
}

Alternatively; Imagine if it worked without. Your using a crate and that crate gets updated with a implementation. Your code would suddenly break from the second choice.

1 Like

Yeah, I think that’s correct. It’s sort of the same thing as Into::into - the output is generic and destination type needs to be known (or inferred).

1 Like

Correcting myself, this isn't strictly true; it can be inferred with use of subsequent statement.
Not with + since Add is generic.

fn i(i:f64) -> f64 {i}
let sum = i(sum);
1 Like