扩展OCaml模块

4
有没有办法在OCaml中向已有的模块添加功能?
具体来说,我有一些跟踪源文件位置的模块“Loc”。我还有一个名为“Ast”的模块,它表示一些代码的抽象语法树。我想在“ast.ml”中定义方法“Loc.of_ast”,从而扩展“Loc”。有没有办法做到这一点?
注意:这可能是一个XY问题。我倾向于相信这样的模块扩展是可能的,因为在Batteries中,有类似“String.of_int”和“Int.of_string”等方法,这意味着这些模块是互相递归的。当然他们不会全部在同一个文件中完全定义...

你为什么想要在 ast.ml 中定义 Loc.of_ast - glennsl
2
String.of_intInt.of_string 可以在不相互递归的情况下定义在单独的模块中,只要这些类型没有在这些模块中定义。它们并没有被定义在那些模块中。stringint 是原语,我相信它们是由编译器定义的。 - glennsl
你可能会对阅读这个讨论感兴趣 https://discuss.ocaml.org/t/modules-that-extend-modules-from-third-party-packages/3777/2 - ivg
2个回答

4
你可以创建一个名字与已有模块相同的新模块,并将现有模块的所有函数include进入你的新模块。新模块遮盖了现有模块,你可以使用你最新定义的所有函数。
顺便说一下,这就是Batteries是如何实现的。请参见:此处
module List = struct
  include List

  let empty = []
end;;

List.empty;;
(* - : 'a list = [] *)

1
我最终决定不这样做。但我认为这是最好的答案。谢谢! - Enrico Borba

3
有没有办法在OCaml中向已经存在的模块添加函数? 没有,模块是不可扩展的实体(与对象不同)。
具体来说,我有一个名为Loc的模块,用于跟踪源文件中的位置。我还有一个名为Ast的模块,表示一些代码的抽象语法树。我想在ast.ml中定义Loc.of_ast方法,从而扩展Loc。有没有办法做到这一点? 传统的方法是将此函数添加到Ast模块中,例如,Ast.to_loc将从树中提取位置。如果您不希望Ast模块依赖于Loc,则只需将其放在单独的模块Ast_support中,您可以在其中引入额外的依赖项(尽管看起来您的Ast模块已经使用Loc模块)。 您将of_ast函数放入Loc模块中的意图可能受到一些OOP背景的影响,在该背景下,数据结构上的操作通常被实现为成员函数或方法。然而,即使在面向对象的语言(如C++)中,始终存在使用更多的抽象违规成员函数与仅是独立函数之间的难题,后者通常更受欢迎。其他语言,除了类没有其他结构(例如Java),你通常会遇到膨胀的接口。没有必要将这些糟糕的习惯带到OCaml中: )而且,OCaml被设计成抵制坏做法并鼓励好做法。在我们的案例中,Loc.of_ast绝不是位置接口的一部分。它也不需要访问定义(我希望是正确抽象化)在Loc模块中的数据结构的内部实现。如果它在Ast的数据表示中使用,则可能属于Ast模块。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接