我正在学习面向程序员的类别理论,其中一个挑战是实现一个Functor接口.

This个问题提供了以下解决方案:

pub trait Functor<A> {
    type With<B>: Functor<B>;
    fn map<B>(self, f: impl Fn(A) -> B) -> Self::With<B>;
}

然而,这将允许With是实现函子的任何类型.我真正想要的是这样的:

pub trait Functor<A> {
    fn map<B>(self, f: impl Fn(A) -> B) -> Self<B>;
}

但是Self不接受类型参数.我该怎么办?

推荐答案

就像计算机科学中的另一个问题一样,通过添加一个间接级别.也就是说,您可以定义family个相关类型,然后使用它来强制执行适当的约束.

一个家庭,说到底,是相当微不足道的:

trait Family {
    type Member<T>;
}

trait FamilyMember<T> {
    type Of: Family<Member<T> = Self>;
}

struct VecFamily;

impl Family for VecFamily {
    type Member<T> = Vec<T>;
}

impl<T> FamilyMember<T> for Vec<T> {
    type Of = VecFamily;
}

然后,您可以通过函数来利用这一点:

trait Functor<A>: FamilyMember<A> {
    fn map<B>(self, f: impl FnMut(A) -> B) -> <Self::Of as Family>::Member<B>;
}

impl<A> Functor<A> for Vec<A> {
    fn map<B>(self, f: impl FnMut(A) -> B) -> Vec<B> {
        self.into_iter().map(f).collect()
    }
}

有点口齿不清...但是it does compile on stable

Rust相关问答推荐

trait 中self 的显式生命周期似乎导致E0499无法在循环中多次borrow * emits 器作为可变的

如何处理动态 struct 实例化?

何时可以在Rust中退出异步操作?

在自定义序列化程序中复制serde(With)的行为

在我的Cargo 中,当我在建筑物中使用时,找不到我可以在产品包中使用的 crate .r我如何解决这个问题?

为什么`AlternateScreen`在读取输入键时需要按Enter键?

如何返回 struct 体中向量的切片

在 Rust 中,在第一个空格上分割字符串一次

如何在 Rust 中将函数项变成函数指针

我可以禁用发布模式的开发依赖功能吗?

为什么需要同时为值和引用实现`From`?方法不应该自动解引用或borrow 吗?(2023-06-16)

Rust 打包在 .deb 中

如何从 rust 中的同一父目录导入文件

具有在宏扩展中指定的生命周期的枚举变体数据类型

Rust 中 `Option` 的内存开销不是常量

你能告诉我如何在 Rust 中使用定时器吗?

在单独的线程上运行 actix web 服务器

当用作函数参数时,不强制执行与绑定的关联类型

BigUint 二进制补码

如何迭代调用可能会失败的函数?操作员?