Guidance on .mli files

It’s clear that I should use an interface file when I wish to hide some aspect of my implementation but are there good reasons to do so otherwise?

In particular, it seems non-nonsensical to include an mli file for an implementation file which just includes a module signature.

Will omitting mli files impact compile times?

Thanks,

Michael

Can you provide a concrete example? With your description I’m not totally sure what scenario you’re thinking of.

If your module doesn’t need any changes from the compiler-inferred interface, and it doesn’t (currently) need documentation, there is really no point.

On rare occasions I might start with an mli, when I know the signature I need to match. But most often the mli is something I leave until a module has matured enough that it isn’t undergoing changes and might benefit from documentation. Some modules never get an mli because it would be purely redundant.

2 Likes

There are three situations I’m thinking of:

  1. You have defined some type in your implementation file but wish to keep it’s implementation abstract. Here you would use an .mli file to hide the implementation.

  2. Your .ml file just contains a module signature; you see this throughout Jane Street’s base and they don’t include an .mli for these ‘[X]_intf.ml’ files

  3. You have an implementation file but it’s interface would be exactly that determined by module type of .... The particular example I’m thinking of is here.

In case number three, is there any advantage to explicitly having the signatures of the modules you are exporting from a libraries top-level file?

  1. This makes sense
  2. This makes sense
  3. In this scenario, whether to provide an .mli or not should be discretionary, but in general module type of should be avoided as it could change the publicly exposed interface in a backward-incompatible way. The argument is the same as avoiding select * in SQL queries.

Specifically, I see that Common.ml here is just an ‘index module’, i.e. a module which just aliases the other modules in its directory. As far as I know, dune does that for you automatically. So the module is actually redundant here.

Could you say more about this? I feel uncomfortable using it but I haven’t got a compelling example with which I could explain to others why I do so.

That’s helpful, I didn’t realize Dune would do this. (In this case we aren’t exposing all of the other modules, NonEmptyList.ml is not currently exposed, but I have included similar ‘index modules’ elsewhere where they would not be needed.)

Sure, I think this is a pretty compelling argument against it: Serious OPAM package quality issues

In this case you can again use dune to hide the module which should not be exposed, see the (private_modules ...) stanza here: https://dune.readthedocs.io/en/stable/dune-files.html

1 Like

Can you not document .ml files? the doc for ocamldoc (so meta) seems to suggest doc can live in .ml files if there is no .mli file.

Yes, of course… thanks for pointing that out. It seems I made an assumption based on my own use-cases. I have a habit of using mli files directly as documentation, viewed in my editor, rather than using generated doc files.

1 Like