Cannot infer type for `B` for filter_map().sum()

2019-07-24 15:15发布

The code below reads numbers, sums them, then prints the sum. I've tried few annotations, but it didn't work. I must be missing something. How could I make it work?

use std::io;
use std::io::Read;

fn main() {
    let mut buff = String::new();
    io::stdin().read_to_string(&mut buff).expect("read_to_string error");

    let v: i32 = buff
        .split_whitespace()
        .filter_map(|w| w.parse().ok())
        .sum();

    println!("{:?}", v);
}

Error message from compiler:

type annotations needed
 --> src\main.rs:9:10
  |
9 |         .filter_map(|w| w.parse().ok())
  |          ^^^^^^^^^^ cannot infer type for `B`

2条回答
放我归山
2楼-- · 2019-07-24 15:19

The quick fix is to say which type you are parsing into:

let v: i32 = buff
    .split_whitespace()
    .filter_map(|w| w.parse::<i32>().ok())
    .sum();

The reason is that filter_map has a type variable B, which would need to be inferred from the closure that you pass to it (the closure returns Option<B>). However, parse() also has a type variable for the type you are parsing into, which also can often be inferred. But here the type-checker would have to infer each of these types from each other, which obviously can't be done. To break the cycle, you have to tell it somewhere what the concrete type is.

You also could have fixed it by annotating filter_map. It's not as nice because filter_map has two type parameters, but you can still let the second one be inferred by using an _:

let v: i32 = buff
    .split_whitespace()
    .filter_map::<i32, _>(|w| w.parse().ok())
    .sum();
查看更多
SAY GOODBYE
3楼-- · 2019-07-24 15:25

Let's look up the signature of filter_map to see, what the complain is about:

fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where F: FnMut(Self::Item) -> Option<B>, 

Okay, so Option<B> is the result, which means he cannot infer what w.parse().ok() will be.

Let's try to give him a hint

.filter_map(|w| w.parse::<i32>().ok())

Let's compile an see.... Hurray!

So, lesson learned: Look up the signature and try to figure out, which part the compiler cannot infer and try to specify it.

查看更多
登录 后发表回答