4/10/2023
This document is the most current thinking on types.
 Type = common features for a set of objects. They have an interface and an implementation.   They are
        nouns, as it were with associated operations. E.g. integers can be added.
 Classes is a realization of a type and has a factory method(s) to create instances.

 In systems where there is a single implementation of a type, classes and types are not distinct.

 In QDL we propose
 type = type definition. This is like an interface in Java in that it has signatures of functions.
 forge = an factory to make types.

 Types may be added using the restriction operator: |
 Integer|x restricts x to integer values, so

 Integer | x := 3; // works
 Integer | x := 3/4; // raises type error

 Since stems have implicit type with trailing ".",
    Integer | x.
 means to restrict all values of x. to being integers. Can also do
    Integer | List | x.
which restricts x. to being a list of integers.

| x (monadic) queries the type, so
   Integer == | x ? 0: "empty"

Also works in function signatures

   f(Integer | x, Boolean | flag)->...

Tells the system to enforce types.

Types
-----
These are names with lists of functions. There are no implementation details.

   type[Name]extends[X0,X1,...][f0(arg0,...);f1(arg0,...);...]

Types may extend other types.
If a factory does not implement one of the given functions, then an error is raised.


Type Forges
------------
These are implementation tasked with creating new types.  These may implement types
and extend existing factories:
      forge[Name]
    extends[X0, X1, ...] // extends forges.
 implements[Y0, Y1,...] // ?? these would be types -- shouldn't they be with types?
       body[
           Name()->... ;//constructor
            ...
           ];

Xi, Yj are resp types or factories. These reside in imported modules and should be fully qualified.

Inheritance contract
--------------------
For each of the Xi, an internally managed instance will be created. The order of these matters
in that if a function, f, is in any of the Xi and not overridden, then the first on the list
will win. This prevents the dreaded multiple inheritance "diamond problem".

Access super antecessors with super(name), e.g., super(X0) woulf give access to the (managed super-forge)
X0.

Constructor contract
--------------------
The name of the constructor is the same as the name of the type. It is accessed exactly once with the
reserved word new. If there is no override, then the Xi's constructors are called in order.

E.g.
 X x := X::X(a,b,c); // calls constructor in forge named X.

 inside of the forge constructor is something like
 X0 X0 := X0::X0(a,b,c);
 X1 X1 := X1::X1(a,b,c); etc.


Accessing an Xi
---------------
The reserved function super(x) can be used. This returns the internally managed instance. In constructos,
you may call super(x, y) to set the internally managed instance to y.

E.g.
module['qdl:/math', 'math']
  body[
        type[Complex]
     extends[Number]
        body[
              re();im();add(Complex|w);subtract(Complex|x);mod();...
            ;]
  ];
module_import('qdl:/math');

     forge[Complex]
implements[math#Complex]
      body[
          Complex(Number|x, Number|y)->block[__real := x; __imag:=y;];
          __real:=null; __ imag:=null;
          re()->__real;im()->__imag;
          mod()->sqrt(__real^2+__imag^2);
          add(Complex|w)->Complex::new(re()+w::re(), im()+w::im());
          times(Complex|w)->Complex::new(re()*w::re()-im()*w::im(), re()*w::im()+im()*w::re());
          to_string()->'<' + re() +',' + imag() + '>';
          input_form()->'Complex::new(' + re() + ','+imag() + ')';
       ];

    z := Complex::new(2, 3/2);
    w := Complex::new(-1, 1/2);
    z::add(w)
    // If we allow for overloading operators as part of the Number contract:
    z+w
<1,2>
    Complex | u. := {'a':Complex::new(1,sin(pi()/4))};
    u.'b' := Complex::new(-1,cos(pi()/3));
    u.
['a':<1,0.7>,'b':<-1,0.5>]

Overriding operators
It is also possible to define types for number, string and such, so that
a mapping from monadic and dyadic operators is in effect. E.g. if
a type extends Integer, then functions named add, subtract would be implemented
and would map to + and -. For complex numbers (above example) that would automatically
allow for things like

   Complex z := Complex::new(2,2/3) + Complex::new(-1,1);

 and it would just work.

