Search code examples
dependency-injectionmoduleocamlcircular-dependency

Circular dependency control in OCaml


My problem is the following :

Module A called Map.ml

let lst = ref [Instance1_ModuleB; Instance2_ModuleB; ...];;
let is_coliding p = DoSomeWork_And_Return_A_Bool ;;
.... other things here.

Module B called Player.ml

Open Map
class player_object (x_in, y_in, name_in)=

object (self)

method jump () =
       if Map.is_colliding self then
             DoSomeThing ();;
....

Any clue how to make that works.

By the way, how do other programming languages handle that? I never care about such dependency in C#.


Solution

  • If your module A only need type from module B and no value, then you can create a moduleB.mli with the interface of module B, and compile it before moduleA:

    moduleA.ml:

    let foo (bar : ModuleB.bar) = bar.baaz
    

    moduleB.mli:

    class bar : object
      method baaz : int
      method buz : int
    end
    

    moduleB.ml

    class bar =
    object(s)
      method baaz = 3
      method buz = ModuleA.foo s
    end
    

    But if you have circular dependency on value or function it there is no simple solution, as for example for :

    moduleA.ml:

    let li = [new bar; new bar]
    
    let foo (bar : ModuleB.bar) = bar.baaz
    

    One can try to break such a circular dependency by using reference or mutable value in general:

    moduleA.ml:

    let li = [new bar; new bar]
    
    let foo (bar : ModuleB.bar) = bar.baaz
    let _ = ModuleB.initB foo
    

    moduleB.ml

    let foo = ref (fun x -> (failwith "not initialized" : int))
    
    class bar =
    object(s)
      method baaz = 3
      method buz = !foo s
    end
    
    let initB f = foo := f