As stated above, I’d be happy to hear about such benefits.
I understand the benefit of separate compilation, but I think this will diminish gradually as flambda becomes more crucial for getting good performance out of OCaml.
Quoting from Edward Z Young’s thesis on Backpack, where he makes the case for a more complex modular system:
Unfortunately, type classes are ill-suited for certain cases of separate modular development:
- From a code perspective, type class parametric code is often harder to use than monomorphic code. For an inexperienced Haskeller, the proliferation of constraints and type parameters in the type signatures of functions can make an otherwise straightforward API impenetrable:
(=~) :: (RegexMaker Regex CompOption ExecOption source,
RegexContext Regex source1 target)
=> source1 -> source -> target – from regex-posix-0.95.2
This point is reasonable, and indeed functors removing type parameters make using said types clearer in my experience.
- Furthermore, type classes work best when exactly a single type parameter is involved in instance resolution. If there aren’t any type parameters, you must introduce a proxy type to drive instance resolution; if there are multiple parameters , you often need to resolve ambiguity by introducing functional dependencies  or replacing parameters with associated types.
This has to do with limitations of typeclass inference, and in my experience in a fairly large haskell codebase, this is still worth the advantages, and is fine so long as you aren’t pushing the envelope with typeclass usage.
- Type classes work best when it is clear what methods they should support. However, for many interfaces, it is not obvious what set of methods should be put into an interface; for example, there are many functions which an interface for strings might support—which ones go in the type class? It is inconvenient to define a new type class (and new instances) just to add a few more methods, and thus this is rarely done in practice.
This seems valid but it applies equally well or even more so when creating functor interfaces, while with type classes, adding functionality to a type can at least be done on a mixin basis by adding an additional type class when needed.
- From a performance perspective, code which uses a type class is compiled without knowledge of how the type class’s methods are implemented. This can be quite costly in a language like Haskell, where inlining definitions is essential to achieving good performance.  This problem can be mitigated by specializing code to a particular type, but if this specialization occurs at use-site, the compiler ends up repeatedly reoptimizing the same function, blowing up the code size of a program. (C++ templates suffer from similar problems.)
This point seems just as valid with regard to OCaml’s functors.