Похоже, вы смешиваете несколько понятий здесь.Прежде всего, вы должны понимать разницу между ними:
fn(A) -> B
impl Fn(A) -> B
или T: Fn(A) -> B
&dyn Fn(A) -> B
Box<dyn Fn(A) -> B>
Число 1 - это тип указателя на функцию, как в C.
Число 2 - это обобщенный тип, который реализует функцию trait Fn
, то есть тип callable .
Number 3 - это динамическая ссылка на вызываемый объект (ключевое слово dyn
является необязательным).
Число 4 - это объект черты , то есть вызываемый в штучной упаковке объект со стертым реальным типом.
Теперь посмотрите на определение tool::fix
:
pub fn fix<A, B, F>(f: F) -> impl Fn(A) -> B
where
F: Fn(&Fn(A) -> B, A) -> B,
Из этого видно, что fix
использует номер 2 для параметра f
, но номер 3 для параметра A
f
.Кроме того, он возвращает число 2.
Сложность в том, что f
- это функция, которая принимает функцию в качестве аргумента.Сам по себе f
может быть любого типа, который реализует Fn
, но первый аргумент этой функции должен иметь вид &dyn Fn
.
Ваша первоначальная ошибка возникает из-за попытки пометить &dyn Fn(A) -> B
, но вы не можете сделать это в общем, потому что такое значение может содержать ссылки, а для Box
требуется тип 'static
.
Но, учитывая все это, вы можете тщательно написать свою функцию, не используя Box
Таким образом, ваша проблема просто исчезает, и результат лучше ( детская площадка ):
fn main() {
fn wrap (wrap_fn: impl Fn(&dyn Fn(u64) -> u64, u64) -> u64) -> impl Fn(u64) -> u64 {
let a = RefCell::new(false);
let fib = fix(move |f, x| {
*a.borrow_mut() = true;
if x == 0 || x == 1 {
x
} else {
// `f` is `fib`
wrap_fn(f, x - 1) + wrap_fn(f, x - 2)
}
});
fib
}
fn b (c: &dyn Fn(u64) -> u64, n: u64) -> u64 {
c(n)
}
println!("{}", (wrap(b))(10));
}