Xref: utzoo comp.lang.misc:7161 comp.object:2961 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!uunet!mcsun!ukc!pyrltd!tetrauk!rick From: rick@tetrauk.UUCP (Rick Jones) Newsgroups: comp.lang.misc,comp.object Subject: Re: CHALLENGE: typing and reusability Message-ID: <1121@tetrauk.UUCP> Date: 26 Mar 91 11:08:07 GMT References: <22032@yunexus.YorkU.CA> <11820:Mar1923:59:3591@kramden.acf.nyu.edu> <19MAR91.22493670@uc780.umd.edu> <18271:Mar2013:19:1091@kramden.acf.nyu.edu> <1991Mar20.214231.3411@neon.Stanford.EDU> Reply-To: rick@tetrauk.UUCP (Rick Jones) Organization: Tetra Ltd., Maidenhead, UK Lines: 109 As a challenge to static typing adherents, hoelzle@cs.stanford.edu (Urs Hoelzle) writes: > >Note that I'm not saying Ada can't do this because it has no >inheritance; I'm saying it couldn't do it even if it had inheritance. > >But you aren't convinced and I've heard this argument often enough, >so let me give an example. Please show me how you would use the many >features of Ada to write this in Ada (or any other statically-typed >language): This looks like a classic "fallacial proof" problem! Like all such brain teasers, the fallacy is actually in the problem, not in the solution. Let me demonstrate: >====================== example ============================== >Assume the following types: > >type List = generic list; understands (among others) > 'concatenate': returns a new [generic] list which is the > concatenation of the two argument lists" > 'do': takes a procedure with one argument and applies it > to all elements of the list (i.e. a generic iterator) > >type FooType = "object that understands 'foo'" > >type A = some random application type, understands (among others) > 'foo' and 'display' > >type B = some other application type (completely unrelated to A), also !! ^^^^^^^^^^^^^^^^^^^^^^^ !! > understands (among others) 'foo' and 'display' This proposition is actually the crux. It maintains that two completely unrelated types, which _happen_ to have two features/methods of corresponding names (and we will assume signatures :-), can be used interchangeably by client code which is only interested in those features. But there is a difference between _looking_ the same and _being_ the same. Both a letter and an invoice may support an operation "post", but it doesn't mean that you are doing the same thing to both of them. The letter you post to the mail, the invoice to the ledger. It's even more subtle if you also consider an invoice to be a sub-type of letter which can also be posted to the mail. Names in themselves are not as significant as they suggest. Eiffel has demonstrated this in its handling of multiple inheritance, where it allows features to be renamed on inheritance (the _same_ feature can have a _different_ name in the context of a sub-class; how do you handle that with dynamic typing?). Names are really a syntactic convenience. It's like the "structure equivalence" problem - are two structures that look the same in fact the same and therefore interchangeable? In this example, you can only safely interchange A and B for use of "foo" and "display" if these two features _are_ related. This is an issue of analysis and design, regardless of the language tools used. The purpose of a statically typed language is to ensure that the relationship exists and is valid. The real issue is not that the solution can't be type-checked, it's that the problem itself doesn't type-check. Please note that I'm not flaming dynamic typing as a concept, it has many points in its favour. What I would say is that any well-engineered design should in principle be statically type checkable, even if you choose to implement it in a dynamically typed language. Having said all that, I agree that current statically typed languages do have problems in this area, which results from the over-tight linkage of classes and types. I have deliberately avoided saying anything about inheritance when saying that "foo" and "display" should be related in A and B. I think that this is a yawning gap in current OO technology, where all (as far as I know) statically typed languages make class and type synonymous. You can therefore only establish the required type relationship between A and B using inheritance. The missing piece is a typing system which allows classes A and B to declare that their "foo" and "display" routines _are_ the same, not just appear to be so. These classes would therefore be subtypes of some implicit type whose only operations are "foo" and "display", even where there is no inheritance relationship. With only inheritance available, you can create the implicit type as an abstract class which supports "foo" and "display", and then make A and B inherit from it (this is where MI becomes indespensable). The generic list classes then have to be written in terms of this abstract class. This is an unwieldy way of doing something conceptually much simpler. >** So, would everybody who does *NOT* believe that dynamically-typed ** >** languages can achieve greater reusability than today's statically-typed ** ^^^^^^ >** languages PLEASE post a solution to this (written in his/her favorite ** >** programming language)??? ** I agree - today's static typing technology is not fully adequate. >To avoid misunderstandings, please note that the above example *is* >type-safe in an abstract sense: no 'message not understood' error can ^^^^^^^^^ >occur because all elements of listC understand both 'foo' (which may >be sent by someProc) and 'display'. However, I claim that this piece >of code won't type-check in Ada, C++, Eiffel, ... Not the way you presented it, as I illustrated. Is there a statically type-checked language where the type hierarchy is not tied to the class hierarchy? -- Rick Jones, Tetra Ltd. Maidenhead, Berks, UK rick@tetrauk.uucp Any fool can provide a solution - the problem is to understand the problem