【问题标题】:Higher order functions supporting possible lifetimes支持可能生命周期的高阶函数
【发布时间】:2023-04-06 20:27:01
【问题描述】:

假设我有一个高阶函数,比如composition from this answer

fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
    F: Fn(A) -> B,
    G: Fn(B) -> C,
{
    move |x| g(f(x))
}

我想部分应用它,如

fn id<T>(x: &T) -> &T { x }

fn compose_with_id<T, U, F>(f: F) -> impl Fn(&T) -> U
where
    F: Fn(&T) -> U
{
    compose(id, f)
}

这不会编译。 IIUC 的问题是,在compose 调用站点,我们必须用特定类型替换A(包括特定生命周期),但返回值需要为所有'a 实现Fn(&amp;'a T) -&gt; U。我尝试将对compose 的调用移动到闭包中:

fn compose_with_id<T, U, F>(f: F) -> impl Fn(&T) -> U
where
    F: Fn(&T) -> U
{
    move |t| compose(id, f)(t)
}

这也无法编译。现在的问题是compose 试图在每次调用结果函数时获取f 的所有权。我没有办法修复compose_with_id(不坚持F: Copy); compose 拥有f 的所有权,这只能发生一次,所以我们必须选择一个生命周期,但返回值需要处理任何生命周期。

我们可以创建一个compose 的变体,用于引用:

fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(&A) -> C
where
    F: Fn(&A) -> &B,
    G: Fn(&B) -> C,
{
    move |x| g(f(x))
}

(其返回值具有 HRTB)但不能用于非参考输入。

如何定义compose,使其可以部分应用于带有或不带有参考输入的不可复制函数?

【问题讨论】:

    标签: rust


    【解决方案1】:

    给 compose_with_id 添加生命周期注解怎么样?

    fn compose_with_id<'a, T, U, F>(f: F) -> impl Fn(&'a T) -> U
    where
        T: 'a,
        U: 'a,
        F: Fn(&'a T) -> U,
    {
        compose(id, f)
    }
    

    【讨论】:

    • 这使得 compose_with_ids 的返回类型更窄(即Fn(&amp;'a T) -&gt; U 用于某些特定的'a,而不是for&lt;'a&gt; Fn(&amp;'a T) -&gt; U),但也许这是我们能做的最好的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    • 2021-06-21
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多