Enrico Borba
Enrico Borba

Reputation: 2127

Extending OCaml Module

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

Answers (2)

ivg
ivg

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

Richard-Degenne
Richard-Degenne

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

Related Questions