Open OCaml module within class

212 views Asked by At

I have a Map module that I want to be in scope within a class. How do I open that module within the entire class?

This was my guess, but it was wrong:

module My_map = struct
    module Map = ...
end

class my_object =
    object
        open My_map.Map

        method ...
    end

But this isn't working. Is there a way to open the module at the class level and not within each method?

Specifically, the issue that I'm having is this:

module Data = My_map.Map.Make(String)

However, when I try to access functions (within the class) that I added to My_map.Map.Make, I get compiler errors saying they don't exist.

2

There are 2 answers

1
Jeffrey Scofield On

I looked through the OCaml grammar just now and I don't see a place to open a module for a class definition as a whole.

You can say something like

class c =
    let x = 4 in
    object method m = x end

So it might make sense to be able to say:

class c =
    let open My_map.Map in
    object method m = ... end

However the grammar doesn't allow it.

You can open the module globally, or maybe give it a short synonym that's less onerous to type in your class definition.

module M = My_map.Map

Update

Rereading your question, I can't shake the feeling that you think you need to open a module in order to use its symbols. This isn't true, opening a module is just for convenience. Any symbol that could be accessed by opening a module can also be accessed without opening the module, by using a full module path. In fact many (including myself) would tell you to avoid opening modules in all but a very few cases.

If you're just having trouble specifying the right module path, it would help a lot if you could give self-contained (smallish) code that demonstrates the problem.

0
Théo Winterhalter On

I don't think you can open your module in the class definition. However, you can "open" it in a function:

module My_map = struct
  module Map = (struct
    type t = int

    let f () : t = 3

  end)
end

class my_object =
  object
      method stuff = My_map.Map.(
        let x = f () in
        x + f ()
      ) 
  end

This way, you see you can use f twice without having to write My_map.Map twice.


Regarding the second part of the issue, as pointed out by Jeffrey Scofield, I'm not sure it is really related to opening a module. Or perhaps would you have wanted (in my example), f to become a method of my_object?

I also don't think it's possible, and I don't see any reason it should. Perhaps, what you want is inheritance?