14

Type Inferencing Based on Complete Type Specifications

Embed Size (px)

Citation preview

Type Inferencing Based on CompleteType Speci�cationsLeonid A. Kalinichenko and Vladimir I.ZadorozhnyInstitute for Problems of InformaticsRussian Academy of SciencesVavilova 30/6, Moscow, V-334, 117900, Russiae-mail: [email protected] speci�cation completeness is a necessary prerequisite for support ofobject creating formulae in object calculus leading to formation of newtypes to be integrated into a type lattice containing the types from whichthey were formed.The paper shows what conditions should be satis�ed in order thatthe inferred types could be correct and what is the systematic way ofintegration of these types into the existing type lattice on the basis of awell-de�ned subtype relation. Ignoring of the speci�cation completenessfor type inference may lead to inconsistent results.The paper contributes to clari�cation of type inferencing operationsfor the case of complete type speci�cations.1 IntroductionAbstract data type (ADT) concepts play more and more important role indata models and database systems. Introduced in database world in early 80sas a technique for inclusion of new user-de�ned types in relational DBMSs [16],ADT provides now a basis for object-oriented data models [10] as well as fora new SQL standard [9]. Object-oriented programming languages are basedon a data abstraction according to which programs are composed of modules,each implementing an ADT [7]. Architectures of heterogeneous interoperableinformation resource environments (HIRE) [12, 13] built around a concept ofa global object space also use an idea of ADT speci�cations separated fromcompletely encapsulated implementations.Information systems design frameworks based on a concept of a re�nementof speci�cations of requirements by interoperable compositions of pre-existingresources taken from HIRE require the ADT speci�cations completeness [6].The completeness of ADT speci�cation is a necessary prerequisite to checkconsistency of ADT speci�cations (e.g., type operations should preserve typeinvariants, a type subtyping hierarchy should have a model) and to reason ontheir reusability and consistent composability under application requirements.The completeness requirement still is ignored by industrial environments [13]though recent analysis clearly indicates its importance [6, 7, 11].

The SYNTHESIS semantic interoperability project [6, 5] provides for two-dimensional uniformity of complete type speci�cations separated of their (pos-sibly multiple) implementations.In this paper1 we focus on issues of a type inferencing during object calculusformulae evaluation under assumption of the type speci�cation completeness.Two kinds of formulae are distinguished: object-preserving and object-creatingones. The object-preserving formulae are limited to returning existing objectsfrom an object base while object-creating formulae may create new objectsduring their evaluation [14]. The object- creating formulae can form new typesthat were not integrated with the types from which they were formed. Based onthe notion of a well-de�ned type lattice we should have a systematic possibilityto integrate this new types into the existing lattice.Taking into account existing approaches for a type inference that do notcare of a speci�cational completeness, we extend them to this case.The paper is organized as follows. We start with a short introduction intoa SYNTHESIS object model that is based on the concepts of algebraic systems[8]. A type system of the model is introduced. An approach for a declarativetype speci�cation technique that is based on an object calculus and on pred-icative speci�cations is de�ned. A subtyping relation forming a type lattice isde�ned.After introduction of the model we consider an approach for a type infer-encing using type constructing operations [14] and type expressions for a casewhen a type speci�cation contains only signatures of functions. This approachis re�ned further for the case of the complete type speci�cation. An exampleclarifying the proposed approach is given.2 SYNTHESIS object model2.1 On the theory of algebraic systemsThe theory of algebraic systems [8] resulted from an application of the methodsof mathematical logic to algebra. So it takes frontier place between algebra andlogic.An algebraic system (or simply a system) is an object U =< A;Of ; Op >,consisting of some non-empty set A, a set of operations Of = fF1; :::; Fngde�ned on a set A, a set of predicates Op = fP1; :::; Pmg de�nedon A. In this case a type of the algebraic system is an object <farity1; :::; farityn; parity1; :::; paritym >, where farityi; parityi are arities ofan operation Fi and a predicate Pi correspondingly.The set A is called a carrier or a basic set of the system U and its elementsare elements of U . The power of A is the power of U . Assuming O = Of [Opwe can write the system U in a shorter notation: U =< A;O >.An algebraic system U =< A;O > is called an algebra if Op = ;, and it isa model if Of = ;.1This work is supported by the Russian Foundation for Basic Research (projects 93-012-618, 94-07-20453)

Here we are interested in an introduction of a concept of a cartesian productof an algebraic system. Consider some non-empty set A whose elements willbe called indexes. For each index � 2 A an algebraic systemU� =< M�; Of�; Op� >of the given type � is put into correspondence.A cartesian product QM� of an indexed system of sets M� under indexesfrom A is a set of functions f from A to union SM� satisfying the followingcondition:f(�) 2M� (� 2 A).Very often a set N of natural numbers serves as a set of indexes. In thiscase the function f is de�ned by the sequence of its values f(0); f(1); :::; f(k); :::and so may be equated with it.We de�ne operations Of and predicates Op on QM� giving an algebraicsystemU =< QM�; Of ; Op >of the same type as the type of the system U�. Let f1; :::; fn be some elementsof QM�.We assumePi(f1; :::; fn) = truei� for every � 2 APi�(f1(�); :::; fn(�)) = true.In the same way we will call a value of Fj(f1; :::; fm) an element f 2QM�,which is de�ned by the following condition:f(�) = Fj�(f1(�); :::; fm(�)) (� 2 A).An algebraic system U =< QM�; Of ; Op > constructed in such a wayis called a cartesian product of systems U� under a set of indexes A and isdenoted asQU�. If the set A contains only numbers 1; 2; :::; k; then a cartesianproduct QU� may be denoted as U1 � :::� Uk, and its elements are equatedwith sequences < c1; ::::; ck > (ci 2 Ui).This de�nition of a product of algebraic systems having the same type canbe easily extended for a case of a product of algebraic systems having di�erenttypes [2].2.2 SYNTHESIS type systemThe fundamental concept of the SYNTHESIS object model [5] is an abstractvalue. All data components in SYNTHESIS are abstract values. Abstract val-ues are instances of abstract data types (ADT) which are algebraic systems.Therefore all the abstract values are typed. The model includes a consistentobject-oriented subset: objects are considered as a kind of mutable values. Themodel is functional in the sense that all accesses to objects and all manipu-lations of objects are based on the application of functions to objects. Basedon the notion of the algebraic system, a SYNTHESIS object model is purelybehavioral. In particular the basic for relational model notion of a tuple (ora record) type is replaced by more general notion of a product type providingobject compositions while preserving pure behavioral approach.

TavalTnoneSS �� ���...

TfunctionTsignature Tset TobjectT typeT class���Tmetaclass Atomic typesMetatypesfor composite types��QQQQQQTproductAAAAAFigure 1: SYNTHESIS type system latticeSYNTHESIS type system lattice is given on Fig. 1.Links in the lattice represent subtyping relationship. The root of the latticeis the Taval type corresponding to all abstract values considered in the model.Its base is the Tnone type provided for representation of values with no seman-tics. For instance, the value none belongs to Tnone and may be returned byfunctions producing a null result of any type.All immutable types of the language obtain properties of Taval type, allmutable types obtain properties of Tsynt object type. Values of Taval type arecharacterized by interfaces having function signatures with typed arguments.The basic property of an abstract value is a capability of executing of interfacefunctions requiring the abstract value itself as its �rst parameter.Objects are a particular case of abstract values. Values of the Tsynt objecttype specialize abstract values with new properties - an ability to have a uniqueidenti�er and a potential ability to belong to some class (classes). Thereforeany mutable type is considered to be a subtype of the corresponding immutabletype.A type in the language is treated as a �rst-class value. Such values maybe de�ned in speci�cations, on typing of variables, may be produced by typefunctions and type expressions.A class in SYNTHESIS is treated as a subtype of the set type. It providesfor using these generally di�erent constructs homogeneously: a class may beused everywhere where a set de�ned on ADT may be used. This propertysimpli�es reaching of the SYNTHESIS object calculus and algebra closure.Class and type speci�cations are abstract and completely separated of theirimplementations. A number of various correct implementations (concretiza-

tions) may correspond to such speci�cations. Correspondence of an implemen-tation to a speci�cation can be established by means of the metadata repository.A product type T is a composition of a number of other types T1; :::; Tn andhas been already de�ned for algebraic systems.2.3 Subtyping relationThe basic meaning of a subtyping in SYNTHESIS is in accordance with thegeneral agreement concerning the subject [3]:� subtyping is a partial order on types;� if � < � then all values (objects) of a type � can be used in any contextin which values (objects) of a type � can be used;� if � < � then instances of type � have at least all properties that instancesof type � have. In another words, a theory of the supertype is containedin a theory of the subtype, i.e. � � � , Th(�) � Th(� ). Therefore,subtyping implies a subset relationship between instances.A subtype � can be obtained from the supertype � by:� adding of new functions to an interface of �;� re�ning the assertions;� re�ning the functions.Subtyping declaration leads to a speci�cation inheritance. For each typemultiple supertypes can be declared assuming a multiple inheritance. A mul-tiple inheritance with con icts when an inherited function belongs to severalsupertypes should lead to an inheritance of a composition of types of thesefunctions in di�erent supertypes [4] (the composition here corresponds to ajoin operation on types in SYNTHESIS). The result of an inheritance shouldproduce a correct subtype de�nition.2.4 Speci�cations of functionsAll operations over typed data in the SYNTHESIS language are representedby functions. A function type de�nes a set of functions, each function of theset being a mapping of a domain of the function (a cartesian product of thesets of the input parameters values) into a range of the function (a cartesianproduct of the sets of the output parameters values).Most commonly a type speci�cation contains only signatures of functions.Such speci�cation is quite rude approximation of the operation, namely, w.r.t.types of its arguments and results (i.e., parameters type declaration form itsprecondition, and result type declaration forms its post-condition). Practicallyit says nothing on what the operation does and as it was mentioned above weneed sematicaly complete type speci�cation.

In SYNTHESIS we use predicative speci�cations of functions which aregiven by mixed pre- and post- conditions de�ning the functions. To expressconditions related to changing of the information resource states an ability isneeded to denote variables expressing a resource state before and after functionexecution. For that a reference to a value of a variable after execution of afunction is denoted by primed variables.Predicative speci�cations are expressed using formulae of the SYNTHESISobject calculus. To specify formulae a variant of a typed (multisorted) �rstorder predicate logic language is used. Every predicate, function, constant andvariable in formulae is typed.Predicates in formulae correspond to classes, collections and functions. Vari-ables, constants and function designators are used as terms. Each term has awell de�ned type. An atom (atomic formula) appears as p(t1; :::; tn); where p isa predicate and ti are terms. Atomic formulae a de�ne simple statement overinformation resources.In a simpli�ed form a formula is an atom or appears as:w1 & w2 (w1 and w2)w1 j w2 (w1 or w2)^ w2 (not w2)w1� > w2 (if w1 then w2)ex x=t (w) (for some x of type t; w)all x=t (w) (for all x of type t; w)where w, w1, w2 are formulae.Variables in formulae can be bounded by quanti�ers. A scope of a quanti�erin a formula with quanti�er is a formula w. Occurences of variables denotedby a quanti�er in a scope of the quanti�er are bounded and are free for theiroccurences out of the scope. A notation x=t de�nes that a type of a variable xis t.If a formula is used as a query to an information resource base and hasx1; :::; xn as free variables then the query results in a collection of substitutions ofwell typed values of x1; :::; xn such that on each of them the formula interpretedon an information resource base gets the true value.3 Type expressionsType operations and expressions are used as a technique for target-creatingformulae evaluation, view and schema evolution support. Here following [14],we introduce type operations that are suitable for incomplete type speci�cationscontaining only signatures of functions.Let Ti(1 � i � n) denotes types.� An operation T1 & T2 produces a type T as a meet of the operand types.T includes functions that are common for T1 and T2: If T2 (T1) is asubtype of T1 (T2) then T1 (T2) is a result of a type meet. Type T is

placed in the type lattice as a supertype of types being operands of theoperation.� An operation T1 j T2 in case when both types T1 and T2 are mutableproduces as a result a type T that is a join of the operand types. Tincludes a union of functions of T1 and T2: If T2 (T1) is a subtype of T1(T2) then T2 (T1) is s result of a join operation. A type T is placed inthe type lattice as a subtype of the operand types. If both types or oneof the types T1 or T2 are not mutable and they are not subtypes of eachother then the result of a join operation is a product type T1 � T2 that isplaced in the type lattice as a subtype of other product types (but not ofthe operand types) in accordance with the interfaces de�ned for producttypes.� An operation T1 � T2 produces as a result a type T that is a product ofthe operand types. A type T is placed in the type lattice as a subtype ofother product types (but not of the operand types) in accordance withthe interfaces de�ned for the product types.A product type T1 � T2 � : : : � Tn is placed in the type lattice as asubtype of a product type T 01 � T 02 � : : : � T 0m if m � n and Tiis a subtype of T 0i for 1 � i � m: It is placed in the type latticeas a supertype of T 001 � T 002 � : : : � T 00k type if n � k and Ti is asupertype of T 00i for 1 � i � n: If a product type cannot be placed intoa type lattice as a subtype of another product type it is placed there asa subtype of the Taval type (if it is an immutable type) or as a subtypeof the Tsynth object type if it is a mutable type.The operations above are a clari�cation of type operations de�ned in [14]for a more general case of uniform treatment of mutable and immutable valuesin SYNTHESIS [5].Using the operations above, type expressions are introduced taking intoaccount that meet and join operations are commutative and associative and aproduct operation is neither commutative nor associative. A product operationhas a higher priority comparing to the operations of type meet and join.4 Type inferencing operations re�nement forcomplete type speci�cation caseComplete type speci�cations include speci�cations of assertions (predicates con-straining admissible type values) and speci�cations of functions serving as typeoperations. In this case type inferencing operations should produce correcttypes placed into type lattice in accordance with the de�nition of subtypingrelation given above that is clari�ed here as follows.A subtyping relation for a supertype Tsup = < Vsup; Ofsup ; Opsup > anda subtype Tsub =< Vsub; Ofsub; Opsub > holds i� there exists an abstraction

function Abs mapping the subtype state space (Statesub) into the supertypestate space (Statesub) such that the following conditions are satis�ed:1. For a subtype invariants to be a re�nement of a supertype invariants thefollowing condition should be proved (Psup(Psub) is a conjunction of allpredicates in Opsup(Opsub)):8 Statesub; Statesup � Psub ^Abs) Psup2. To preserve supertype operations behavior, subtype operations shouldbe a re�nement of the corresponding supertype operations [7]. To showthat an operation of a subtype Osub 2 Ofsub is a re�nement of the cor-responding operation Osup 2 Ofsup of the supertype when a subtypeand supertype state spaces Statesub and Statesup are related by an Absmapping, proof obligations should be generated according to the followingtemplates [15]:The �rst template should state that a subtype operation should terminatewhenever a supertype operation is guaranteed to terminate (X and Ydenote input and output spaces of the operation):8 Statesub; Statesup; X � preOsup ^Abs) preOsubThe second template ensures that the state after the subtype operation(marked by ') represents one of those abstract states in which an oper-ation of a supertype could terminate (here spc(O) denotes a predicativespeci�cation of O expressed in a mixed pre- and post- conditions):8 Statesub; Statesup; State0sub; X; Y � preOsup ^ Abs ^ spc(Osub) )9 State0sup �Abs ^ spc(Osup)If these conditions are satis�ed then a subtype operation is suitable forall purposes for which a supertype operation is suitable.We de�ne a type speci�cation to be correct i� it has a model (e.g., forTsup it means: 9 v 2 Vsup � Psup(v) and type operations preserve type invari-ants (for Tsup it means that for each Osup 2 Ofsup the following conditionshould be satis�ed: 8 v 2 Vsup; x 2 X; y 2 Y � preOsup(v; x) ^ Psup(v; x) )postOsup(v; y) ^ Psup(v; y))).The type inferencing operations de�ned above should be extended with thefollowing transformations (justi�cations):� Type meet operation:Assertions created in the resulting type (obtained from operand typeassertions) should be formed by a maximal subset of assertions commonfor the operand types and relevant to a reduced set of functions of aresulting type.� Type join operation:A set of assertions inherited from operand types should be consistent (theresulting type should have a model).

� Any type operation:A speci�cation of any interfacing function of a resulting type can be cho-sen among corresponding interfacing functions of operand types if thefunctions are in a re�nement order (for a supertype (subtype) more ab-stract (more re�ned) function should be chosen). If the functions arenot in a re�nement order they are considered to be di�erent interfacefunctions.In case of a speci�cation completeness type inference operations shouldproduce correct supertype (subtype) of the operand types. To do that theoperations should perform nontrivial transformations of speci�cations and jus-ti�cation of their correctness.5 Case study: research projects supportapplication5.1 Problem descriptionThere is a funding agency supporting research projects (entirely or partly). Aproject can be entirely supported (ES-project) after positive conclusion of aprincipal reviewer whose status in the relevant research areas is characterizedas "high". A project can be partly supported (PS-project) if it is alreadysponsored by a company whose current �nancial state is stable.If research area is "computer science" then ES-projects should get morethen 10th level of priority, while PS-projects { just more then 5th level (i.e.,generally ES-projects on computer science are more signi�cant). Moreover,in this case research area of the principal reviewer in ES-projects should beexactly "computer science", and sponsors of PS-projects should be engaged incomputer industry.Any ES-project (PS-project) can collaborate with another ES-project (PS-project) correspondingly. A PS-project should be reviewed by participants ofany other project while an ES-project should be reviewed only by participantsof another ES-project. An ES-project (PS-project) can be joined with anotherES-project (PS-project) correspondingly to organize a new project.5.2 Problem speci�cation in simpli�ed SYNTHESISsyntaxBelow, for simplicity we assume identity abstract mapping in type/subtype re-lation.Type declarations:{Tproject;in:type;area:{set_of: string};

priority_level:integer;};{Tes_project;in: type;supertype:Tproject;principal_reviewer:Treviewer;collaborate_with:Tes_project;reviewed_by:Tes_project;make_joint_project(+in/Tes_project, -out/Tes_project);constraints:all proj/Tes_project(proj.principal_reviewer.status = "high") &all proj/Tes_project (proj.area = "comp_sci" ->proj.priority_level > 10 &proj.principal_reviewer.res_area = "comp_sci")};{Tps_project;in: type;supertype:Tproject;sponsor:Tcompany;collaborate_with:Tps_project;reviewed_by:Tproject;make_joint_project(+in/Tps_project, -out/Tps_project);constraint:all proj/Tps_project(proj.sponsor.cur_state = "stable") &all proj/Tps_project (proj.area = "comp_sci" ->proj.priority_level > 5 &in("comp_industry", proj.sponsor.engaged_in)};{Treviewer;in: type;res_area: string;status: string;};{Tcompany;in:type;engaged_in: {set_of: string};cur_state: string;} Declaration of sets:fsp : {set;

type_of_element: Tes_project};psp: {set;type_of_element: Tps_project}5.3 Examples of queries1) Union of fsp and psp:fx j in(x; fsp) j in(x; psp)gWhat is the type of element of the resulted set? The most "lazy" way issimply to take for this the nearest commom supertype of Tes project andTps project (i.e., type Tproject). But information on types of fsp and pspallows to get more restricted resulting type. And it is exactly what our intentionis: to generate the most restricted supertype of basic types for such kinds ofqueries. Such type set is formed as meet of Tes project and Tps projecttypes:Te&p project = Tes project & Tps projectThe type hierarchy evolves as follows:{Tes_project;in:type;supertype:Te&p_project;...};{Tps_project;in:type;supertype:Te&p_project;...};{Te&p_project;in:type;supertype:Tproject;collaborate_with:Te&p_project;reviewed_by:Tproject;make_joint_project(+in/Te|p_project, -out/Te&p_project);constraint:all proj/Te&p_project (proj.area = "comp_sci" ->proj.priority_level > 5)}Type Te|p project is de�ned below.2) Intersection of fsp and psp:

fx j in(x; fsp) & in(x; psp)gThe most "lazy" way: simply take for the type of an element of the resulted setthe nearest commom subtype of Tes project and Tps project (in the worstcase type Tnone). But it is too restricted, and again, information on types offsp and psp allows to get more loose resulting type. And our intention here isto generate the least restricted subtype of basic types. Such type set is formedas join of Tes project and Tps project types:Te|p project = Tes project j Tps projectThe type hierarchy evolves as follows:{Te|p_project;in:type;supertype: Tes_project, Tps_project;collaborate_with:Te|p_project;reviewed_by:Tes_project;make_joint_project(+in/Te&p_project, -out/Te|p_project);constraint:all proj/Te|p_project(proj.principal_reviewer.status = "high"&proj.sponsor.cur_state = "stable") &all proj/Te|p_project (proj.area = "comp_sci" ->proj.priority_level > 10 &in("comp_industry", proj.sponsor.engaged_in) &proj.principal_reviewer.res_area = "comp_sci")};3) Product of fsp and psp:fx; y j in(x; fsp) & in(y; psp)gThe type of element of the resulted set is the product type of Tes project andTps project:Te*p project = Tes project * Tps projectType hierarchy evolution:{Te*p_project;in:type;es_component: Tes_project;ps_component: Tps_project} As we stated earlier, to preserve supertype operations behavior, subtypeoperations should be a re�nement of the corresponding supertype operations.In the example without loss of generality we demonstrate the re�nement for therestricted operation speci�cation that contains only pre- and post- conditionsde�ned for types of parameters.

6 ConclusionImportance of complete speci�cations as a necessary prerequisite to consistentADTs de�nition (e.g., type operations should preserve type invariants, typesubtyping hierarchy should have a model) and to their reusability and consistentcomposability under application requirements is well recognized.The paper attracts attention to the fact that the type speci�cation com-pleteness is also a necessary prerequisite to support object creating formulae inobject calculus that should form new types to be integrated into a type latticecontaining the types from which they were formed.The paper shows what conditions should be satis�ed in order that the in-ferred types could be correct and what is the systematic way of integration ofthese types into the existing type lattice on the basis of a well-de�ned subtyperelation. Ignoring of the speci�cation completeness for type inference may leadto inconsistent results.The paper contributes to clari�cation of type inferencing operations for thecase of complete type speci�cations.The paper shows that a dynamic type inference in presence of completetype speci�cations may lead to serious practical problems: a way of automaticrealization of nontrivial transformations (justi�cation) of type speci�cations fortype inference deserves further investigations.References[1] S. Alagic. F-Bounded polymorphism for database programing languages.In Proc. of the Second East-West Database Conference, Klagenfurt,September 1994.[2] I. A. Chaban, L. A. Kalinichenko, and V. I. Zadorozhny. Could the OODBstandards be better if more grounded? In Proc. of the Second East-WestDatabase Conference, Klagenfurt, September 1994.[3] H.-D. Enrich, G. Engels, J. Paredaens, and P. Wegner. Fundamentals ofObject-Oriented Languages, Systems and Methods. Dagstuhl Seminar Re-port, 95, August 1994.[4] A. Formica,M. Missiko�. Correctness of ISA hierarchies in object -orienteddatabase schemas. In Proceedings of the International Conference "Extend-ing Database Technologies", EDBT'94, March 1994.[5] L. A. Kalinichenko. SYNTHESIS: a language for description, design andprogramming of interoperable information resource environment. Institutefor Problems of Informatics of the Russian Academy of Sciences, (in Rus-sian), 113p., September 1993.[6] L. A. Kalinichenko. Emerging semantic-based interoperable informationsystem technology. Computers as our better partners. In Proceedings ofthe International IISF/ACM Symposium, Tokyo, World Scienti�c, 1994.

[7] B. Liskov, J. M. Wing. Speci�cations and their use in de�ning subtypes.OOPSLA'93, 1993.[8] A.I. Maltsev. Algebraic systems. Moscow, Nauka, (in Russian), 1970.[9] J. Melton. Object technology and SQL: adding objects to a relationallanguage. Data Engineering Bulletin, IEEE Computer Society, 17(4), De-cemeber 1994.[10] The Object Database Standard: ODMG-93. Ed. by R. G. G. Cattell,Morgan Kaufmann Publ., 169p., 1994.[11] A. Hutt (editor). Object Analysis and Design. Description of methods.Object management group. John Wiley and Sons. 202p., 1994.[12] Object Management Group, "Object Management Architecture Guide",OMG Document Number 92.11.1, September 1, 1992.[13] Object Management Group, "The Common Object Request Broker: Ar-chitecture and Speci�cation", OMG Document Number 91.12.1, December1991.[14] R. J. Peters, A. Lipka, M. T. Ozsu, and D. Szafron. The query modeland query language of TIGUKAT. Technical Report TR 93 -01, ComputerScience Department, University of Alberta, Canada, June 1993.[15] J. M. Spivey. The Z Notation. A reference manual. Prentice-Hall, 1989.[16] M. Stonebraker. Inclusion of new types in relational data base systems. InReadings in Database Systems, Morgan Kaufmann Publishers, California,1988.