Inferring types and using type annotations when pa

2019-07-21 13:19发布

问题:

I'm trying to write a function that will parse float from given string. It should return error in case of wrong or negative value.

fn read_value(strvalue: &str) -> Result<f32, Error> {
    match FromStr::from_str(strvalue) {
        None => Err(Error::InvalidValue),
        Some(value) => if value >= 0.0 {Ok(value)} else {Err(Error::InvalidValue)}
    }
}

This code gives:

src/main.rs:50:27: 50:32 error: the type of this value must be known in this context
src/main.rs:50         Some(value) => if value >= 0.0 {Ok(value)} else {Err(Error::InvalidValue)}

The first point. This error seems strange to me because, if I understand correctly, type of value can be inferred automatically. From the result type the type of value must be f32.

The second question. How can I fix this error? Or more general - how to annotate types of expressions in Rust?

E.g. in Haskell I can write something like:

if (value :: f32) > 0.0 ...

Or put type annotation in pattern match::

Some(value :: f32) => ...

回答1:

To work around it, I'd suggest using the parse method with a type parameter. To specify a functions type parameter, instead of calling foo(), you call foo::<types>():

fn read_value(strvalue: &str) -> Result<f32, u8> {
    match strvalue.parse::<f32>() {
        None => Err(1),
        Some(value) => if value >= 0.0 {Ok(value)} else {Err(2)}
    }
}

Another form that works without a type annotation (and hints that this might be a bug). This version uses a match guard:

fn read_value(strvalue: &str) -> Result<f32, u8> {
    match FromStr::from_str(strvalue) {
        None => Err(1),
        Some(value) if value >= 0.0 => Ok(value),
        _ => Err(2),
    }
}

And another using chained methods, representing it as a series of transforms:

fn read_value_chain(strvalue: &str) -> Result<f32, u8> {
    strvalue.parse()
        .ok_or(1)
        .and_then(|v: f32| if v > 0.0 { Ok(v) } else { Err(2) })
}