# Defining several similar classes by inheritance

**URL:** https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717
**Category:** Learning
**Tags:** objects, ppxlib
**Created:** [April 26, 2019, 4:22pm UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717 "2019-04-26T16:22:41Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![thierry-martinez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/thierry-martinez/32/1481_2.png) [@thierry-martinez](https://discuss.ocaml.org/u/thierry-martinez)
#### Post date: [April 26, 2019, 4:22pm UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717/1 "2019-04-26T16:22:41Z")

</div>

Dear OCaml community,

Let say I have two classes `a` and `b` that define methods `a#m` and `b#m` (we can suppose that these methods overload the method `O#m` from a common ancestor `o` of the classes `a` and `b` if it helps).

I can define a class `a_enriched`, where I overload again the method m for composing its result with a given function f.

```ocaml
class a_enriched f = object
  inherit a as super

  method! m = f super#m
end

```

I can do the same with `b_enriched`.

```auto
class b_enriched f = object
  inherit b as super

  method! m = f super#m
end

```

The code that defines `a_enriched` and `b_enriched` is the same apart from the name of the classes.

**Can I define the classes `a_enriched` and `b_enriched` without repeating most of their definitions?** In my actual settings, I don’t have only one single method `m` but several methods to overload, and I would like be able to write things more concisely.

* * *

To give more context if it can help to find the correct solution, the two classes `A` and `B` are called in my particular use case `lift_expr` and `lift_pattern`, and derive from “lifters” obtained with the `traverse_lift` deriver from ppxlib.

```auto
class lift_expr loc = object(self)
  inherit [Parsetree.expression] Clang__bindings.lift
  ...
end

class lift_pattern loc = object(self)
  inherit [Parsetree.pattern] Clang__bindings.lift
  ...
end

```

and the code in `...` is substantially different between the two classes.

My question comes from the need to enrich the behavior of both lifters by open recursion. Something like:

```auto
class lift_expr_enriched f loc = object
  inherit lift_expr loc as super

  method! qual_type e =
    match e with
    | <thing of interest>(x) -> f x
    | _ -> super#qual_type e
end

class lift_pattern_enriched f loc = object
  inherit lift_pattern loc as super

  method! qual_type e =
    match e with
    | <thing of interest>(x) -> f x
    | _ -> super#qual_type e
end

```

and I would like to write most of the duplicated code once.

Thank you!

---

<div class="post-metadata">

### Author: ![thierry-martinez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/thierry-martinez/32/1481_2.png) [@thierry-martinez](https://discuss.ocaml.org/u/thierry-martinez)
#### Post date: [May 17, 2019, 5:05am UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717/2 "2019-05-17T05:05:40Z")

</div>

I found a solution by defining the enrichment in a functor: the enriched class should precisely match a given class type (I wonder if there exists a more general solution), but it fulfils my needs.

```auto
class type ['a] t = object
  method m : 'a list
end

class a = object
  method m = [42]
end

class b = object
  method m = ["foo"]
end

module type S = sig
  type t

  class c : [t] t
end

module Enrich (X : S) = struct
  class c = object
    inherit X.c as super

    method! m = super#m @ super#m
  end
end

module A_enriched = Enrich (struct type t = int class c = a end)

module B_enriched = Enrich (struct type t = string class c = b end)

class a_enriched = A_enriched.c

class b_enriched = B_enriched.c

```

---

<div class="post-metadata">

### Author: ![ivg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ivg/32/103_2.png) [@ivg](https://discuss.ocaml.org/u/ivg)
#### Post date: [May 17, 2019, 2:02pm UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717/3 "2019-05-17T14:02:19Z")

</div>

> [@thierry-martinez](#):
>
> My question comes from the need to enrich the behavior of both lifters by open recursion.

If I understood you correctly, then you’re not really using the open recursion in the functionality that you’re mixing in to your overloaded methods. I.e., the `f` function doesn’t really call any methods. You’re just using overriding as a way of adding this behavior.

If that is true, then there is a general solution, which unfortunately will require changing the base classes, i.e., the `lift_expr` and `lift_pattern` classes.

The idea is simple, the class methods instead of returning a concrete type shall instead be parametrized in the return type and become a functor, e.g.,

```ocaml
module Lift_expr(M : S) : sig
    class base : object
       method qual_type : expr -> 'a M.t
       ...
    end
end

```

Then, when you need to add an extra behavioral aspect to your computation, you can pass a different module `M` which can have arbitrary (bounded by the signature `S` behavior). You won’t need any inheritance.

Concerning the signature `S`, it could be just

```ocaml
module type T1 = sig
   type 'a t
end

```

But it won’t give you a lot of freedom. For example, if you will later decide to add some context aspect, or even some state, then you will not be able to do this. Therefore you may stick to Applicative or even to Monad. The latter will enable a lot of freedom, so that you can even change the execution order, add non-determinism. Moreover, you can even use [Monad transformers](http://binaryanalysisplatform.github.io/bap/api/odoc/monads/Monads/Std/index.html) to compose those behavioral aspects.

For a complete example of this solution, consider looking into [BAP Evaluators Framework](https://github.com/BinaryAnalysisPlatform/bap/blob/master/lib/bap/bap.mli#L2737-L3232). It uses classes parametrized into monads.

Take a note, that they are deprecated, as classes usually make composability nearly impossible1, so we switched to more composable solutions which don’t involve any inheritance. Therefore, if you’re in control of the library, my advice would be to stick away from classes.

* * *

1) When you inherit from a class, you have to reason about all ancestors, as well as keep in mind all possible descendants. Therefore, if your class hierarchy is open, it is impossible to write roubst code, as you can’t really assume any behavior from any method. This limits applicability of classes into very small hierarchies, which are closed and used locally, inside a module and are hidden beyond the abstraction wall.

---

<div class="post-metadata">

### Author: ![thierry-martinez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/thierry-martinez/32/1481_2.png) [@thierry-martinez](https://discuss.ocaml.org/u/thierry-martinez)
#### Post date: [May 18, 2019, 11:20am UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717/4 "2019-05-18T11:20:31Z")

</div>

Thank you very much, @ivg, for such a detailed explanations!

Unfortunately, it will not be easy to change the base classes: they are generated by the `traverse_lift` PPX deriver from `ppxlib`.

> [@ivg](#):
>
> Concerning the signature `S` , it could be just
> 
> ```auto
> module type T1 = sig
> type 'a t
> end
> 
> ```

I think that there should at least be some constructors for values of type `'a t` in order to be able to return a value of type `'a M.t` in the methods of class `base`.

For my particular case, I solved the problem with a functor taking as parameter a module carrying the class to enrich.

```auto
module type Lifter = sig
  type t

  class lifter : object
    inherit [t] Clangml_lift.lift
    inherit [t] Ppxlib_traverse_builtins.std_lifters
  end
end

module Remove_placeholder (X : Lifter) = struct
  class lifter subst_payload map = object
    inherit X.lifter as super

    method expr (expr : Clang.Ast.expr) = ...

    method qual_type (qual_type : Clang.Ast.qual_type) = ...
  end
end

```

The concerns I have with the generality of this approach (even if it works in my case) is that the type of `lifter` in the signature `Lifter` is fully specified. It seems strange for me there seems to be no kind of subtyping available at the level of class types (we cannot call the functor `Remove_placeholder` with a class with more methods than those specified in the signature).

Interestingly, my problem has a nice solution in C++.

```cpp
template<typename T, T f(T), class X>
class Derive : public X {
public:
  T m() { return f(X::m()); }
};

```

which can be used this way:

```cpp
class C {
public:
  virtual int m() { return 1; }
};

static int f(int x) {
  return x * 2;
}

int
main(int argc, char* argv[])
{
  C c;
  Derive<int, f, C> c_prime;
  ...
}

```

What prevents to do that in OCaml is that there seems to be no way to parameterize a class by another class (since classes are not first-class values), and even if we may do that with a functor, this method is rigid in the type of the class.

---

<div class="post-metadata">

### Author: ![ivg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ivg/32/103_2.png) [@ivg](https://discuss.ocaml.org/u/ivg)
#### Post date: [May 21, 2019, 1:53pm UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717/5 "2019-05-21T13:53:54Z")

</div>

> [@thierry-martinez](#):
>
> Interestingly, my problem has a nice solution in C++

This makes sense, since templates in C++ operate as macros, i.e., on a syntactic level, and therefore,

```c++
template<typename T, T f(T), class X>
class Derive : public X {
public:
  T m() { return f(X::m()); }
};

```

Is a macro that generates a new module with different types every time you’re applying it. And only once a template is instantiated to a new module it is being typed and manifested to an object.

Contrary, despite looking syntactically close, OCaml functors are values, not patterns for generating code. You can, of course, implement the same approach in OCaml using `ppx` rewriters. But it will have the same issue as C++, instead of depending on abstractions you will be depending on syntactic constructs, i.e., instead of quantifying on what a module is doing your’re quantifying on how it looks.

---

<div class="post-metadata">

### Author: ![thierry-martinez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/thierry-martinez/32/1481_2.png) [@thierry-martinez](https://discuss.ocaml.org/u/thierry-martinez)
#### Post date: [May 22, 2019, 1:53pm UTC](https://discuss.ocaml.org/t/defining-several-similar-classes-by-inheritance/3717/6 "2019-05-22T13:53:55Z")

</div>

Indeed, there is no typing before instantiating the template, so it makes thing easier for C++.

However, I am not able to construct a counter-example that justifies the following restriction for class types (OCaml manual, 7.9.1, § Class body type).

> Furthermore, all methods either virtual or public present in the class body must also be present in the class body type (on the other hand, some instance variables and concrete private methods may be omitted).

I would have liked to have a functor that accepts as argument a module with a class `c` containing at least a method `m`, and possibly other methods: it does not seem to be possible. (Again, it is more a theoretical question, I don’t need it actually in my case.)
