Reputation: 2127
Is there any way to add functions to an already existing module in OCaml?
Specifically, I have some module Loc
that tracks locations in a source file. I also have a module called Ast
that represents the abstract syntax tree of some code. I want to have the method Loc.of_ast
defined in ast.ml
, and thus an extension of Loc
. Is there any way to do this?
Note: This might be an XY problem. The reason that I'm inclined to believe that such module extensions are possible is because, in Batteries, there are methods such as String.of_int
and Int.of_string
, which implies these modules are mutually recursive. Surely they aren't all entirely defined in the same file...
Upvotes: 4
Views: 1389
Reputation: 35210
Is there any way to add functions to an already existing module in OCaml?
No. Modules are sealed and not extensible entities (unlike objects).
Specifically, I have some module Loc that tracks locations in a source file. I also have a module called Ast that represents the abstract syntax tree of some code. I want to have the method Loc.of_ast defined in ast.ml, and thus an extension of Loc. Is there any way to do this?
The conventional way would be to add this function to the Ast
module, e.g., Ast.to_loc
which will extract the location from a tree. If you don't want your Ast
module to depend on Loc
then just put it in a separate module, e.g., Ast_support
which you can use in the code in which you do not afraid to introduce an extra dependency (though it looks like that your Ast
module is already using the Loc
module).
Your intention to put the of_ast
function into the Loc
module is probably influenced by some OOP background, where the operations on the data structure are usually implemented as member-functions or methods. However, even in OOP languages, such as C++ there is always a dillema between using a more abstraction breaching member-functions vs. just a stand alone function, with the latter being usually preferred. Other languages, which doesn't provide any structuring beyond classes (e.g., Java) you usually end up in bloated interfaces. There is absolutely no need to bring these bad habits to OCaml :) Moreover, OCaml is designed in a such way that it will resist bad practices and encourage good ones. In our case, the Loc.of_ast
is by no means a part of the location interface. Neither it needs access to internal implementation of the datastructures defined (and I hope properly abstracted) in the Loc
module. It might belong to the Ast module, especially if it is used in the data representation of your Ast.
Upvotes: 3
Reputation: 2949
What you can do is creating a new module called like an existing module, and include
all the functions of the existing module into your new one. The new module shadows the existing one, and you can use all of your newly-defined functions.
This is how Batteries does it, by the way.
module List = struct
include List
let empty = []
end;;
List.empty;;
(* - : 'a list = [] *)
Upvotes: 5