From: Patrick May on
"Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:
> I think it quite is possible to achieve ad-hoc subtypes with interface
> inheritance + subtyping + supertyping. E.g. if you have two unrelated
> types A, B and wanted A<:B, you could create a third "bridge" type C,
> such that A<:C (supertype) and C<:B (subtype). Because <: is
> transitive A<:B. Once C is declared the compiler will require to
> implement all missing implementations of inherited/exported
> operations. This can be automated by providing the compiler with type
> conversions appropriately declared etc.
>
> No OOPL is close to that.

I think you could manage it with Common Lisp. The meta-object
protocol gives you a lot of expressiveness and flexibility.

Regards,

Patrick

------------------------------------------------------------------------
http://www.softwarematters.org
Large scale, mission-critical, distributed OO systems design and
implementation. (C++, Java, Common Lisp, Jini, middleware, SOA)
From: Dmitry A. Kazakov on
On Thu, 15 Apr 2010 14:36:37 -0700 (PDT), Nilone wrote:

> OO inheritance doesn't seem to suit algebraic structures. Isn't the
> co- and contravariance rules on algebraic domains reversed as compared
> to co-algebraic domains?

What rules do you mean?

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Nilone on
On Apr 16, 8:38 am, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
wrote:
> On Thu, 15 Apr 2010 14:36:37 -0700 (PDT), Nilone wrote:
> > OO inheritance doesn't seem to suit algebraic structures.  Isn't the
> > co- and contravariance rules on algebraic domains reversed as compared
> > to co-algebraic domains?
>
> What rules do you mean?
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de

My view of IntegerType is that it's an object, not a class, and I made
it as much so as the language allowed, hence the static methods and
lack of constructor.

Inheritance requires that the methods of the class accept the same or
broader set of arguments, while returning the same or narrower set of
types, right? If I tried to inherit my IntegerType from a similarly
designed RealType, it would require that IntegerType.Divide() accept
RealValues, which isn't what I want to do at all. I want
RealType.Divide() to accept IntegerValues. Conversely, if I inherit
RealType from IntegerType, it would require that RealType.Divide()
return at most an IntegerValue, which is again not what I want to do.

The only possibility for inheritance that I can see is if I create a
NumericValue class from which all possible types of numbers can
inherit. But what behaviour does an algebraic value have? In OO,
they're only used by objects to represent state.
From: Dmitry A. Kazakov on
On Fri, 16 Apr 2010 01:10:50 -0700 (PDT), Nilone wrote:

> On Apr 16, 8:38�am, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
> wrote:
>> On Thu, 15 Apr 2010 14:36:37 -0700 (PDT), Nilone wrote:
>>> OO inheritance doesn't seem to suit algebraic structures. �Isn't the
>>> co- and contravariance rules on algebraic domains reversed as compared
>>> to co-algebraic domains?
>>
>> What rules do you mean?
>
> My view of IntegerType is that it's an object, not a class, and I made
> it as much so as the language allowed, hence the static methods and
> lack of constructor.

Egh, object is a run-time instance of a type. Class is a set of [derived]
types. IntegerType, as the name suggest, is a type.

> Inheritance requires that the methods of the class accept the same or
> broader set of arguments, while returning the same or narrower set of
> types, right?

No. Inheritance is always covariant.

A covariant argument/result is of the class closure (i.e. polymorphic). An
operation defined on the class = method [in the corresponding
argument/result].

Contravariant = no inheritance. An operation contravariant in some
argument/result is not a method in this argument/result = it is not
inherited in there. It is just so because the type is specific
(non-polymorphic).

> If I tried to inherit my IntegerType from a similarly
> designed RealType, it would require that IntegerType.Divide() accept
> RealValues, which isn't what I want to do at all.

Why so? If you inherit a method of the interface:

function "/" (Left, Right : Real) return Real;

then all arguments and the result are covariant. I see no problem. Except
that some [broken] languages give you no control over the covariance.

BTW, if you derived Real from Complex, you would like to have Sqrt
covariant in the argument and contravariant in the result.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: S Perryman on
Nilone wrote:

> On Apr 16, 8:38 am, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de>
> wrote:

>>On Thu, 15 Apr 2010 14:36:37 -0700 (PDT), Nilone wrote:

>>>OO inheritance doesn't seem to suit algebraic structures. Isn't the
>>>co- and contravariance rules on algebraic domains reversed as compared
>>>to co-algebraic domains?

>>What rules do you mean?

> My view of IntegerType is that it's an object, not a class, and I made
> it as much so as the language allowed, hence the static methods and
> lack of constructor.

> Inheritance requires that the methods of the class accept the same or
> broader set of arguments, while returning the same or narrower set of
> types, right? If I tried to inherit my IntegerType from a similarly
> designed RealType, it would require that IntegerType.Divide() accept
> RealValues, which isn't what I want to do at all. I want
> RealType.Divide() to accept IntegerValues. Conversely, if I inherit
> RealType from IntegerType, it would require that RealType.Divide()
> return at most an IntegerValue, which is again not what I want to do.

> The only possibility for inheritance that I can see is if I create a
> NumericValue class from which all possible types of numbers can
> inherit. But what behaviour does an algebraic value have? In OO,
> they're only used by objects to represent state.

The reality is that you actually need type substitutability constraints
to be more precise than an "all or nothing" scenario.

So if we have :

type Real
begin
whole, fraction, add, subtract, multiply, divide
end

type Integer
begin
value, add, subtract, multiply,
divide // the (quotient,remainder) form
end


We want to define the relationships thus :

Real conforms-to Integer // C1
{
whole = Integer::value ;

invariant : fraction = 0 ;
}

Integer conforms-to Real // C2
{
exclude { divide }
fraction = 0
}


And for the following :

doSomething(Real r, Real i)
{
Integer v1(123) ;
Real v2(zero) ;

v1 = v1.multiply(r) ; // #1
v2 = i.divide(v1.plus(1) ) ; // #2
print v1.value, v2.fraction ;
}


Real r1(123.25) ;
Real r2(123) ;
Integer i1(999) ;

doSomething(r1,r2) ; // U1
doSomething(r1,i1) ; // U2
doSomething(r2,r1) ; // U3


U1 will fail with a type error, due to #1.
C1 requires that only a Real with fraction = 0 can be used as an Integer.
The value r1 does not conform here

U2 will fail with a type error, due to #2.
#2 requires an instance that supports Real::divide.
But here 'i' is an Integer, and C2 states that Integer does not support
Real::divide.

U3 is ok.

The only other issue is when errors are detected.
U2 can be only detected at runtime. U2 can be detected statically.


As you can see, there is far more scope for substitutability and
correctness than the current OO type regimes (the Simula model in
particular) provide.


Regards,
Steven Perryman