In the current OCaml implementation, the compilation unit dependency graph must be acyclic. Simply put, compilation units (i.e. different files) cannot mutually recursively refer to each other.
This restriction is an excessive approximation, since it prohibits valid programs, and this contradicts intuition, since it is possible to write recursive modules into a single compilation unit. The reason for this limitation is the complexity of checking the type of a recursive module. A recursive module cannot be checked by type as a standalone object, since it requires the entire set of modules involved in recursion. But a separate OCaml compilation system requires each compilation unit to be autonomous and printable. If OCaml did not use a separate compilation (and linked the program as a whole), then it would be possible to implement recursive units.
A partial solution will be to identify portions of the interface that are independent of mutual recursiveness and implement them in a separate module (s). For example, you can define your types as follows:
type 'ba = A of int | B of 'b type 'ac = C of float | C of 'a type t1 = t2 a and t2 = t1 c
Now you can define the acyclic part of the interface for 'ba
. This interface should be common with respect to a variable of type 'b
(in other words, it should not touch it). It is difficult to imagine such an interface in our example, but assuming that this example is synthetic, but for product types this method will make sense (see type 'ba = {a : int; b : 'b
} - you can implement everything functions related to a
).
As a final note, I would like to say that recursive modules are rarely needed in practice and usually mean a design problem. Especially when it is necessary to move the definitions into separate modules - this indicates that the abstractions were not selected properly. Of course, it may be that the main problem is inherently complex, but in real life it is very rare.
source share