Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
This session Composite Datatypes — Lists and Tuples After this session, you should be able to handle composite data types in Haskell COM1022 Functional Programming Techniques defining the types defining functions on the types using standard Prelude functions Professor Steve Schneider Reference: Thompson, Chapter 5 University of Surrey Autumn 2009 Week 11 [based on slides by Dr Hans Georg Schaathun] Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 1 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Introduction Autumn 2009 Week 11 3 / 42 Introduction Shopping basket Tuples versus Lists as an example The items are tuples: (String, Int) A basket contains many items Fixed number of entries (2) Combining different data types (String and Int) Each item comprises a description and a quantity Sample items: The basket is a list: [ (String, Int) ] ( "Salt (1lb)", 3 ) ( "Sugar (1kg)", 5 ) Variable number of items Same data type for elements of the list: (String,Int) Sample Shopping Basket: Any data type can be used to define tuples and strings [( "Salt (1lb)", 3 ), ( "Sugar (1kg)", 5 ), ( "Orange", 12 ) ] Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 4 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 5 / 42 Introduction Tuples Defining data types Other tuples Tuples can have any number of items We can define our own data types: type Item = (String,Float,String) e.g. ("Oranges",3.5,"lbs") type Item = (String,Int) type Basket = [Item] ... or This establishes synonyms for common data types type Item = (String,String,Int,String,String) e.g. ("COM1022", "Functional Programming", 20, "HGS", "http://www.computing.surrey.ac.uk/teaching /current/com1022/") synonyms makes code more intuitive and readable can be used interchangably (when readability is not an issue) All type identifiers have to start with a Capital The built-in type String is defined as type String = [Char] i.e. a String is a special case of lists Professor Steve Schneider Uses of tuples Composite Datatypes — Lists and Tuples Tuples Autumn 2009 Week 11 6 / 42 Professor Steve Schneider Uses of tuples Composite Datatypes — Lists and Tuples Tuples Why do we use tuples? Autumn 2009 Week 11 8 / 42 Functions over tuples Pattern matching A known example Related information should be bundled together For instance, a data base factorial 0 = 1 factorial n = factorial (n-1) Person needs: name, address, date of birth etc. Library book needs: title, author, shelfmark, ISBN, etc. Several function definitions Represent each person/book by a tuple Different patterns for the arguments one variable identifies one person/book each piece of information is one component of the tuple Haskell will use the first applicable pattern Every person/book has the same components 1 2 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 9 / 42 0 is a literal, and matches only a numerical 0. n is an identifier and matches any value Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 11 / 42 Tuples Functions over tuples Tuples Tuple patterns Functions over tuples Selector functions an example Introducing tuples, more complex patterns become possible itemType :: Item -> String itemType (x,_) = x itemType is a selector function (x,_) matches any pair extracts one of several items x matches the first item _ matches anything but no identifier is assigned selector functions are often needed built-in selector functions fst (x,_) = x snd (_,y) = y quantity :: Item -> Int quantity (_,x) = x Doubling the quantity: double :: Item -> Item double (x,y) = (x, 2*y) Professor Steve Schneider Composite Datatypes — Lists and Tuples Tuples Autumn 2009 Week 11 12 / 42 Composite Datatypes — Lists and Tuples Functions over tuples Lists Pattern matching for readibility Autumn 2009 Week 11 13 / 42 The power of lists The generality of lists For every type t there is a list type [t] Consider a function adding the components of a pair addPair :: Professor Steve Schneider Lists of Float: [Float] Lists of lists of Float: [[Float]] Lists of tuples: [(Float,[Float],Int)] Lists of functions: [ Int -> Int] Lists of functions on lists: [ [Int] -> Float ] (Int,Int) -> Int Selector functions can solve the problem addPair p = fst p + snd p Pattern matching tends to make it more readable There is no limit addPair (x,y) = x + y But each list type has one specific constituent type Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 14 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 16 / 42 Lists The power of lists Lists The strength of functional programming List comprehension Systematic definition of large lists Large lists can be defined systematically similar to normal mathematical set notation Lists are at the heart of functional programming For instance The strength is in the flexible functions possible on lists ... that is ... [1..9] = [1,2,3,4,5,6,7,8,9] [2*x | x<-[1..8] ] = [2,4,6,8,10,12,14,16] polymorphism – to be explored later in this session higher-order functions – later in the course The latter example is known as list comprehension In maths notation it looks like {1 . . . 9} {2x|x ∈ {1 . . . 8}} Professor Steve Schneider Composite Datatypes — Lists and Tuples Lists Autumn 2009 Week 11 17 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples List comprehension Lists List comprehension Autumn 2009 Week 11 19 / 42 List comprehension Multiple generators Sometimes more than one generator is used suits = [ "Spades", "Hearts", "Diamonds", "Clubs" ] honours = [ "Ace", "King", "Queen", "Knave" ] goodCards = [ (x,y) | x <- suits, y <- honours ] ex = [1..8] [2*x | x<-ex] List comprehension generates a list based on another list the variable x is called a generator What does goodCards evaluate to? The general form is [expression | condition] expression is evaluated for every value of the generator(s) where the generator(s) have to satisfy the condition Main> goodCards [("Spades","Ace"),("Spades","King"),("Spades","Queen"), ("Spades","Knave"), ("Hearts","Ace"),("Hearts","King"), ("Hearts","Queen"),("Hearts","Knave"),("Diamonds","Ace"), ("Diamonds","King"),("Diamonds","Queen"),("Diamonds","Knave"), ("Clubs","Ace"),("Clubs","King"), ("Clubs","Queen"), ("Clubs","Knave")] The simplest condition x ∈ ex (x<-ex) Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 20 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 21 / 42 Lists List comprehension Lists Complex conditions List comprehension New Scientist Enigma 1574 (5 December 2009) Doubly square dates. 4 April 2001 was the first doubly square date of the century because whether written in the order day.month.year or month.day.year (in each instance with two digits in each element) it comes out as 04.04.01, and 40401 = 2012 . Suppose we have a function isEven n = (n ‘mod‘ 2 == 0) which is True if and only if n is even ex = [2,5,8,12] [ 2*n | n <- ex, isEven n, n > 3 ] Still with two digits for each element, there are some doubly square dates for which the square that comes from the order day.month.year is not the same as the square that comes from the order month.day.year. This is the case for each of the next two doubly square dates after 4 April 2001. What are those two dates? now only even ns larger than 3 are used the result is [16,24] Professor Steve Schneider Composite Datatypes — Lists and Tuples Lists Autumn 2009 Week 11 22 / 42 Professor Steve Schneider List comprehension Composite Datatypes — Lists and Tuples Lists Doubly square dates Autumn 2009 Week 11 23 / 42 List comprehension Pythagoras dsdates :: [(Int,Int,Int)] Pythagorean triads: integer sides of a right angled triangle. dsdates = [(x,y,z) | z <- [1..99], y <- [1..12], x <- [1..31], dsquare (x,y,z)] triads :: Int -> [(Int,Int,Int)] triads n = [(x,y,z) | z <y <x <(x*x dsquare :: (Int,Int,Int) -> Bool [1..n], [1..z-1], [1..y-1], + y*y == z*z)] dsquare (x,y,z) = (square (10000*x + 100*y + z)) && (square (10000*y + 100*x + z)) square ... Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 24 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 25 / 42 Lists List comprehension Lists Conditions with pattern matching Functions on lists List patterns Simple patterns Normal rules for pattern matching apply in list comprehension Pattern matching applies to lists as to tuples For instance ltest [0,a] = a ltest [0,a,b] = a + b ltest [a,_] = a addPairs :: [(Int,Int)] -> [Int] addPairs pl = [ x+y | (x,y) <- pl ] addPairs [ (2,3), (2,5), (3,1) ] [ 2+3, 2+5, 3+1 ] = [5,7,4] Professor Steve Schneider Composite Datatypes — Lists and Tuples Lists ... but such patterns dictate the list length Autumn 2009 Week 11 26 / 42 Professor Steve Schneider Functions on lists Composite Datatypes — Lists and Tuples Lists List patterns Autumn 2009 Week 11 28 / 42 Autumn 2009 Week 11 30 / 42 Functions on lists Maximum Simple patterns The list constructor : can be used for patterns x:xs Maximum x is one element (the first) xs is the rest of the list maxm maxm maxm | | Note that xs is one element shorter than x:xs this is the basis for simple recursion For instance, return the first non-zero element :: [Int] -> Int [x] = x (x:xs) x > maxm xs = x otherwise = maxm xs ltest (0:xs) = ltest xs ltest (x:xs) = x Is there a bug in the ltest code above? Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 29 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Lists Functions on lists Lists Functions on lists Remove duplicates from a list I Remove duplicates from a list II Remove an element from a list: a recursive definition Remove duplicates from a list: a recursive definition remove :: Int -> [Int] -> [Int] remdups :: [Int] -> [Int] remove n [] = [] remdups [] = [] remove n (x:xs) | n == x = remove n xs | otherwise = x:(remove n xs) remdups (x:xs) = x:(remdups (remove x xs)) Professor Steve Schneider Composite Datatypes — Lists and Tuples Lists The recursive case: retain the first element x of the list, remove further occurrences of x from the rest of the list, and apply remdups to it. Autumn 2009 Week 11 31 / 42 Functions on lists [Int] -> [Int] e.g. sort [3,6,2,8,5] = [2,3,5,6,8] Recursion: if we can sort lists of length less than n, how can we sort lists of length n? Seeing a way to do this will be the basis for a recursive definition. Base case: sort [x] = [x] Recursive case: sort (x:y:xs) = ??? ...assume we can already do sort (y:xs) and that we have z:zs = sort (y:xs) Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 32 / 42 Polymorphism Polymorphism Given a list of integers, how do we rearrange that list so it includes the same elements but sorted in order? Professor Steve Schneider Composite Datatypes — Lists and Tuples Polymorphism Challenge: Sorting a list sort :: Professor Steve Schneider Autumn 2009 Week 11 polymporphism ∼ «has many shapes» Polymorphic functions apply to different types of data For instance the length of a list length :: [a] -> Int where a is a type variable i.e. a matches any type Or concatenation (++) :: [a] -> [a] -> [a] a is an arbitrary type but all three instances of a are the same type Polymorphism saves us the trouble of typing several similar definitions 33 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 35 / 42 Polymorphism Polymorphism Polymorphism For example Polymorphism Polymorphism versus Overloading Polymorphism and Overloading both allow The length function could be defined as same function name on different types length :: [a] -> Int length [] = 0 length (x:xs) = 1 + length xs However, there is a key difference Polymorphism has a single function definition applicable to several types Overloading allows different definitions This is an example of recursion over lists Professor Steve Schneider Composite Datatypes — Lists and Tuples for different types Autumn 2009 Week 11 36 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Strings Autumn 2009 Week 11 37 / 42 Strings Strings Special Characters A special case of lists String is a synonum for [Char] All polymorphic list functions apply to strings Special characters represented by escape sequences Newline \n Tab \t Quotes (\" — \’) Backslash \\ map, foldr, ++ Main> [ ’a’, ’b’, ’c’ ] "abc" Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 38 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 39 / 42 Strings Conclusion Printing Special characters Summary Summary Hugs displays the escape sequences Not the special characters Main> "Item\tQuantity\nApples\t4\nOranges\t12\n" "Item\tQuantity\nApples\t4\nOranges\t12\n" Much of the power of functional languages is the list capabilities Simple expressions to define lists List comprehension An I/O function is needed to get the proper display Pattern matching This is the putStr function Main> putStr "Item\tQuantity\nApples\t4\nOranges\t12\n" Item Quantity Apples 4 Oranges 12 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 40 / 42 Professor Steve Schneider Composite Datatypes — Lists and Tuples Autumn 2009 Week 11 42 / 42