overloading and polymorphism ... see Miranda notes
A : array(1 .. 10) of BOOLEAN; B : array(1 .. 10) of BOOLEAN; C, D : array(1 .. 10) of BOOLEAN;Ada defines A and B as of different types, but C and D are both of the same type. Here's another example, with some type declarations:
type VEC is array(1 .. 10) of INTEGER; type VEC2 is array(1 .. 10) of INTEGER; A : VEC; B, C : VEC; D : VEC2; type PERSON is record NAME : STRING(1 .. 120); POUNDS : INTEGER; end record; type ENGLISH_ACCOUNT_PAYABLE is record NAME : STRING(1 .. 120); POUNDS : INTEGER; end record; subtype SMALL_INT is INTEGER range -10 .. 10; I : INTEGER; J : SMALL_INT;Here A, B, and C are all of the same type; D is of a different type. PERSON and ENGLISH_ACCOUNT_PAYABLE are different types. This is all consistent with pure name equivalence. I and J are both integers. (In pure name equivalence they would be different -- this is the "modified" part.)
The structural equvalence rule in its pure form would say that A, B, C, and D are all of the same type, and PERSON and ENGLISH_ACCOUNT_PAYABLE are the same type. Algol-68 is an example of a language that uses structural equivalence. This kind of structural equivalence has pretty much fallen out of favor though.
C would say that A, B, C, and D are all of the same type, and PERSON and ENGLISH_ACCOUNT_PAYABLE are different types. C uses structural equivalence, except for records (structs).
Variant records -- are they done in a type safe way? Pascal: no. Ada: yes. In Ada, a variant record must have a discriminant that lets the compiler distinguish between the cases; the discriminant must be set at the same time as the variant fields.
type DEVICE is (PRINTER, FLOPPY, HARD_DISK); type STATE is (UP, DOWN); type PERIPHERAL(UNIT : DEVICE := PRINTER) is record STATUS: STATE; case UNIT is when PRINTER => PAGE_LENGTH : FLOAT; when others => MEGABYTES : INTEGER; end case; end record; P : PERIPHERAL; P := (UNIT => FLOPPY, MEGABYTES => 2); -- not allowed: P.unit := printer;