动态闭包 Vec 的错误类型推断
Bad type inference for the Vec of dynamic closures
我正在尝试获取部分应用函数的列表,如下所示:
fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter().map(|x| Box::new(move |y| x + y)).collect()
}
编译器给我一个错误:
error[E0277]: 类型 std::vec::Vec u32>> 的值无法从类型元素的迭代器构建std::boxed::Box<[闭包@src/main.rs:4:41: 4:57]>
后续尝试也没有成功:
1.
fn partially_applied_with_explicit_collect_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter().map(|x| Box::new(move |y| x + y)).collect::<Vec<Box<dyn Fn(u32) -> u32>>>()
}
fn partially_applied_with_explicit_vec_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
let mut res: Vec<Box<dyn Fn(u32) -> u32>> = xs.into_iter().map(|x| Box::new(move |y| x + y)).collect();
res
}
fn partially_applied_with_explicit_push() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
let mut res = vec![];
for x in xs {
res.push(Box::new(move |y| x + y));
}
res
}
也只有这次尝试终于成功了!
fn partially_applied_with_explicit_push_and_vec_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
let mut res: Vec<Box<dyn Fn(u32) -> u32>> = vec![];
for x in xs {
res.push(Box::new(move |y| x + y));
}
res
}
为什么动态闭包的类型推断如此糟糕?
为什么 collect
在第一次尝试中没有奏效?
有没有更好的方法利用类型推断来表达这样的想法?
潜在的问题是每个闭包都有自己的不可命名类型,它是唯一的成员。此外,虽然编译器可以自动将特定的盒装闭包转换为 Box<dyn *closure's type*>
,但它无法深入到泛型类型来执行向上转换。
所以下面是可以的:
fn closure() -> Box<dyn Fn(u32) -> u32> {
Box::new(|x| x)
}
但这不是:
fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter().map(|x| Box::new(move |y| x + y)).collect()
}
为什么不呢?
value of type `Vec<Box<dyn Fn(u32) -> u32>>` cannot be built from
`std::iter::Iterator<Item=Box<[closure@src/main.rs:12:37: 12:51]>>`
help: the trait `FromIterator<Box<[closure@src/main.rs:12:37: 12:51]>>`
is not implemented for `Vec<Box<dyn Fn(u32) -> u32>>`
因为 FromIterator
中 Vec
的特征绑定是
impl<T> FromIterator<T> for Vec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> { ... }
}
和 Box<[closure@src/main.rs]>
是不同于 Box<dyn Fn(u32) -> u32>
的类型。
所以问题不是“为什么 Rust 的类型推断在这里失败”,而是“为什么 Vec 没有实现以下内容”:
impl<T, U> FromIterator<T> for Vec<U>
where T: Into<U> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<U> { ... }
}
那个,我不知道。我怀疑当有多对 T,U
可以使事情正常时,这会导致类型推断本身的问题。
N.B。您可以将您的盒子转换为正确的类型,如下所示:
fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter()
.map(|x| Box::new(move |y| x + y) as Box<dyn Fn(u32) -> u32>)
.collect()
}
我正在尝试获取部分应用函数的列表,如下所示:
fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter().map(|x| Box::new(move |y| x + y)).collect()
}
编译器给我一个错误:
error[E0277]: 类型 std::vec::Vec
后续尝试也没有成功:
1.
fn partially_applied_with_explicit_collect_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter().map(|x| Box::new(move |y| x + y)).collect::<Vec<Box<dyn Fn(u32) -> u32>>>()
}
fn partially_applied_with_explicit_vec_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
let mut res: Vec<Box<dyn Fn(u32) -> u32>> = xs.into_iter().map(|x| Box::new(move |y| x + y)).collect();
res
}
fn partially_applied_with_explicit_push() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
let mut res = vec![];
for x in xs {
res.push(Box::new(move |y| x + y));
}
res
}
也只有这次尝试终于成功了!
fn partially_applied_with_explicit_push_and_vec_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
let mut res: Vec<Box<dyn Fn(u32) -> u32>> = vec![];
for x in xs {
res.push(Box::new(move |y| x + y));
}
res
}
为什么动态闭包的类型推断如此糟糕?
为什么 collect
在第一次尝试中没有奏效?
有没有更好的方法利用类型推断来表达这样的想法?
潜在的问题是每个闭包都有自己的不可命名类型,它是唯一的成员。此外,虽然编译器可以自动将特定的盒装闭包转换为 Box<dyn *closure's type*>
,但它无法深入到泛型类型来执行向上转换。
所以下面是可以的:
fn closure() -> Box<dyn Fn(u32) -> u32> {
Box::new(|x| x)
}
但这不是:
fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter().map(|x| Box::new(move |y| x + y)).collect()
}
为什么不呢?
value of type `Vec<Box<dyn Fn(u32) -> u32>>` cannot be built from
`std::iter::Iterator<Item=Box<[closure@src/main.rs:12:37: 12:51]>>`
help: the trait `FromIterator<Box<[closure@src/main.rs:12:37: 12:51]>>`
is not implemented for `Vec<Box<dyn Fn(u32) -> u32>>`
因为 FromIterator
中 Vec
的特征绑定是
impl<T> FromIterator<T> for Vec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> { ... }
}
和 Box<[closure@src/main.rs]>
是不同于 Box<dyn Fn(u32) -> u32>
的类型。
所以问题不是“为什么 Rust 的类型推断在这里失败”,而是“为什么 Vec 没有实现以下内容”:
impl<T, U> FromIterator<T> for Vec<U>
where T: Into<U> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<U> { ... }
}
那个,我不知道。我怀疑当有多对 T,U
可以使事情正常时,这会导致类型推断本身的问题。
N.B。您可以将您的盒子转换为正确的类型,如下所示:
fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
let xs = vec![1_u32, 2, 3];
xs.into_iter()
.map(|x| Box::new(move |y| x + y) as Box<dyn Fn(u32) -> u32>)
.collect()
}