What is the "right" way to add constraints on a type, to handle recursive structures with variants and to combine fragments of types?

In short, I don’t know how to fully and correctly implement my OO model in OCaml, and I feel that I try to bend variant for that purpose.

Let me express simply the situation in other words:

1/ in OCaml I can express any individual class/thing/entity (designed with an OO approach):
I just have to pack up its attributes and operations in a record, a class or a module. A signature will mint it’s attributes and operations, and a structure will implement with functions the behaviour defined by the operations.
And I can express any invariants of that class/thing/entity that will be enforced as you demonstrated above within a module. There is no need for research tools.
We assume here that a class just knows how to create a relation with other classes by calling the relevant function.
However, implementing the inheritance/multiple inheritance is not clear for me.
With the OCaml object system, it’s easy to define that B inherits from A. Then B gets automatically all the features from A and can overrides some features.
How to do the same with the OCaml module system?
Hmm… multiple signature and structure include and redefinition/shadowing of “inherited” functions should do the job. Am I right?
So, as a side question, if this is exact:
what are the advantages of the object system? and when to use it

2/ In OCaml, I can create any kind of relation between any number of classes:
A product type such as a record or a tuple is fine for holding that. There is place for any properties such as the name of the relation, the role and the cardinality and multiplicity of each class involved in the relation and any other useful properties (types ans functions). And again any invariant of the relation can be enforced as desired.
Except for the case of inheritance relation has been pointed in 1/, the job should be done.

3/ In parallel, OCaml let me express trees with variant:
a simple or complex fixed size tree with a variant (i.e. for various cases as you mentioned above), or even a language with a recursive variant as well as some eval function to analyze any unlimited size expression which is an unlimited size tree.
Exactly as shown in RWO:Variants :

"Examples from RWO: variant and recursive variant"...

Various cases:

type basic_color =
  | Black | Red | Green | Yellow | Blue | Magenta | Cyan | White ;;

type color =
  | Basic of basic_color     (* basic colors *)
  | Bold  of basic_color     (* bold basic colors *)
  | RGB   of int * int * int (* 6x6x6 color cube *)
  | Gray  of int             (* 24 grayscale levels *)

Or a small language using recursive variants:

type 'a expr =
  | Base  of 'a
  | Const of bool
  | And   of 'a expr list
  | Or    of 'a expr list
  | Not   of 'a expr

BTW, I made a mistake when aswering @ivg that “I’ve never used that kind of expression 'a <sometype>”. I’ve already played with small languages like the example from RWO or OCaml refman where " expr is parameterized by a polymorphic type 'a ".

The most famous example of unlimited size int binary tree defined with a recursive variant is probably:

type tree = Leaf of int 
          | Node of tree * tree

I feel uncomfortable with variant, somehow “obliged” to use it because those trees are very nice, and also because it’s very close to OO inheritance with property {disjoint}

So the point that motivated me to create this topic may be that:

  • I try with OCaml to define inheritance/multiple inheritance between things/classes with modules (because “first-class OCaml modules are mainly used over classes…”) and I don’t really know how to handle that with modules;
  • I struggle for using polymorphism in order to factorize as much as possible functions and don’t exactly know how to do.

These two points aim towards as much as possible factorization of things (and their relations, which are things).

Is it more clear?


PS: as a side note and as as a possible illustration, pls. find a class diagram from this site https://stackoverflow.com/questions/37112937/uml-modeling-how-to-represent-a-multi-way-inheritance-onto-a-class-diagram

image

UML can represent this with no problem. But, how you map it into a programming language is another matter. (And another SO question.) Many languages do not support multiple classification of instances, so you have to hammer a square peg into a round hole.

Can it be implemented in OCaml as follows?

type person = Physical_person 
            | Company
type inex = Inner_actor 
          | External_actor
type actor = { person: person;
               kind:   inex
             } 

and then the attributes/operations of the general Actor class should be injected in the sub classes via include in the module of each other class?