9.6  Oop Support

At the moment the most significant project in progress is implementing support for object-oriented programming in Mythryl per Bernard Berthomeiu’s March 2000 paper OO Programming Styles in ML.

I believe having a reasonable OOP story is essential if Mythryl is to gain traction with contemporary mainstream programmers, partly because they will not take a language seriously that does not have OOP support, partly because they will not be able to efficiently transfer their existing skills to a language without OOP support — they have no other skills for programming in the large.

There have been a variety of attempts over the years to support object oriented programming in ML, ranging from Ocaml to Moby to the ML2000 proposals.

There is at this point no consensus that OOP even makes sense in the ML context. For example, John Reppy thinks the topic worth pursuing, Robert Harper does not.

Among those who think OOP is a sensible fit to ML programming, there is no consensus as to how it should be done. Xavier Leroy’s approach in Ocaml requires major changes in the typechecking system which significantly increase its complexity. Much the same maybe said of John Reppy’s approach in Moby.

My impression is that while mainstream programmers need some flavor of OOP to feel comfortable in a programming language, that OOP does not need to be particularly sophisticated nor of any particular flavor. A wide variety of OOP approaches may be found among successful contemporary mainstream languages, ranging from the simple (Perl) to the complex (C++) with mainstream programmers by and large seeming largely oblivious to the differences.

It is not clear that experienced Mythryl programmers will use OOP heavily once through the transition stage of learning the language. The Ocaml experience is that even when OOP support is provided, only about 15% of programs use it. In general ML module system support satisfies most programming in the large requirements; OOP is mainly needed when late binding is required on a large scale.

Consequently, I feel Bernard Berthomeiu’s OOP approach is a good fit to Mythryl. It provides basic OOP support, in principle without requiring any change to the compiler except syntactic sugar.

I have an initial implementation perhaps half to three quarters complete:

Pushing this project through to completion proved to require more changes to the compiler than I had originally hoped. There are two major problems.

The first is that Berthomeiu’s approach requires that classes be made abstract, which in ML requires strong sealing, which in turn requires synthesizing a complete API signature for the package defining the class. This is not reasonable when OOP is being implemented as a derived form early in the compiler, before type deduction has been performed.

To deal with this problem I implemented a new style of package sealing partial sealing which is like strong sealing except that API elements not mentioned are left visible and unchanged instead of being hidden. This required changes in:

A more serious problem is that if the methods of a class are to be able to create instances of that class (a frequent requirement if, say, combining two objects to produce a third in the pure-functional spirit), then the new method for the class must be mutually recursive with the methods for that class.

This is a problem primarily because Berthomeiu’s OOP approach also requires the methods to be typeagnostic, which requires that they be generalized. SML/NJ, at least, does not generalize mutually recursive functions.

Berthomeiu’s paper passes over this point in silence.

Here is a minimal stimulus exhibiting the problem. This program compiles fine:

package test: api { f: X -> Void; } {

    fun f (x: X) = ();
    fun g () = f 0;

but when made mutually recursive it fails to compile:

package test: api { f: X -> Void; } {

    fun f (x: X) = ()
    fun g () = f 0;

(See src/app/tut/oop-crib-temp/oop-crib-temp.pkg.)

Removing this restriction results in changes starting to propagate deeper into the compiler. I do not yet understand those parts of the compiler well enough to make this work:

I do not understand that part of the codebase, so I have suspended this line of development until I have time to study it properly.

(2011-06-07 CrT: Robert Harper informs me that most-general-type inference on mutually recursive functions is mathematically undecidable.)

Comments and suggestions to: