I would like to design 2 modules A and B which both have their own functions, for instance: A.compare: A.t -> A.t -> bool, B.compare: B.t -> B.t -> bool. The elements of A and B are convertible. So I would also need functions a_of_b : B.t -> A.t and b_of_a : A.t -> B.t. My question is where I should define these functions? inside the structure of A or the one of B or somewhere else?
Could anyone help?
Edit1: just amended some errors based on the first comment
This is a classic design problem. In OOP languages, it is hard to resolve this elegantly because a class encapsulates both a type definition and methods related to that type. Thus, as soon as you have a function such as a_of_b, which regards two types to an equal extent, there is no clear place for it.
OCaml correctly provides distinct language mechanisms for these distinct needs: type definitions are introduced with the keyword
type, and related methods are collected together in amodule. This gives you greater flexibility in designing your API, but does not solve the problem automatically.One possibility is to define modules A and B, both with their respective types and compare functions. Then, the question remaining is where to put
a_of_bandb_of_a. You could arbitrarily give preference to module A, and define the functionsA.to_bandA.of_b. This is what the Standard Library did when it putto_listandof_listin Array. This lacks symmetry; there is no reason not to have put these functions in B instead.Instead you could standardize on using
of_functions vsto_functions. Let’s say you preferto_. Then you would define the functionsA.to_bandB.to_a. The problem now is modules A and B are mutually dependent, which is only possible if you define them in the same file.If you will have lots of functions that deal with values of type
A.tandB.t, then it may be worth defining a module AB, and putting all these functions in there. If you will only need two, then an extra module is perhaps overkill.On the other hand, if the total number of functions regarding A’s and B’s is small, you could create only the module AB, with
type a,type b, and all related methods. However, this does not follow the OCaml community’s convention of naming a typetwithin its own module, and it will be harder to apply the Set and Map functors to these types.