Re: Mixing OO and DB

From: Dmitry A. Kazakov <mailbox_at_dmitry-kazakov.de>
Date: Thu, 21 Feb 2008 20:04:11 +0100
Message-ID: <1kjuugvny6rj.1xwvagu41da95.dlg_at_40tude.net>


On Thu, 21 Feb 2008 05:41:42 -0800 (PST), David BL wrote:

> On Feb 21, 9:11 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
> wrote:

>> On Wed, 20 Feb 2008 21:42:44 -0800 (PST), David BL wrote:
>>> On Feb 20, 8:05 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
>>> wrote:
>>>> On Tue, 19 Feb 2008 18:15:31 -0800 (PST), David BL wrote:
>>>>> On Feb 19, 7:05 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
>>>>> wrote:
>>>>>> On Mon, 18 Feb 2008 19:09:48 -0800 (PST), David BL wrote:
>>>>>>> On Feb 19, 12:41 am, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
>>>>>>> wrote:
>>>>>>>> On Mon, 18 Feb 2008 05:59:39 -0800 (PST), David BL wrote:
>>>>>>>>> I disagree. I'm talking about algorithms that are implicitly
>>>>>>>>> parameterised over various value-types.  LSP isn't even applicable for
>>>>>>>>> value-types.
>>
>>>>>>>> How so? LSP defines behavioral notion of type as set of provable
>>>>>>>> predicates. This clearly includes your parametrized types. The parameters
>>>>>>>> are subjects of type substitution. It is pure LSP.
>>
>>>>>>> I have a more specific understanding of LSP.   Let an object mean a
>>>>>>> variable that has identity, state and behavior, but isn't assumed to
>>>>>>> hold a value.
>>
>>>>>> Wait here. Object's state + identity = its value. As I said before, value
>>>>>> semantics is fundamental in the sense that a stateful one is derived from
>>>>>> it.
>>
>>>>> Saying
>>
>>>>>     Object's state + identity = its value
>>
>>>>> doesn't seem well defined.  Does the object's state ever encompass
>>>>> following a pointer?   What about objects with OS resource handles
>>>>> like socket handles or mutex handles?  How do you delineate its state?
>>
>>>> Resource value /= value of its handle. They are of *different* types.
>>
>>>> (You have a mental block about [fictional] equivalences of values. Whatever
>>>> equivalence between the resource and its handle might exist, it is not an
>>>> immanent thing. It is simply an implementation to be *first* proven to be
>>>> correct. Claiming the equivalence in advance is putting a cart before the
>>>> horse.)
>>
>>> You didn't answer my question.  How do you define an object's state
>>> when it contains pointers or handles?
>>
>> Through the values of those pointers and handles. Where is a problem?
>>
>>> Here's an example
>>
>>> class X
>>> {
>>> public:
>>>     X() { p = new int(0); }
>>>     ~X() { delete p; }
>>>     int Get() const { return *p; }
>>>     void Set(int x) { *p = x; }
>>> private:
>>>     int* p;
>>> };
>>
>> And? Did you mean X could be made a subtype (and supertype) of int. So
>> what?

>
> No. Please ignore the purpose of X. However assume that its copy
> constructor and assignment operator have been declared private to make
> it clear that it isn't a value type.
>
> I wanted to establish what you considered the state of an object
> instance to be. I presume it includes the value of the pointer p,
> but not the int that p points at. Yes?

Right, if we considered the private view of X, where p would be visible.

> How do you justify that? It seems entirely adhoc to me.

It is not very clear to me what does require a justification. There is no relation between X, int, int* except than stated. X has values. Note that values are incomparable (as it should follow from what I said before). Hence you could not say that two X are same if p is same. If we liked the compiler to copy X, we would declare corresponding copy operations. That would make possible by-copy parameter passing. But again it would not guarantee anything like "same value passed". The compiler would apply the copy operation, get a value and whether that is same is up to the programmer. In short, two values are same when the operation = is defined and returns true. Otherwise, nobody cares.

>> I
>> hope you aren't going discard the notion of field? Then how to capture it
>> without out-substitutability?

>
> Out-substitutability isn't enough either. Algorithms and data
> structures that are parameterised in a field T may mention T in many
> places. For example, in variables declared on the frame within a
> function, or for members of data structures etc.

You should care only of field operations.

> I think it is utterly wrong to say that Real and Complex are subtypes
> of Field. In fact I would suggest that it's rather confusing to think
> of Field as a type at all!

Sure, because field is a class, a set of types implementing the interface of. Note that class is not a type. A class can have an associated type of its polymorphic values when that makes sense. In the case of Real and Complex it does. I.e, there could be a subclass of field containing Real and Complex in order to be able to mix them in arithmetic. In general case for Field it does not make sense. It could be sort of:

Field <-- Numeric field <--- Real / Complex

> As we've agreed a type is a set of values
> plus a set of operations on those values. Do you see how Field
> doesn't fit that notion very well? If we want to shoehorn it into
> being a type then its values are themselves types like Real and
> Complex. I cannot think of any operations on it.

Field is not a type it is a set { Real, Complex } (for simplicity only these two). The closure of Field is a proper type. Its values are pairs type - value. It has all operations of the field, like +, -, *, ... These operations are said dispatching (virtual in C++ terms). When + is applied to the polymorphic values an operation is chosen according to the first elements of the pairs involved and applied to the second elements of.

>> Note that I don't buy parametrization for two reasons:
>>
>> 1. It is a meta language (=accepted defeat)
>>
>> 2. If parametrization were OK, then why did you introduce
>> in-substitutability? Let's kill it too and use parametrization everywhere.

>
> I don't accept your second reason because in-substitutability avoids a
> lot of parameterisation so that's a positive not a negative.
>
> In order to support a type of type like Field there needs to be
> special syntactic support one way or the other. Perhaps something
> like
>
> // Field = set of types
> type* Field;

This is an interface. Here the field operations should be declared as abstract.

> type Complex
> in Field
> {
> ...
> };

> type Real
> in Field
> isa Complex
> {
> ...
> };

It is transitive, so Field need not to be mentioned here.

> type* Ring;
>
> type Integer
> in Ring
> isa Real
> {
> ...
> };

OK, but you should mention Ring interface in the Field one. Otherwise they will be different interfaces in Real. This is the diamond-diagram problem of multiple inheritance.

> type Matrix<Field>
> {
> ...
> };
>
> Since we haven't been able to avoid parameterisation of Matrix,

This is a different issue, namely, how containers are created in the types algebra. I would not like to see parametrization here. Instead it should state (without inventing some ad-hoc syntax):

  1. Matrix is an interface
  2. Matrix implements a container interface of a two dimensional array
  3. The container elements are from the class of Field.
  4. Matrix (square one) implements the ring interface

Instead of parametrization Matrix could be constrained:

2.a in its indices (matrix size and shape) 3.a in its elements (real matrix, for instance)

> I
> don't think a lot has been achieved. Note as well that we didn't
> actually formalise what a field is apart from stating that Real and
> Complex are examples of fields.

We did, when we declared Field. That shall have +, -, *, / etc. Real and
Complex have to implement them. Matrix will use these operations in order
to implement its own interface.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Received on Thu Feb 21 2008 - 20:04:11 CET

Original text of this message