Documenting what signatures are intended to be implemented by a module

I was speaking to a Haskell user and they said that one thing they like about typeclasses is that one has to explicitly register an instance of the typeclass in the source code, so that tooling can easily tell you what instances are available for a given typeclass, and this has a generally good effect on documentation, and also encourages the Haskell community to standardize around some common interfaces, i.e., there is a monoid typeclass in the stdlib.

Do documentation tools for OCaml currently expose functionality that would facilitate this kind of community standardization around a handful of standard interfaces? One can always write

module Int_ordered : Ordered = Int

and then the compiler would check that indeed Int implements the Ordered functionality. The module M need not be exposed publicly; there is no need to have very many specialized Int modules floating around, Int_ordered, Int_enumerable and so on; the point is to allow the programmer to annotate their code in a way that documentation tools understand which would signal that a module is intended to implement a certain interface.

2 Likes

Yes, we can easily document the intended compatible interfaces by doing something like:

(* int.mli *)

include Ordered
(* ...other items... *)

And then odoc does show the interface as one that was included. Eg, see Decimal (decimal.Decimal)

1 Like

Okay, thank you. That’s very helpful.

@yawaramin, part of my motivation for asking this is a comment you made in an older post that many small modules (as Haskell has many small typeclasses) would not be idiomatic for OCaml because it has subtyping. So, I want to ask you a loosely related question. Next priority for OCaml? - #120 by yawaramin

I understand what you’re saying here. I am wondering like, rather than constructing many small modules on the fly, because OCaml has module subtyping, do you think it would be more idiomatic to just infer large modules which are declared to implement a signature by way of an explicit include statement?

(There’s some difficult technical questions here that I’m setting aside as I don’t know how to address them)

Yes, I believe that is more idiomatic. For example if you look at my link above, I included the definitions of val compare and others directly in the Decimal module, I didn’t put them in a separate Decimal_compare module. The standard library takes this approach too, eg look at Int.compare. This is what enables uniform functor composition like eg Set.Make(Int) and Set.Make(Decimal).

1 Like

You might also consider just checking the type without introducing a new name, like this:

module _ : Ordered = Int
3 Likes

Why is the doc site displayed using a light theme on your machine but displays it using a dark theme on mine, even on mobile? Is there a way to force the doc site to be light theme when building docs?

It looks like you have dark mode preference set in your OS?

2 Likes