扩展OCaml模块

时间:2019-06-30 23:04:46

标签: module ocaml

是否可以将功能添加到OCaml中已经存在的模块中?

具体地说,我有一些模块Loc跟踪源文件中的位置。我还有一个名为Ast的模块,它代表某些代码的抽象语法树。我想在Loc.of_ast中定义方法ast.ml,从而扩展Loc。有什么办法吗?

注意:这可能是XY问题。我倾向于认为可以进行此类模块扩展的原因是,在电池中,存在诸如String.of_intInt.of_string之类的方法,这意味着这些模块是相互递归的。当然,它们并没有完全在同一个文件中定义...

2 个答案:

答案 0 :(得分:3)

您可以做的是创建一个称为现有模块的新模块,并将现有模块的所有功能include添加到新模块中。新模块遮盖了现有模块,您可以使用所有新定义的功能。

顺便说一下,这是how Batteries does it

module List = struct
  include List

  let empty = []
end;;

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

答案 1 :(得分:3)

  

是否可以将功能添加到OCaml中已经存在的模块中?

不。模块是密封的,不是可扩展的实体(与对象不同)。

  

具体来说,我有一些模块Loc跟踪源文件中的位置。我还有一个名为Ast的模块,它代表某些代码的抽象语法树。我想在ast.ml中定义方法Loc.of_ast,因此是Loc的扩展。有什么办法吗?

常规方法是将此功能添加到Ast模块中,例如Ast.to_loc,它将从树中提取位置。如果您不希望您的Ast模块依赖于Loc,则只需将其放在一个单独的模块中,例如Ast_support,您可以在不害怕的代码中使用它引入额外的依赖关系(尽管您的Ast模块似乎已经在使用Loc模块)。

您将of_ast函数放入Loc模块的意图可能受到某些OOP背景的影响,在OOP背景中,对数据结构的操作通常以成员函数或方法的形式实现。但是,即使在诸如C ++之类的OOP语言中,在使用更多抽象违反成员函数与仅使用独立函数之间总是存在困惑,后者通常是首选。其他语言,除了类(例如Java)以外,不提供任何结构化功能,而这些语言通常会以膨胀的界面结尾。绝对没有必要将这些不良习惯带入OCaml :)此外,OCaml的设计方式还可以抵制不良行为并鼓励良好行为。在我们的情况下,Loc.of_ast绝不是位置界面的一部分。两者都不需要访问在Loc模块中定义(并且希望适当抽象)的数据结构的内部实现。它可能属于Ast模块,尤其是在Ast的数据表示形式中使用时。