Com S 641 meeting -*- Outline -*- * type equivalence (3.5) ** the problem ------------------------------------------ TYPE EQUIVALENCE (3.5) How to check actual's type vs. formals? Example: class Car = record var age: newint, var weight: newint end; class Person = record var age: newint, var weight: newint end; class Ship = Car; var c: Car; var p: Person; var s: Ship; var c2: record var age: newint, var weight: newint end; var p2: record var age: newint, var weight: newint end; proc con(r: {age:intloc, weight:intloc}) = r.weight := r.weight + 1 ------------------------------------------ Q: Which of the variables (if any) can be passed to con? ** structural and by-name equivalence ------------------------------------------ NOTIONS OF TYPE EQUIVALENCE structural: name (occurrence): ------------------------------------------ ... S matches T if either both are primitive types and textually equal, or both are record types with the same field names and with the corresponding types match. ... S matches T if either both are primitive types and textually equal, or both are names that denote the same declaration occurrence. Q: What rule is used in C for comparing types? In Java? C uses name equivalence, as does C++, for structs So does Java Q: What do C and C++ do with typedefs? these are compared structurally Q: What about Haskell data and type declarations? data is by name, type is structural. Q: What kinds of parameter types are useful with occurrence equivalence? records, arrays, etc. Q: What are the advantages of occurrence equivalence? gives more stringent type checking, so don't try to pass Kilometers to Miles easier to implement (just compare an address or tag) Q: Disadvantages? hard to link to external files or modules or libraries ** typing rules ------------------------------------------ BY NAME TYPING RULES Schmidt's version: pi |- D: ___________________________ pi |- record D end: What are the types of our example? ------------------------------------------ ... pi |- D: pi1 dec _________________________________ where occ is unique pi |- record D end: occ pi1 class def occ is called an *occurrence tag* or *brand* ... Car: 0 {age: intloc, weight: intloc} class Person: 1 {age: intloc, weight: intloc} class Ship: 2 {age: intloc, weight: intloc} class c: 0 {age: intloc, weight: intloc} p: 1 {age: intloc, weight: intloc} s: 2 {age: intloc, weight: intloc} c2: 3 {age: intloc, weight: intloc} p2: 4 {age: intloc, weight: intloc} con: 5 {age: intloc, weight: intloc} -> comm Q: Is that typing rule functional? No. How would we make it functional? (pi,oc) |- D: pi1 dec / oc1 _________________________________ where oc2 = oc1+1 (pi,oc) |- record D end: oc2 pi1 class / oc2 Discuss whether this is really better or not ** leave it to the programmer to decide A good principle of language design: if you have a design choice that isn't perfectly clear, give it to the programmer to make, but provide a good default In Modula-3 this is done with type eqvivalence, it's structural by default, but you can use "BRANDED" types to get by-name checking. TYPE Apple = BRANDED REF INTEGER; TYPE Orange = BRANDED REF INTEGER;