OCaml 中的受保护方法

Lobsters Hottest 工具

摘要

本文解释了如何使用类型相等性证明在 OCaml 中编码受保护方法,从而仅对特定方法而非整个类施加接收者约束。

<p><a href="https://lobste.rs/s/ki0ge3/guarded_methods_ocaml">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/08/03 01:33

# OCaml 中的守卫方法 来源:https://xvw.lol/en/articles/oop-refl.html **守卫方法(Guarded methods)**允许你仅针对某些方法向接收者(`self`)附加**约束**,这意味着这些方法只有在接收者满足这些约束(即*守卫*)时才能被调用。 OCaml (https://ocaml.org/) 在语法层面并不允许*直接*定义这类方法。在本文中,我们将探讨如何利用**类型相等见证(type equality witness)**来对它们进行编码。 ## 问题描述 当一门语言(在程序运行前进行类型检查,如 Java 或 OCaml)引入**参数多态**(Java 的*泛型*)时,有时可以约束类型变量。例如: ``` class MyClass { ... } ``` 我们假设类型变量 `T` 是 `S` 的子类型,从而让 `MyClass` 变得可泛型。问题在于,这种约束应用于**整个类**。但有时我们希望约束只应用于**某些特定方法**。 例如,假设我们有一个描述列表的类 `MyList`: ``` class MyList extends ArrayList { public int length() { return this.size(); } } ``` 我们如何定义一个 `flatten` 方法,使得对于类似 `[[1, 2, 3], [4, 5]]` 的列表,能生成 `[1, 2, 3, 4, 5]`?如果将约束放在类级别,我们就会强制这个列表“*始终是列表的列表*”,这非常受限。要实现这样的方法,我们有三种理论上的途径。 ### 将方法移到类外部 第一种解决方案最明显:简单地“*作弊*”,把方法移到类体之外(例如,放入静态上下文或*伴生对象*中): ``` class MyList extends ArrayList { public static MyList flatten(MyList> list) { // flatten 的实现 } public int length() { return this.size(); } } ``` 这种方法有效,而且不需要任何特殊仪式。但它迫使开发者去跟踪哪些方法在类体中、哪些在静态上下文中。此外,它破坏了向实例发送消息的系统性方式(这常常被作为支持面向对象编程的关键论据之一)。 ### 扩展方法 Kotlin (https://kotlinlang.org/)(以及其他语言,如 C# (https://docs.microsoft.com/en-us/dotnet/csharp/))提供了扩展方法 (https://kotlinlang.org/docs/extensions.html)。这些扩展方法除了允许**扩展现有类**(这对于为 `String` 类(在 Java 中是 `final` 的)添加行为非常有用)之外,在定义*接收者*方面也提供了更大的灵活性。例如,我们可以用如下的方式(在 Kotlin 中)编写 `flatten`: ``` class MyList : ArrayList { ... } fun MyList>.flatten() = ... ``` 尽管这个方案看起来近乎完美,但它仍然要求方法在**类外部**定义,这可能意味着必须将类的某些成员设为*公有(public)*才能从扩展中访问(看起来存在潜在的*抽象泄漏*)。不过,它仍然**保留了系统性的消息发送方式,同时允许更细粒度地限定接收者**。 ###

相似文章

卫兵!卫兵

Lobsters Hottest

探讨 Elixir 中一个令人惊讶的行为:`is_map_key/2` 守卫可能导致守卫失败而非返回 false,从而破坏了布尔运算符的可交换性。

OxCaml 中其他语言应该借鉴的功能 - The Consensus

Lobsters Hottest

OxCaml 是 Jane Street 的 OCaml 超集,引入了一个 `[@zero_alloc]` 注解,强制编译器在调用树中任何函数在堆上分配内存时拒绝构建,将内存分配检测从运行时分析转变为编译时强制执行。

OxCaml 中的数据竞态自由

Lobsters Hottest

OxCaml 是 Jane Street 对 OCaml 编译器的分支,它引入了编译时对数据竞态的保证,从而在不增加运行时开销的情况下实现顺序一致性。这篇博文解释了新的模式轴及其对并行编程的影响。

类型推断(第一部分)

Lobsters Hottest

关于类型推断的教程,涵盖Damas-Hindley-Milner类型系统、合一及相关概念,并附有OCaml代码示例。