重用和扩展 Ocaml 中定义的类型

发布于 2024-11-26 20:35:48 字数 221 浏览 1 评论 0原文

在 Ocaml 中,是否有一个简单的构造/样式来扩展定义的类型?

假设我们有布尔类型,

bool2 = True | False 

现在我们想将其扩展为三值逻辑。在 Ocaml 中,有没有比像这样重新定义 bool2 更优雅的:

bool3 = True | False | ThirdOne

In Ocaml, is there a simple construct/style to extend a defined type?

Say, if we have the boolean type

bool2 = True | False 

Now we want to extend it for 3-valued logic. In Ocaml, is there more elegant one than redefining bool2 like this:

bool3 = True | False | ThirdOne

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

放我走吧 2024-12-03 20:35:48

多态变体提供了这个功能:

type bool2 = [ `True | `False ]
type bool3 = [ bool2 | `Third_one ]

就是这样。

多态变体还有另一个有用的快捷方式。在模式匹配中,使用以 # 开头的类型名称:

let is_bool2 = function
    #bool2 -> true
  | `Third_one -> false

应谨慎使用多态变体,因为它们很容易导致混乱的错误消息。如果原始类型 bool2 无论如何都不是多态变体,则两种类型的并集将按如下方式实现。假设bool2是核心类型bool,我们使用经典变体的定义是:

type bool3 = Bool of bool | Third_one

在模式匹配中,编译器将检查是否覆盖了所有情况,而不需要类型注释。它看起来像这样:

match x with
| Bool true -> ...
| Bool false -> ...
| Third_one -> ...

Polymorphic variants provide this functionality:

type bool2 = [ `True | `False ]
type bool3 = [ bool2 | `Third_one ]

That's it.

There is another useful shortcut for polymorphic variants. In pattern-matching, use the type name preceded by #:

let is_bool2 = function
    #bool2 -> true
  | `Third_one -> false

Polymorphic variants should be used with caution as they can easily lead to confusing error messages. If the original type bool2 is not a polymorphic variant anyway, the union of two types is achieved as follows. Let's assume bool2 is the core type bool, our definition using classic variants is:

type bool3 = Bool of bool | Third_one

In pattern-matching, the compiler will check that all cases are covered, without requiring type annotations. It looks like this:

match x with
| Bool true -> ...
| Bool false -> ...
| Third_one -> ...
夏雨凉 2024-12-03 20:35:48

我建议不要过度使用多态变体。它们在纸面上看起来不错,但更灵活的推理和子类型随时都会给你带来麻烦。当我使用多态变体时,我尝试确保每次使用都用精确的约束类型表达式进行注释。

我建议返回并修改您的旧代码,因为这似乎很自然。如果您在编写代码时考虑到了可扩展性,特别是避免了 bool2 类型上的 _ 模式,那么编译器会警告您任何地方假设仅创建了两个构造函数。编译器对类型修改的反馈非常有用,因为它是使程序正确的机械帮助。

这种做事方式当然有一些缺点。其中之一是修改类型定义,然后修改每个用例可能无法很好地适应您通常的编译测试实践:如果您在大型代码库上执行此操作,则在项目编译之前您将需要做大量的事情再次干净(因此可以进行测试)。您可以将修改拆分为版本控制系统的多个补丁,但这意味着某些中间提交状态不会编译,这不太令人愉快。另一种可能性是更改这些位置仅添加运行时故障(| Third_one -> assert false),然后您就有可编译的代码,并且可以在运行时纠正这些故障 -应用程序测试期间的时间。但我仍然认为静态编译器反馈对于代码维护来说是一个很好的帮助。

还可以选择将代数数据类型包装在“扩展代数数据类型”中 type bool3 = New |旧的 bo​​ol2 ,在您作为马丁答案的评论给出的链接中进行了讨论。这可能是在不破坏编译的情况下从一种数据类型转换到另一种数据类型的好方法,但从长远来看,这是痛苦的,特别是当您将更多的扩展堆叠在一起时。

当然,在某些情况下真正需要的是一种通过添加代码而不是修改代码来扩展数据类型的方法,这种方法既静态安全,又易于编译、运行和测试,并且运行高效。时间。这是表达式问题的一个实例,它们是各种解决方案,多态变体是其中之一他们。但在常见情况下,您不需要仅添加代码的额外灵活性,并且不值得相关语言功能的额外复杂性,因此我建议坚持使用普通的旧变体类型,除非它明显是一个巨大的获得做不同的事情。

PS:关于多态性变体及其与表达问题的关系,强制性论文是 通过多态变体进行代码重用,作者:Jacques Garrigue。

I would advise against the immoderate use of polymorphic variants. They look nice on paper, but the more flexible inference and subtyping will come to bite you back at any time. When I use polymorphic variants, I try to make sure that every use is annotated with a precise constraining type expression.

I would suggest going back and modifying your old code, as it seems natural to do. If you have written your code with extensibility in mind, and in particular avoided _-patterns on the bool2 type, then the compiler will warn you of any place where the assumption that there are only two constructors is made. This compiler feedback on type modification is very useful, as it is a mechanical help to make your program correct.

This way of doing things has of course some drawbacks. One of them is that modifying the type definition, then modifying each use case may not work well with your usual compile-test practice: if you do that on a large code base, you will have important amount of things to do before your project compiles cleanly again (and thus can be tested). You may split your modification in several patches to your version control system, but that means some intermediary committed states do no compile, which is not very pleasing. The other possibility is to change those place only to add a run-time failure (| Third_one -> assert false), then you have compilable code and you can correct those failures as they happen at run-time during the testing of the application. But I still think the static compiler feedback is a good help for code maintenance.

There is also the option of wrapping the algebraic datatype in an "extended algebraic datatype" type bool3 = New | Old of bool2, which is discussed in the link you give as a comment of Martin answer. This may be a good way to transition from one datatype to the other without breaking compilation, but on the long term it is painful, especially if you stack more of those extensions on top of each other.

Of course, what would be really needed in some situations would be a way to extend the datatype by code addition, instead of code modification, in a way that is both statically safe, easier to compile, run and test, and efficient at run-time. This is an instance of the Expression Problem, of which they are various solutions, polymorphic variants being one of them. But in the common case, you don't need the additional flexibility of doing code addition only, and it's not worth the additional complexity of the concerned language features, so I would advise to stick with plain old variant types unless it is demonstrably a huge gain to do differently.

PS: regarding polymorphic variants, and their relation to the expression problem, the obligatory paper is Code reuse through polymorphic variants by Jacques Garrigue.

冷了相思 2024-12-03 20:35:48

根据手头的任务,您还可以找到可扩展变体类型有用。更多信息和使用案例请参见此处

type bool = ..
type bool +=
    | True
    | False

(* Elsewhere *)
type bool +=
    | Third_one

Depending on the task at hand, you may also find Extensible Variant Types useful. More information and use cases here.

type bool = ..
type bool +=
    | True
    | False

(* Elsewhere *)
type bool +=
    | Third_one
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文