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
COMPUTER SCIENCE 123 Foundations of Computer Science 9. List comprehensions Summary: This lecture introduces list comprehensions in Haskell. You should also have: Tutorial sheet 4 Solutions to Tutorial sheet 3 Lab sheet 5 Solutions to Lab sheet 4 Reference: Thompson Sections 5.5–6 © R.L. While, 2000–3 List comprehensions • Haskell provides a very concise syntax for specifying some sorts of more complex lists − e.g. the squares of the odd numbers up to 10 [k ^ 2 | k <- [1 .. 10], odd k] == [1, 9, 25, 49, 81] − • • • • “the list containing k^2 such that k is taken from the list [1 .. 10] and k is odd” The expressions after the vertical bar are called the qualifiers of the list Each qualifier is either − a generator (e.g. k <- [1 .. 10]), or − a test (e.g. odd k) The expression before the vertical bar specifies “what is done” with each element from the generator that passes the test So intuitively: − for each element from the generating list (i.e. [1 .. 10] ), − if it passes the test (i.e. if it is odd), its square is put on the result list, − but if it fails the test (i.e. if it is even), it doesn’t contribute to the result list cs123 Foundations of CS 1 9. List comprehensions Generators • • • The list from which the potential elements are drawn is called the generator The generator provides the elements that might contribute to the result list The order of the elements on the generating list determines the order of the elements on the result list − for example [2 * k | k <- [1 .. 5]] == [2, 4, 6, 8, 10] [2 * k | k <- [5, 4 .. 1]] == [10, 8, 6, 4, 2] [(k, '?') | k <- [11 .. 12]] == • • [(11, '?'), (12, '?')] The variable that ranges over the generating list (i.e. k in these two examples) is called the bound variable The expression on the left doesn’t have to use the bound variable (although it usually will) − for example replicate replicate :: Int -> a -> [a] -- replicate n x returns a list -- containing n x's replicate n x = [x | k <- [1 .. n]] cs123 Foundations of CS 2 9. List comprehensions Generators contd. • A list comprehension can have more than one generator [(x, y) | x <- [1 .. 4], y <- [1 .. 2]] == • • [(1, ,(2, ,(3, ,(4, 1), 1), 1), 1), (1, (2, (3, (4, 2) 2) 2) 2)] Notice the order of the pairs − the second generator varies faster than the first − set x to 1, and go through the whole of the second list − then set x to 2, and go through the second list again − etc The range of the second generator can depend on the first [(x, y) | x <- [1 .. 4], y <- [1 .. x]] == − [(1, ,(2, ,(3, ,(4, 1) 1), (2, 2) 1), (3, 2), (3, 3) 1), (4, 2), (4, 3), (4, 4)] or [(x, y) | x <- [1 .. 4], y <- [x .. 3]] == cs123 Foundations of CS [(1, 1), (1, 2), (1, 3) , (2, 2), (2, 3) , (3, 3)] 3 9. List comprehensions Tests • • A test can be any expression of type Bool Consider the function factors that takes a number n and gives us the factors of n factors :: Int -> [Int] -- factors n returns a list -- containing the factors of n factors n = [k | k <- [1 .. n], n `mod` k == 0] • Consider the function isPrime that takes a number n and tells us if n is prime − a number is prime if its only factors are 1 and itself isPrime :: Int -> Bool -- isPrime n returns True iff n is prime isPrime n = factors n == [1, n] • Consider the function primes that takes a number n and gives us the primes up to n primes :: Int -> [Int] -- primes n returns a list containing -- the primes up to n primes n = [k | k <- [0 .. n], isPrime k] • A list comprehension can have more than one test − an element must pass all tests in order to contribute to the result list cs123 Foundations of CS 4 9. List comprehensions Examples • Consider again the function multiples, this time written as a list comprehension multiples :: Int -> Int -> [Int] -- multiples x y returns a list containing -- natural numbers up to 100 that are -- multiples of both x and y multiples x y = [k | k <- [0 .. 100], k `mod` x == 0, k `mod` y == 0] − or equivalently multiples x y = [k | k <- [0 .. 100], k `mod` x == 0 && k `mod` y == 0] • Consider a function lettersOf that takes a string xs and gives us the letters from xs lettersOf :: String -> String -- lettersOf xs returns a list containing -- the letters from xs lettersOf xs = [x | x <- xs, isAlpha x] • Consider a function order that takes a string xs and gives us a string containing the elements from xs, but with all small letters preceding all capital letters − e.g. order "LabFourTest" = "abourestLFT" order :: String -> String -- pre: xs contains only letters -- order xs returns a string containing -- the elements of xs, with small letters -- preceding capital letters order xs = [x | x <- xs, isLower x] ++ [x | x <- xs, isUpper x] cs123 Foundations of CS 5 9. List comprehensions Examples • Consider a function alphaSquare that gives us a list of 5 strings each of length 5, collectively containing the first 25 letters of the lower-case alphabet alphaSquare :: [String] -- alphaSquare returns a list of 5 strings -- containing the first 25 letters of the -- lower-case alphabet alphaSquare = [[alphabet j | j <- [5 * i + 1 .. 5 * i + 5]] | i <- [0 .. 4]] − − • this is an example of a nested list comprehension this just means that the expression before the vertical bar is itself a list comprehension Consider a function pythag that takes a number n and gives us all right-angled triangles with integer sides and hypotenuse shorter than n type Triad == (Int, Int, Int) pythag :: Int -> [Triad] -- pythag n returns a list containing all -- right-angled triangles with integer -- sides and hypotenuse shorter than n pythag n = [(x, y, z) | x <- [1 .. n], y <- [x .. n], z <- [y .. n], x^2 + y^2 == z^2] − this is a very slow way of doing this: can you make it faster by changing the generators? cs123 Foundations of CS 6 9. List comprehensions “String ” functions • All of the String functions discussed in Lecture 5 actually work for all lists − !! (indexing), null, length, ++ (concatenation), \\ (difference), : (cons), reverse !! :: [a] -> Int -> a null :: [a] -> Bool length :: [a] -> Int ++ :: [a] -> [a] -> [a] \\ :: [a] -> [a] -> [a] : :: a -> [a] -> [a] reverse :: [a] -> [a] • The a in these types denotes any type − all of these functions work for lists containing elements of any type • they just re-arrange the elements of their argument(s) • they are polymorphic functions cs123 Foundations of CS 7 9. List comprehensions