怎么做等于嵌套的“ impl Trait”呢?

时间:2018-10-19 03:56:24

标签: rust

function Afunction B作为参数,function B再次以function C作为参数。我尝试如下语法,但这给了我一个错误:

fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> () {
 // ...
}  
error[E0666]: nested `impl Trait` is not allowed
 --> src/main.rs:2:21
  |
2 |     fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> () {
  |             --------^^^^^^^^^^^^^^^-------
  |             |       |
  |             |       nested `impl Trait` here
  |             outer `impl Trait`

由于某些原因,我不能使用&dyn关键字:

fn a(b: impl Fn(&dyn Fn() -> ()) -> ()) -> () {
 // ...
} 

还有其他方法吗?

我不知道为什么嵌套impl Trait 会导致错误。

1 个答案:

答案 0 :(得分:10)

嵌套的隐式特性不起作用,因为尚未指定或实现。另外,因为考虑到Rust的其他部分如何工作,它并不是很有用。

fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> ()可以使用完全通用语法编写为

fn a<B, C>(b: B) -> ()
where B: Fn(C) -> (),
      C: Fn() -> ()

那是什么意思?这意味着B是可调用对象,它接受其他可调用对象的参数。但是这里重要的是具体类型。具体来说,B不会接受具有兼容签名的任何呼叫,而特别是C。什么是C?好吧,这就是问题所在。如果您这样拨打a

a(|f| f());

然后C是lambda参数f的类型,但是该类型是未知的,因为不能单独从用法中推导出参数f的类型。但是假设这不是问题,a的主体将是什么样?

fn a<B, C>(b: B) -> ()
where B: Fn(C) -> (),
      C: Fn() -> () {
  b(|| ())
}

在这里,我们尝试调用b传递lambda。但是lambda的类型是unnamed local lambda type,而不是C。由于C是从外部传入的,因此它不能是a本地的lambda类型。简而言之,除非您将C作为a的附加参数传递,否则a不会传递给{{1} }。

您显然希望b不是一个可以用某些B调用但可以用 any C调用的函数对象。您希望它是一个多态函数对象。 Rust不支持编译时多态函数对象(Haskell中的等效对象为C或类似的对象)。它仅支持运行时多态函数对象。

这就是forall a. a -> IO ()的工作。现在,您已经说过不能使用dyn,因为您要将函数对象传递给另一个线程。因此,请改用&dyn

Box<dyn>