【发布时间】:2017-06-18 10:49:46
【问题描述】:
我找到了自己对my own question 的回答,如下所示
trait Mu<T> {
fn unroll(&self, &Mu<T>) -> T;
}
impl<T, F:Fn(&Mu<T>) -> T> Mu<T> for F {
fn unroll(&self, o:&Mu<T>) -> T { self(o) }
}
fn y<T, F:Fn(T) -> T>(f:&F) -> T {
(&|w:&Mu<T>| { w.unroll(w) }).unroll(&|w:&Mu<T>| { f(w.unroll(w)) })
}
它编译并完全回答了问题。但为了让它更漂亮,我为Mu<T> 实现了Fn 特征,如下所示:
impl<'a, T> Fn<&'a Mu<T>> for &'a Mu<T> {
extern "rust-call" fn call(&self, o: &'a Mu<T>) -> T {
self.unroll(o)
}
}
impl<'a, T> FnMut<&'a Mu<T>> for &'a Mu<T> {
extern "rust-call" fn call_mut(&mut self, o: &'a Mu<T>) -> T {
self.unroll(o)
}
}
impl<'a, T> FnOnce<&'a Mu<T>> for &'a Mu<T> {
type Output = T;
extern "rust-call" fn call_once(self, o: &'a Mu<T>) -> T {
self.unroll(o)
}
}
有特色
#![feature(fn_traits)]
#![feature(unboxed_closures)]
我想把 y 组合器写成
fn y1<T, F:Fn(T) -> T>(f:&F) -> T {
(&|w:&Mu<T>| { w(w) })(&|w:&Mu<T>| { f(w(w)) })
}
但这不会编译。错误信息:
rustc 1.19.0-nightly (78d8416ca 2017-06-17)
error[E0618]: expected function, found `&Mu<T>`
--> <anon>:36:20
|
36 | (&|w:&Mu<T>| { w(w) })(&|w:&Mu<T>| { f(w(w)) })
| ^^^^
|
note: defined here
--> <anon>:36:8
|
36 | (&|w:&Mu<T>| { w(w) })(&|w:&Mu<T>| { f(w(w)) })
| ^
error[E0618]: expected function, found `&Mu<T>`
--> <anon>:36:44
|
36 | (&|w:&Mu<T>| { w(w) })(&|w:&Mu<T>| { f(w(w)) })
| ^^^^
|
note: defined here
--> <anon>:36:30
|
36 | (&|w:&Mu<T>| { w(w) })(&|w:&Mu<T>| { f(w(w)) })
| ^
为什么 Rust 无法找出给定的 Fn 实现?有什么办法可以改善吗?
进一步的尝试表明它与这些功能无关,甚至与闭包有关。即使答案中显示的示例 Shepmaster 也不是最小的。一个最小的示例如下所示:
trait T1 {}
trait T2 {}
impl<'a> T1 for &'a T2 {}
struct S {}
impl T2 for S {}
fn main() {
let t2: &T2 = &S {};
let t1: &T1 = &t2; //This is OK
let t3: &T1 = t2; //E0308: Expecting `T1`, found `T2`
}
问题是我们试图为 trait 对象引用实现一个 trait,然后我们需要在将 trait 对象转换为目标 trait 的 trait 对象时添加额外的引用。
【问题讨论】:
-
请查看minimal reproducible example 是什么,为什么它很重要,以及如何创建一个。例如,您的整个示例可以是boiled down to this。
-
虽然不是最小的,但是我的例子是完整且可验证的。之所以不小,是因为我昨天在睡前想出了这个可靠的例子,不想睡前的时间太长,但还是想让别人看到。