1 个不稳定版本
0.1.0 | 2020 年 12 月 3 日 |
---|
#1760 在 Rust 模式
44KB
850 行
Lifted
Lifted 是 Rust 的高阶类型。它基于对 Liebow-Feeser 方法的修改实现,最终达到与 Yallop & White 描述的相同方案。
快速入门
假设你想编写一个高阶特质,例如 Functor
。我们可以想象它可能有一天看起来有点像这样
trait Functor<A> {
fn fmap<B, F: Fn(A) -> B>(me: Self<A>, f: F) -> Self<B>;
}
这在今天是不合法的,但通过一些小的修改,我们可以这样编写它
use lifted::K1;
trait Functor {
fn fmap<A, B, F: Fn(A) -> B>(me: K1<Self, A>, f: F) -> K1<Self, B>;
}
有两个关键的变化,以及一个隐藏的变化
- 我们不是假设性地参数化我们的
Functor
特质,而是将类型参数移动到了方法本身 - 而不是假设的原生
Self<B>
,我们使用一个K1<Self, B>
包装结构体,并且 - 而不是假设性地为半成品类型(例如
Vec
)实现特质,我们为 HKT 形式VecC
实现。
(请注意,虽然“HKT 形式”一词是从 generic_std
借用的,但在这里的使用是独立发现的。进一步审查后,这个概念与 Yallop & White 中的“brand”概念非常相似。)
前两个大致可以自解释,但第三个可能需要插图来澄清。让我们来实现它!
use lifted::Kind1;
// Define the higher-kinded form of `Vec`
pub struct VecC;
// Specify how to construct a type instance
impl<T> Kind1<T> for VecC {
type Inner = Vec<T>;
}
impl Functor for VecC {
fn fmap<A, B, F: Fn(A) -> B>(me: K1<Self, A>, f: F) -> K1<Self, B> {
let me = me.into_inner(); // unwrap the Vec<A>
let you = me.map(f); // map the Vec<A> to a Vec<B>
K1::new(you) // rewrap the Vec<B>
}
}
有关更多详细信息,请参阅 API 文档。
文档
API 文档
API 文档托管在 docs.rs 上
最低支持的 Rust 版本
该 crate 没有使用任何异国情调的语言功能,因此可以支持甚至非常旧的稳定 Rust 版本。它已经与 Rust 1.35 成功测试。 (一旦我们开始设置 CI,我们将通过 CI 测试验证此 MSRV)。
与其他 crate 的比较
- crate:
generic_std
- 目的: 为
std
类型提供通用特质 - 实现: 修改 Smith 的方法,从 HKT 形式构造类型实例
- 维护: 一个实验性版本
- 注意: 也考虑了生命周期种类!
- 注意: 没有处理具体的实例
- 目的: 为
- crate:
fp-core
- 目的:Rust 中函数式编程的库
- 实现:使用
HKT
特征从另一个实例构建类型实例,宏来实施 - 维护:过去一年内没有变化
- 包:[rats](https://github.com/daviswahl/rats)
- 目的:Rust 的一个实验性类型级函数式编程库
- 实现:一个神级枚举、特性和一些奇怪的探戈中的类型品牌
- 维护:过去两年内没有变化
- 包:
higher
- 目的:以最小的样板代码实现伪高阶类型
- 实现:
Lift
特征从另一个实例构建类型实例,派生宏来实施 - 维护:过去一年内有一个变化
- 包:
kinder
- 目的:代数结构和高级类型仿真
- 实现:
Higher
特征从另一个实例构建类型实例,宏来实施 - 维护:过去四年内没有变化
- 包:
archery
- 目的:抽象引用计数指针的原子性
- 实现:也基于 Liebow-Feeser
- 维护:活跃
贡献
我很高兴看到任何和所有的贡献,包括错误报告、可用性建议、补丁或愤怒但好意的批评。鼓励您向官方的 问题跟踪器 报告问题,并将任何问题或补丁发送到 邮件列表。GitHub 镜像的拉取请求也是可接受的。