Lists Adrian Groza Department of Computer Science Technical University of Cluj-Napoca
Recall... Parameter evaluation Call-by-value Call-by-name Call-by-need Functions Infix operators Local declarations, private functions Simultaneous declarations, converting iterative to functional programming
Operators precedence and associativity 2 ˆ3 ˆ2 sqrt 2 ˆ2 sqrt 2 ˆ2 == 2 not True 5 < 6 mod truncate 2.8 ˆ2 2 + 3 == 5 not 2 * 3 == 10 (1,2) < (1,4)
Operators precedence infixr 8 infixl 7 infix 7 infixl 6 infixr 5 infix 4 infixr 3 infixr 2 * / +, - : ==, /=, <, <=, >=, > & & exponentiation multiplication division addition, subtraction cons relational comparisons boolean AND boolean OR Note Function application of function names and argument expressions has higher precedence (10) than other operators. Thus the expression f x + y is the same as (f x) + y.
Outline 1 Polymorphism Polymorphic Types Polymorphic Equality 2 Lists Constructing Lists List Processing Matrices Composed Lists 3 Food for Thought
Polymorphic Types Polymorphism
Polymorphic Types Polymorphism Strong vs. Weak typing Strong (Pascal, Java) - provides safety. each value has a unique type Weak (Lisp, Prolog) - provides flexibility. Polymorphic types - try to get the best from both worlds by transferring a part of the reasoning regarding types to the system. Definition An object is polymorphic if it could be seen as having more than one type.
Polymorphic Types Polymorphism - Why should I care? Building robust systems One way to ensure that a robust system can deal with objects that have more complex methodologies than were originally intended is to have the object API be polymorphic.
Polymorphic Types Polymorphic types Example [1, 2, 3] [ a, b, c ] [[1, 2], [3, 4], [5, 6]] Note that [2, b ] is not a valid example. Polymorphic types describe families of types ( a)[a] is the family of types consisting of, for every type a, the type of lists of a. Type variables Identifiers such as a are called type variables. They are uncapitalised to distinguish them from specific types such as Int: predefined (a,b,c) or user defined (typevar psi epsilon tau)
Polymorphic Types Polymorphic functions length [1,2,3] length [ a, b, c ] length [[1],[2],[3]] Observation The length function is an example of a polymorphic function. It can be applied to a list containing elements of any type, for example [Integer], [Char], or [[Integer]]. length :: [a] -> Integer length [] = 0 length (x:xs) = 1 + length xs fun null [] = true null ( :: ) = false; val null = fn a list -> bool Definition A polymorphic function is a function that can be applied to objects of more than one data type.
Polymorphic Types Polymorphic Partial Functions Example head :: [a] -> a head (x:xs) = x tail :: [a] -> [a] tail (x:xs) = xs Remark Unlike length, these functions are not defined for all possible values of their argument. A runtime error occurs when these functions are applied to an empty list. (head xs) ++ (tail xs) for xs=[] Definition A partial function is a function which is not defined on its entire domain.
Polymorphic Types Type Inference Definition An expression is well-typed if the type checker is able to identify consistent type substitutions for all existing type variables. Example fun facti (n,p) = if n = 0 then p else facti (n-1, n*p); 1 is int n-1 is int n is int n*p multiplication over integers p is int val facti = fn int * int -> int If the type inference lets some types unrestricted the
Polymorphic Types Projection Functions fun firstfirst z =first (first z) ; (0) Projection functions return val firstfirst =fn: ( m * n) * b -> m (9) the component of a tuple. firstfirst ((2,3),4); -> 2 fun first (x,y) = x; Type Inference: val first =fn: a * b -> a val first = fn: a * b -> a (1) fun second (x,y) = y; (1) (0) z= a * b (3) val second =fn: a * b -> b (1) (3) first a (4) first ( one,2); (4) (1) a = ( m * n) (5) one: string (3) (5) z = ( m * n) * b (6) second ( one,2); (6) (1) first z returns ( m * n) (7) 2: int (7) (1) first ( m * n) returns m (8) (6) (8) (9) A polymorphic function can have different types within a single expression. first = fn: ( m * n) * b -> m * n first = fn: ( m * n) -> m
Polymorphic Equality Polymorphic equality Polymorphic functions don t need the equality predicate: length need equality predicate: member Example (Length) length [] = 0 length (x:xs) = 1 + length xs Example (Member) fun memb (x, []) = false memb (x, (y::ys)) = (x = y) orelse memb(x,ys); val memb = fn: a * a list -> bool
Polymorphic Equality Polymorphic equality Definition An equality type is a type endowed with an equality predicate. It is represented by equality type variables, denoted α =, β =... Examples Hugs :type (==) (==) :: Eq a => a -> a -> Bool PolyML op =; val it = fn : a * a -> bool
Outline 1 Polymorphism Polymorphic Types Polymorphic Equality 2 Lists Constructing Lists List Processing Matrices Composed Lists 3 Food for Thought
Constructing Lists Lists, lists, lists 1 (Irlanda de Nord, 17) 2 (Romania, 16) 3 (Ungaria,13) 4 (Finlanda, 10) 5 (InsuleleFeroe, 6) 6 (Grecia, 3)
Constructing Lists List Definition Example [1, 2, 3] [ Fr, Be, Bo, Ro, L ] [] [[1, 2], [3, 4, 5]] [(1, one ), (2, two )] Definition A list is a sequence of values of a specific type. A list is either empty, or is an ordered pair made of an element ( head ) and a list ( tail ). Observation It shows the connection between data and control.
Constructing Lists Expressions in Lists As with tuples we can put expressions into lists: Example Hugs [not False] [True] :: [Bool] Hugs [7-3, True then 1 else 2] [4, 1] :: [Integer]
Constructing Lists Operations on Lists Example Hugs head [1,2,3,4] 1:: Integer Hugs tail [1,2,3,4] [2, 3, 4] Hugs abcde!!3 d :: Char Hugs [4,5] ++ [ ] ++ [8,9] [4, 5, 8, 9] :: [Integer] Evaluate the following expresions: head bull : tail cat [null (tail [1]), head [null []]]
Constructing Lists Constructors Example Haskel operator : (right associative) Hugs 1:2:3:[] [1, 2, 3] ML operator :: (right associative) PolyML 1::2::3::[]; Note val it = [1, 2, 3] : int list Hugs [ a, n, a ] ana ::[Char] Hugs a : n : a :[] ana ::[Char]
Constructing Lists List Building Quiz: What does this function do? Example fun i(m,n) = if m > n then [] else m::i(m+1,n); PolyML i(3,8);
Constructing Lists Pattern Matching Pattern (x:xs) (1:xs) (1:xs) (x: : :y) Parameter [1, 2, 3] [1, 2, 3] [2, 3] [1, 2, 3, 4, 5] Bindings x=1, xs=[2, 3] xs=[2, 3] Fail x=1, y=[4, 5] val (a,b) = (5,6); val (c,d) = (2,( xx, y )); val (e, (f,g)) = (1, (2,3)); val (l, m, n) = ( xx, (1,2)); (x:y) = [1,2] (x:y) = [[1,2]] (x:y) = [ olemiss ] (x:y) = olemiss (x: : :y) = [1,2,3,4,5,6]
List Processing List Processing With Patterns Example fun prodl [] = 1 prodl (n::ns) = n * prodl ns; val prodl = fn: int list -> int PolyML prodl [5,6,7,8]; 1680 : int Example fun prodl ns = if null ns then 1 else hd ns * prod (tl ns); Observation Using patterns increases code clarity and allows a better analysis of cases, thus leading to a better performance of the generated code.
List Processing Partial Functions and Pattern Matching Example fun maxl [x] = x maxl (x::y::ys) = if x>y then maxl(x::ys) else maxl(y::ys); Warning: Matches are not exhaustive. Found near fun maxl([x]) = x maxl(...) = if... then...(...) else...(...) val maxl = fn : int list -> int Definition A partial function is a function which is not defined on its entire domain.
List Processing Partial Polymorphic Functions fun hd(x:: ) = x; Warning: Matches are not exhaustive. val hd = fn : a list -> a PolyML hd [1, 2, 3]; 1 : int PolyML tl [1, 2, 3]; [2, 3] : int list fun tl( ::xs) = xs; ***Warning: Patterns not exhaustive PolyML tl [ unu, doi, trei ]; [ doi, trei ] : string list PolyML hd [[[1, 2], [3]], [[4]]]]; [[1, 2], [3]] : (int list) list
List Processing List Processing Example (Take first n elements of a list) take 0 = [] take k [] = [] take k (xs:xs) = x : take (k-1) xs Example (Drop first n elements of a list) drop 0 xs = xs drop k [] = [] drop k (x:xs) = drop (k-1) xs (drop n xs)! m == xs! (n + m)
List Processing List Processing Example (Append of two lists) infixr 3 +++ [] +++ ys = ys (x:xs) +++ ys = x: (xs +++ ys) Example [1,2,3] +++ [4,5] = 1: ([2,3] +++ [4,5]) = 1: (2: ([3] +++ [4,5])) = 1: (2: (3: ([] +++ [4,5]))) = 1: (2: (3: [4,5])) Which of the following equations are true and which are false? 1. [[ ]] +++ xs = xs 2. [[ ]] +++ xs = [xs] 3. [[ ]] +++ xs = [[],xs]
List Processing List Processing Example (Reversing a list) invers [] = [] invers (x:xs) = invers xs ++ [x] invers [1,2,3] = invers [2,3] ++ [1] = invers [3] ++ [2] ++ [1] = invers [] ++ [3] ++ [2] ++ [1] = [] ++ [3] ++ [2] ++ [1] = [3] ++ [2] ++ [1] = [3,2] ++ [1] = [3,2,1] inver xs = inv xs [] where inv [] ys = ys inv (x:xs) ys = inv xs (x:ys) inver [1,2,3] = inv [1,2,3] [] = inv [2,3] 1:[] = inv [3] 2:[1] = inv [] 3:[2,1] = inv [] [3,2,1] = [3,2,1]
List Processing Big Integers type Bignumber = [Int] prod :: Bignumber -> Int -> Bignumber Hugs prod [1, 2, 3] 4 [2, 9, 4] prod m i = prod1 m 0 where prod1 [] 0 = [] prod1 [] c = (c mod 10): prod1 [] (c div 10) prod1 (d:n) c = let k = d * i + c in (k mod 10) : prod1 n (k div 10) Example fact 0 = [1] fact n = prod (fact (n - 1)) n Hugs fact 20 [0, 0, 0, 0, 4, 6, 6, 7, 1, 8, 0, 0, 2, 0, 9, 2, 3, 4, 2]
Matrices Operations with Matrices val mat =[[ x, y, z ], [ u, v, w ]]; val mat [[ x, y, z ], [ u, v, w ]] : string list list fun col [] = [] col ((x:: )::linii) = x::col linii; val col = fn: a list list -> a list fun restcol [] = [] restcol (( ::xs)::linii) = xs::restcol linii; val restcol = fn: a list list -> a list list fun transp ([]::linii) = [] transp linii = col linii:: transp(restcol linii); val trans = fn: a list list -> a list list
Composed Lists Quiz Which is the signature and what does this function compute? Example fun f [] = [] f (x::xs) = x @ f xs;
Composed Lists Flattening Lists fun flatten [] = [] flatten (x::xs) = x @ flatten xs; val flatten = fn a list list -> a list PolyML flatten [[ brain, sourgeons ], [ never, say ],[ ooops ]]; [ brain, sourgeons, never, say, ooops ] : string list
Outline 1 Polymorphism Polymorphic Types Polymorphic Equality 2 Lists Constructing Lists List Processing Matrices Composed Lists 3 Food for Thought
Readings Reading Chapter 3 from Ioan Alfred Letia, Programare Functionala