有什么方法可以创建特定 FnMut 的别名吗?

Is there any way to create an alias of a specific FnMut?

我想和FnMut(&[f32]) -> f32一起工作, 为了不 copy/paste 完整签名,我想引入某种别名,但是

type Boo = FnMut(&[f32]) -> f32;

fn f<F: Boo>(mut f: F) {}

导致编译器错误:

error[E0404]: expected trait, found type alias `Boo`
 --> src/main.rs:3:13
  |
3 |     fn f<F: Boo>(mut f: F) {}
  |             ^^^ type aliases cannot be used for traits

然后我尝试了:

trait Boo: FnMut(&[f32]) -> f32 {}

fn f<F: Boo>(mut f: F) {}

它编译了,但是如果我尝试在另一个地方使用 Boo 代替特征:

trait Boo: FnMut(&[f32]) -> f32 {}

struct X(Vec<Box<Boo>>);

我得到:

error[E0191]: the value of the associated type `Output` (from the trait `std::ops::FnOnce`) must be specified
 --> src/main.rs:3:18
  |
3 | struct X(Vec<Box<Boo>>);
  |                  ^^^ missing associated type `Output` value

有什么方法可以创建我可以使用的特定 FnMut 的别名 而不是 FnMut(&[f32]) -> f32?

特征别名目前不是语言的一部分。但是,恰好有一个 accepted RFC。很难准确预测何时实施,但接受 RFC 代表承诺在未来某个时间实施它。

您的错误原因是您的 Boo 特征是 FnMut 的子类型,并且任何实现还必须提供所需的关联类型 Output。但是编译器仍然不知道会提供哪个实现,所以你需要告诉它 Output 的类型是什么:

struct X(Vec<Box<Boo<Output = f32>>>);

这有点笨拙,我觉得这是一个需要改进的地方。直觉上,似乎 Output 可以从 -> f32 推断出来,但我这里可能是错的。

即使修复了该错误,Boo 严格来说是 FnMut(&[f32]) 的子类型,因此您不能只提供任何需要 Boo 的闭包。该闭包还必须实现您的特征。您可以将此作为所有 FnMut(&[f32]) -> f32 的一揽子实施,如下所示:

impl <F> Boo for F where F: FnMut(&[f32]) -> f32 {}

现在任何 Boo 都是 FnMut(&[f32]) -> f32(通过子类型),任何 FnMut(&[f32]) -> f32 都是 Boo(通过一揽子实施)。