是否可以将功能添加到OCaml中已经存在的模块中?
具体地说,我有一些模块Loc
跟踪源文件中的位置。我还有一个名为Ast
的模块,它代表某些代码的抽象语法树。我想在Loc.of_ast
中定义方法ast.ml
,从而扩展Loc
。有什么办法吗?
注意:这可能是XY问题。我倾向于认为可以进行此类模块扩展的原因是,在电池中,存在诸如String.of_int
和Int.of_string
之类的方法,这意味着这些模块是相互递归的。当然,它们并没有完全在同一个文件中定义...
答案 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的数据表示形式中使用时。