2 Values and Types
Total Page:16
File Type:pdf, Size:1020Kb
2 Values and Types . Types of values. Primitive, composite, recursive types. Type systems: static vs dynamic typing, type completeness. Expressions. Implementation notes. © 2004, D.A. Watt, University of Glasgow / C. Huizing TU/e 1 1 Types (1) . Values are grouped into types according to the operations that may be performed on them. Different PLs support different types of values (according to their intended application areas): • Ada: booleans, characters, enumerands, integers, real numbers, records, arrays, discriminated records, objects (tagged records), strings, pointers to data, pointers to procedures. • C: enumerands, integers, real numbers, structures, arrays, unions, pointers to variables, pointers to functions. • Java: booleans, integers, real numbers, arrays, objects. • Haskell: booleans, characters, integers, real numbers, tuples, disjoint unions, lists, recursive types. 2 2 Types (2) . Roughly speaking, a type is a set of values: • v is a value of type T if v ∈ T. E is an expression of type T if E is guaranteed to yield a value of type T. But only certain sets of values are types: • {false, true} is a type, since the operations not, and, and or operate uniformly over the values false and true. • {…, –2, –1, 0, +1, +2, …} is a type, since operations such as addition and multiplication operate uniformly over all these values. • {13, true, Monday} is not considered to be a type, since there are no useful operations over this set of values. 3 3 Types (3) . More precisely, a type is a set of values, equipped with one or more operations that can be applied uniformly to all these values. The cardinality of a type T, written #T, is the number of values of type T. 4 4 Primitive types . A primitive value is one that cannot be decomposed into simpler values. A primitive type is one whose values are primitive. Every PL provides built-in primitive types. Some PLs also allow programs to define new primitive types. 5 5 Built-in primitive types (1) . Typical built-in primitive types: Boolean = {false, true} PL- or implementation- # Character# = {…, ‘A’, …, ‘Z’,defined set of characters ## …, ‘0’, …, ‘9’, (ASCII, ISO-Latin, or ## …} Unicode) PL- or implementation- # Integer# = {…, –2, –1, defined set of whole ## 0, +1, +2, …} numbers PL- or implementation- # Float# = {…, –1.0, …, defined set of real ## 0.0, +1.0, …} numbers . Names of types vary from one PL to another: not significant. 6 6 Built-in primitive types (2) . Cardinalities: " #Boolean" = 2 " #Character" = 128 (ASCII), 256 (ISO-Latin), or 32768 (Unicode) # #Integer# = max integer – min integer + 1 . Note: In some PLs (such as C), booleans and characters are just small integers. Infinite cardinalities do exist (Integer in Mathematica, e.g.) 7 7 Defined primitive types . In Ada we can define new numeric types. In Ada and C we can define new enumeration types simply by enumerating their values (called enumerands). Java 1.5 has them also: public enum Jam {apricot, blueberry, codfish } 8 8 Example: Ada numerics . Type declaration: type Population is range 0 .. 1e10; . Set of values: # Population = {0, 1, …, 1010} . Cardinality: " #Population = 1010+1 9 9 Example: Ada enumerations . Type declaration: type Color is (red, green, blue); . Set of values: " Color = {red, green, blue} . Cardinality: " #Color = 3 10 10 Composite types . A composite value is one that is composed from simpler values. A composite type is a type whose values are composite. PLs support a huge variety of composite types. All these can be understood in terms of a few concepts: • Cartesian products (tuples, structures, records) • mappings (arrays) • disjoint unions (algebraic data types, discriminated records, objects) 11 • recursive types (lists, trees, etc.) ! 11 Cartesian products (1) . In a Cartesian product, values of several types are grouped into tuples. Let (x, y) stand for the pair whose first component is x and whose second component is y. Let S × T stand for the set of all pairs (x, y) such that x is chosen from set S and y is chosen from set T: # S × T = { (x, y) | x ∈ S; y ∈ T } hence the “×” notation . Cardinality: 12 # #(S × T) = #S × #T 12 Cartesian products (2) . We can generalise from pairs to tuples. Let S1 × S2 × … × Sn stand for the set of all n-tuples such that the ith component is chosen from Si: # S1 × S2 × … × Sn = { (x1, x2, …, xn) | x1 ∈ S1; x2 ∈ S2; …; xn ∈ Sn } . Basic operations on tuples: • construction of a tuple from its component values • selection of an explicitly-designated component of a tuple. so we can select the 1st or 2nd (but not the ith, if i is not fixed) component 13 • Records (Ada), structures (C), and tuples (Haskell) can all be understood in terms of Cartesian products 13 Example: Ada records (1) . Type declarations: type Month is (jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec); type Day_Number is range 1 .. 31; type Date is record m: Month; d: Day_Number; end record; . Application code: " someday: Date := (jan, 1); record … construction put(someday.m+1); put("/"); component put(someday.d); 14 someday.d := 29; someday.m := selectionfeb; 14 Example: Ada records (2) . Set of values: # Date = Month × Day-Number = {jan, feb, …, dec} × {1, …, 31} # viz:# (jan, 1)# (jan, 2)# …# (jan, 30)# (jan, 31) #(feb, 1)(# feb, 2)# …#(feb, 30)(# feb, 31) NB #…# …# …# …# … #(dec, 1)(# dec, 2)# …#(dec, 30)(# dec, 31) . Cardinality: # #Date = #Month × #Day-Number = 12 × 31 = 372 15 15 Example: Haskell tuples . Declarations: data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec type Date = (Month, Int) . Set of values: # Date# = Month × Integer ## = {Jan, Feb, …, Dec} × {…, –1, 0, 1, 2, …} . Application code: tuple " construction someday = (jan, 1) component m, d = someday anotherday = (m + 1, d) selection (by pattern matching) 16 16 Mappings (1) . We write m : S → T to state that m is a mapping from set S to set T. In other words, m maps every value in S to some value in T. If m maps value x to value y, we write y = m(x). The value y is called the image of x under m. Some of the mappings in {u, v} → {a, b, c}: # m1 = {u → a, v → c} # m = {u → c, v → c} 2 image of u is # m3 = {u → c, v → b} c, image of v is b 17 17 Mappings (2) . Let S → T stand for the set of all mappings from S to T: # S → T = { m | x ∈ S ⇒ m(x) ∈ T } . What is the cardinality of S → T? " There are #S values in S. # Each value in S has #T possible images under a mapping in S → T. #S copies of #T multiplied # So there are #T × #T × … × #togetherT possible mappings. For example,Thus: in {u, v} → {a, b, c} #S there #are#( S3 →2 = T )9 =possible (#T) mappings. 18 18 Arrays (1) . Arrays (found in all imperative and OO PLs) can be understood as mappings. If an array’s components are of type T and its index values are of type S, the array has one component of type T for each value in type S. Thus the array’s type is S → T. An array’s length is the number of components, #S. Basic operations on arrays: so we can select the ith construction of an array from its components • component • indexing – using a computed index value to select a 19 component. 19 Arrays (2) . An array of type S → T is a finite mapping. Here S is nearly always a finite range of consecutive values {l, l+1, …, u}. This is called the array’s index rangelower . upper .bound In C and Java, boundthe index range must be {0, 1, …, n–1}. In Ada, the index range may be any primitive (sub)type other than Float. We can generalise to n-dimensional arrays. If an array has index ranges of types S1, …, Sn, the array’s type is S1 × … × Sn → T. 20 20 Example: Ada arrays (1) . Type declarations: type Color is (red, green, blue); type Pixel is array (Color) of Boolean; . Application code: " p: Pixel := (true, false, true); c: Color; array … construction p(c) := not p(c); indexin indexin g g 21 21 Example: Ada arrays (2) . Set of values: # Pixel = Color → Boolean = {red, green, blue} → {false, true} # viz:# {red → false,# green → false,# blue → false} #{red → false,# green → false,# blue → true} #{red → false,# green → true,# blue → false} #{red → false,# green → true,# blue → true} #{red → true,# green → false,# blue → false} #{red → true,# green → false,# blue → true} #{red → true,# green → true,# blue → false} #{red → true,# green → true,# blue → true} . Cardinality: 22 " #Pixel = (#Boolean)#Color = 23 = 8 22 Example: Ada 2-dimensional arrays . Type declarations: type Xrange is range 0 .. 511; type Yrange is range 0 .. 255; type Window is array (YRange, XRange) of Pixel; . Set of values: # Window# = Yrange × Xrange → Pixel ## # = {0, 1, …, 255} × {0, 1, …, 511} → Pixel . Cardinality: # #Window = (#Pixel)#Yrange × #Xrange = 8256 × 512 23 23 2-dimensional arrays in C, Java . achieved by means of nested arrays Pixel[][] . note that the following sets are isomorphic: • Yrange × Xrange → Pixel • Yrange → ( Xrange → Pixel ) . transformation from one to the other is called Currying 24 24 Functions as mappings . Functions (found in all PLs) can also be understood as mappings. A function maps its argument(s) to its result. If a function has a single argument of type S and its result is of type T, the function’s type is S → T. Basic operations on functions: • construction (or definition) of a function • application – calling the function with a computed argument. We can generalise to functions with n 25 arguments. If a function has arguments of 25 types S1, …, Sn and its result type is T, the function’s type is S1 × … × Sn → T.