This is another solution in OCaml to the Independently Extensible
Solutions to the Expression Problem. as described by
Zenger and
Odersky in their Technical Report
Nr. 200433,
March 2004.

This code has been check with OCaml 3.08. It uses anonymous classes in
DblePlusNegTest. This could have been expanded into toplevel class
definitions in an earlier version of OCaml, which allowed closed classes
(classes where self had a closed object type).
The recent versions of OCaml do not allow this but for anonymous classes).

The code is then a mere translation of the original code in Scala,
where type annotations have been removed. Hence, the code is in general
shorter than in scala with the only exception of using private methods for
sharable instance variables discussed above.

ShowDblePlusNeg uses multiple inheritance of two classes built from a
common ancestor. This is a known difficulty when using multiple inheritance,
since the state of the common ancestor is being dupplicated in the two
subclasses. For instance, objects of the class ShowDblePlusNeg.num will
contained two occurrences of field value. This is fine here because
instance variables are not mutable and fields are not updated, so they can
be freely dupplicated: the two fields are filled with (and retain) the
same initial value v.

OCaml does not offer any primitive construct to deal with this situation.
However, a simple solution is to make all read, write and update to instance
variables of the shared class go indirectly through private methdods. Since
methods definitions are overridden during inheritance, all methods will then
refer to the same instance variable---the one defined last---and unused
dupplicates will passively sit in the state of the object. Ths is not very
elegant, but it works well. A small extension of the language with
annotations on instance variables could be used to drive the inheritance
of instance variables and avoid the use of private methods.

We have not used this schema here because objects are purely functional.

The eval and show classes above contain the method #apply, with
different types. Since expressions and vistors have mutually
recursive types, this would make it impossible to use both visitors
on the same expression. Fortunately, the recursion is covariant,
and we can coerce to forget the apply method in expression types.
Below, a new problem arises in class dble, as visitors return
expressions. We can
no longer use the covariance of the recursion. We choose to make
#apply private, so that it no longer appears in the object type.
We can extract the #apply method by using an out parameter.
moduleFDblePlusNeg = structopenFBasePlusNegclass ['e] dbleapply = object (self : 'e #visitor)valmutableresult = Nonemethodprivateapply (t : 'e) : 'e =t#acceptself;matchresultwithSomex®x | None®assertfalseinitializerapply := self#applymethodprivatereturnx =result¬SomexmethodvisitNumv =self#return (newFBase.num (v×2))methodvisitPluslr =self#return (newFBasePlus.plus (self#applyl) (self#applyr))methodvisitNegt =self#return (newFBaseNeg.neg (self#applyt))endend