Re: Mixing OO and DB
Date: Mon, 18 Feb 2008 19:09:48 -0800 (PST)
Message-ID: <59008154-3b39-486a-be6f-f899a30193cf_at_e6g2000prf.googlegroups.com>
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:
> > On Feb 18, 8:20 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
> > wrote:
> >> On Sun, 17 Feb 2008 19:12:50 -0800 (PST), David BL wrote:
> >>> On Feb 16, 8:38 pm, "Dmitry A. Kazakov" <mail..._at_dmitry-kazakov.de>
> >>> wrote:
> >>>> 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:
>
> >>>>>>>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 assume the notation T :> S means S is a subtype of T. I think you
> >>> are suggesting (a definition of subtyping) that T :> S implies that
> >>> for any algorithm, all occurrences of T can be replaced by S.
>
> >> This is a LSP notion.
>
> > 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. If S,T are object types where S is a subtype of T then LSP states that if q(x) is a property provable about objects x of type T. Then q(y) should be true for objects y of type S.
In my mind LSP is inappropriate for value-types because it is concerned with variables rather than values.
> (The real problem with LSP is that unconditional substitutability is all
> thinkable context is impossible.)
>
> >>> However, then there would be no valid subtyping relationships between
> >>> Z,R and C. For example, R :> C isn't valid because R is an ordered
> >>> field whereas C is not. C :> R isn't valid because C is an
> >>> algebraically closed field, whereas R is not. Z isn't a subtype of
> >>> either R of C because Z isn't a field. Neither R or C is a subtype
> >>> of Z because only Z has the property that its positive elements are
> >>> well-ordered.
>
> >> Right. This is why I treat subtyping as mere a types relation such that an
> >> operation gets inherited. Inheritance means no more than that the compiler
> >> does not spill a type error and routinely applies appropriate conversions
> >> of the arguments. The conversions are user-defined or compiler-generated.
>
> > That's not formal enough for me. It sounds like sub-typing can mean
> > anything you want it to mean.
>
> Right, it has to be this way. If I want to make square a subtype of train
> traffic, it is my business. I should provide the implementations of the
> corresponding operations and that is.
> >>> I would suggest what you're after is some concept of abstract value-
> >>> types like "Ring" and "Field". I can see it could be useful to write
> >>> data structures and algorithms in their most generic sense without
> >>> explicit parameterisation. For example matrices are defined on an
> >>> abstract field. This still allows for many nontrivial functions to be
> >>> written - eg matrix inverse. I can imagine indicating that R,C are
> >>> subtypes of Field according to this parameterisation notion of sub-
> >>> type.
>
> >>> However independently of such as feature, I still believe it is
> >>> important to capture the quite different concept of subtyping espoused
> >>> by C.Date, because it concerns implicit conversions of value-types (as
> >>> distinct from parameterisation), and that's very important.
>
> >> I see no difference. To me it is the same notion of subtyping.
>
> > Really! I can't understand that.
>
> I don't see how Date's conversions are any different from mine:
>
> S is an in-subtype of T in the operation f iff:
>
> 1. there exists f, operation on T denoted as T.f
>
> T.f : T -> <no matter>
>
> 2. there exists a conversion from S to T:
>
> S_to_T : S -> T
>
> 3. there exits f, operation on S denoted as S.f
>
> S.f : S -> <no matter>
>
> It is said that f is inherited by S iff
>
> S.f = T.f o S_to_T
>
I think we're better off with examples. At least I have some context!
Consider the following function that inverts a matrix parameterised in
field T for the type of the matrix elements.
template <class T> Matrix<T> Invert(Matrix<T> x)
Invert<R> is valid because R is a field, whereas Invert<Z> is not
valid because Z is not a field.
According to C.Date's definition of sub-type, Z is a sub-type of R.
This definition of sub-type doesn't allow you to assume you can
replace R with Z in Invert<R> to yield Invert<Z>.
> >>> Treating Z as a subset of R, or R as a subset of C is very useful. A
> >>> function that accepts a complex number can be passed a real number
> >>> without explicit conversion. A function that returns a real number
> >>> can used to initialise a complex variable. Implicit conversions are
> >>> deemed valid if and only if *exactly the same logical value* is
> >>> represented before and after the "conversion". This implies two
> >>> things: the conversion cannot silently drop information, nor can it
> >>> silently add information.
>
> >> I would relax this too. Note that you can add exceptions as ideals to the
> >> set of values. This gives you an opportunity to convert non-substitutable
> >> out-Circle for out-Ellipse into substitutable
> >> out-Circle-or-else-Constraint_Error for
> >> out-Ellipse-or-else-Constraint_Error.
>
> > Sorry, I just cannot understand your approach.
>
> You cannot convert, you can drop an exception. This makes things
> substitutable back. This is not mine approach, it is a widely used model.
> Consider float. You cannot convert max float + max float from R back to
> float. So you throw overflow, or use NaN, whatsoever. You add an ideal to
> the set of floats /= R.
>
> > You didn't answer my question: When a Rectangle value is converted to
> > a ColouredRectangle, what is the colour initialised to?
>
> It cannot be converted! For out-substitutability of Rectangle, it is out
> ColouredRectangle which is converted to Rectangle.
So you're saying slicing away the colour is respectable?
> In-substitutability of S to T in f() works as a composition f o S_to_T
> Out-substitutability of S to T in g() works as a composition S_from_T o g
>
> The conversion is not forward, it backward.
Received on Tue Feb 19 2008 - 04:09:48 CET