structure PersonDB = struct exception RecordNotFound (* * Record ia a parameterized type at the top of the class hierarchy. *) type 'x Record = { Name : string, Age : int, Address : string, SpecializedInfo: 'x } (* * A PersonRecord is subtype of Person with no specialization. *) type PersonRecord = {} Record (* * A StaffEmployee is a subtype of Record, with two added fields. *) type StaffEmployee = { HourlyWage: int, EmploymentStatus : int } Record (* * A SalariedEmpolyee is a subtype of Record, with two added fields. *) type 'x SalariedEmployee = { Salary: int, Step: int, SpecializedInfo: 'x } Record (* * A Programmer is a subtype of Salaried Employee (subsubtype of Person), * with one added field. *) type Programmer = { Languages: string list } SalariedEmployee (* * A Manager is a subtype of Salaried Employee (subsubtype of Person), with * one added field. *) type Manager = { Supervisees: string list } SalariedEmployee (* * A GenericRecord is the union of all record types that will be stored in * the database. *) datatype GenericRecord = PR of PersonRecord | SE of StaffEmployee | P of Programmer | M of Manager (* * A KeyedRecord is a record with an unbundled key, so that a generic * database find operation can be implemented. It's a datatype instead of * an abstype so that the find operation can access its constructors. *) datatype KeyedRecord = EmptyRecord | Data of {Key: string, Data: GenericRecord} (*with*) fun newPersonRecord(NameVal, AgeVal, AddressVal) = Data{Key=NameVal, Data= PR{Name=NameVal, Age=AgeVal, Address=AddressVal, SpecializedInfo={}}} fun newProgrammer(NameVal, AgeVal, AddressVal, SalaryVal, StepVal) = Data{Key=NameVal, Data= P{Name=NameVal, Age=AgeVal, Address=AddressVal, SpecializedInfo={Salary=SalaryVal, Step=StepVal, SpecializedInfo={Languages=["C", "ML"]}}}} (*end*) (* * PersonDatabase a is a generic database, intended to hold KeyedRecords. *) abstype 'p PersonDatabase = EmptyDB | Body of 'p list with val newPersonDatabase = EmptyDB fun AddPerson(EmptyDB, p) = Body([p]) | AddPerson(Body(b), p) = Body(b @ [p]) fun FindPerson(EmptyDB, k) = raise RecordNotFound | FindPerson(Body(Data((p as {Key=k, ...})) :: ps), k1) = if k = k1 then #Data(p:{Key: string, Data: GenericRecord}) else FindPerson(Body(ps), k1) end end