Re: Mixing OO and DB

From: Dmitry A. Kazakov <mailbox_at_dmitry-kazakov.de>
Date: Sat, 16 Feb 2008 12:38:36 +0100
Message-ID: <11x13hc7bc4hs.1j9fl70wqyscn$.dlg_at_40tude.net>


On Fri, 15 Feb 2008 17:45:16 -0800 (PST), David BL wrote:

> On Feb 16, 5:24 am, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
> wrote:
>> On Fri, 15 Feb 2008 08:46:54 -0800 (PST), David BL wrote:

>>> I'm aware of the three conceivable options, but I'm quite clear in my
>>> mind that the system should only support the narrowing of in-
>>> parameters and widening of out-parameters.
>>
>> It is an arbitrary constraint, worse is that it kills any algebraic
>> operations.
>
> I imagine any notion of sub-typing could be called arbitrary because
> the fact is that there is no single definition that will keep everyone
> happy.
>
> I hope you are remembering in this discussion that I expect an OO
> language to support at least two distinct notions of subtype. One
> centres on substitutability of values and the other on
> substitutability of objects. I'm reticent to say variable instead of
> object because some people assume (by definition) variable represents
> a value.
>
> I'm assuming here we are only discussing value-types. Agreed?

Does it mean that we will not be able to model algebras in our programs? I see no reason why should we bring such sacrifice.

>>>Therefore, as Invert() has
>>> been written (1) is the only option.
>>
>> As a counterexample, consider C (complex) instead of Z.
>
> Please provide more details. Are you alluding to covariant return
> types? ie
>
> Complex Invert(Complex x);
> Real Invert(Real x);

Yes. Covariant result for Real :> Complex inheritance is appropriate and reasonable. But it is not for Real :> Integer. This is a mathematical fact, rather than a property of some arbitrary types system. The problem is that C is a field, Z is not. Thus the types system shall be able to capture what behavior (mathematical structure in this case) you are going to inherit upon derivation from R, a ring (for Z) or a field (for C). There is no way to know it in advance, and if we restricted it to "all what R is", we would get just another R.

> I don't see how this presents a problem.

The problem is that you never can inherit *all* behavior from T, by any S, which would not be trivially equivalent to T. It just does not go.

>>> If you want option (3) then you
>>> need to explicitly write a parameterised function. Eg
>>
>>> template <class T> T Invert(T x) { return 1/x; }
>>
>>> However it seems inappropriate to allow Invert<int>().
>>
>> From the language design point of view there is no any problem because the
>> type system shall have different types for polymorphic and specific values.
>
> Sorry, I can't understand "different types for polymorphic and
> specific values".

Let we have a class of types derived from the base type T, i.e.

   class T = { T, T1, T2, ... } (forall i, Ti <: T)

Then values t, t1, t2, ... of T, T1, T2 I call specific. Polymorphic values are ones of the class. A polymorphic value is like (T1, t1). It has the type tag and its specific value.

A properly typed system shall not mix t1 and (T1, t1). The first value has the type T1, the second value has the type "closure of the class T".

>>> When C.Date talks about value substitutability he doesn't mean you can
>>> pick any function you like and substitute a sub-type in place of a
>>> super-type throughout the function.
>>
>> Then it is worse, it is so that substitutability is not controlled by the
>> type. If so, then how it is any better than just let the programmer to do
>> what he wants?
>
> I don't understand what the problem is. Please provide an example.

If I have Foo defined on T and S derived from T, can I substitute a value of S in Foo? You say that to know the types would not be enough to tell that.

>>> Doing so gives you a *distinct*
>>> function and the system is not allowed to guess that it is meaningful
>>> to do so. If you wanted this to be valid, then it would greatly
>>> restrict possible sub-typing relationships and that limits code
>>> reuse. In particular, it would no longer be possible to treat Z as a
>>> subtype of R.
>>
>> (which is not, in LSP sense.)
>
> I think there is a misunderstanding here. In this discussion I'm only
> talking about value-types. In an OO application I would imagine that
> many if not most types are *not* value-types and indeed go by LSP for
> sub-typing. Note that I assume LSP is (only) about substitutability
> of objects (or if you like, variables that have state but don't
> necessarily represent a value).
>
> The types we are discussing here - ints, floats, circles, ellipses are
> all value-types. I don't see any sense in demanding LSP sub-typing
> amongst value-types. Variables for these types do nothing but hold a
> value, and don't exhibit behaviour in the sense that is relevant to
> LSP.
OK, let me to try from other side. The classes rooted in your value-types do not model integers, reals, circles, ellipses, because you strip out the corresponding algebraic properties of. E.g.

   Float models field (has + etc)
   class rooted in Float does not model field (does not have +)

This kills the whole idea of generic programming, i.e. what actually subtyping was thought for. You cannot design a field-based algorithm in terms of the class Float. You only can do it for the concrete specific type Float. Why should I derive anything then?

> In fact imposing LSP sub-typing amongst value-types means there cannot
> be any non-trivial sub-typing amongst value-types at all.

YES! [snip, we are in agreement here]

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Received on Sat Feb 16 2008 - 12:38:36 CET

Original text of this message