我正在做“ Rust by Example”的更多组合器部分,并决定自己动手,看看用map
代替多少努力and_then
。
在尝试过程中,我遇到了一些非常奇怪的事情(对我来说,它甚至看起来像是编译器错误)。它看起来像我只需要返回一个Food
类型时,返回类型应该是Option(Food)
我认为,cookable
下面的功能应该可以简化为一行:
have_ingredients(food).map(|f| can_cook(f))
显然也可以是:
have_ingredients(food).and_then(can_cook)
尽管我看不到这两个函数之间的根本区别,但它们都返回Option<U>
。
这样做时,我遇到一个奇怪的编译器错误,因此我按如下所示明确地破坏了匹配-看起来Food
即使返回类型为,编译器也想返回Some(Food)
。到底是怎么回事???
//! stack.rs
#[derive(Debug)]
enum Food {
CordonBleu,
Steak,
Sushi,
}
#[derive(Debug)]
enum Day {
Monday,
Tuesday,
Wednesday,
}
/// we don't have the ingredients for sushi
fn have_ingredients(food: Food) -> Option<Food> {
match food {
Food::Sushi => None,
_ => Some(food),
}
}
/// can cook anything but cordon blue
fn can_cook(food: Food) -> Option<Food> {
match food {
Food::CordonBlue => None,
_ => Some(food),
}
}
/// can be done using map
fn cookable(food: Food) -> Option<Food> {
match have_ingredients(food).map(|f| can_cook(f)) {
// Some(food) => food, // Why is this correct???
Some(food) => Some(food), // **error: mismatched types:
None => None,
}
}
fn eat(food: Food, day: Day) {
match cookable(food) {
Some(food) => println!("Yay! On {:?} we eat {:?}", day, food),
None => println!("Oh no we didn't get to eat on {:?}!", day),
};
}
fn main() {
let (cordon_bleu, steak, sushi) = (Food::CordonBleu, Food::Steak, Food::Sushi);
eat(cordon_bleu, Day::Monday);
eat(steak, Day::Tuesday);
eat(sushi, Day::Wednesday);
}
这是上述程序的完整编译器错误:
ch16_errors git:(master) ✗ rustc stack.rs
stack.rs:38:28: 38:32 error: mismatched types:
expected `Food`,
found `core::option::Option<Food>`
(expected enum `Food`,
found enum `core::option::Option`) [E0308]
stack.rs:38 Some(food) => Some(food),
^~~~
stack.rs:38:28: 38:32 help: run `rustc --explain E0308` to see a detailed explanation
error: aborting due to previous error
have_ingredients(food).map(|f| can_cook(f))
给出Option<Option<Food>>
,而不是Option<Food>
,因为map
它不会展平值。
考虑
Option<T>::map(Fn(T) -> U)
这将转换Option<T>
为Option<U>
。从而让T = Food
,U = Option<Food>
在can_cook
给出了实例
Option<Food>::map(Fn(Food) -> Option<Food>)
给出一个Option<Option<Food>>
。
因此Some(food)
,比赛中food
的类型为Option<Food>
。
and_then
展平结果类型,这就是为什么这种情况不会发生。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句