Download List comprehensions

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

History of the function concept wikipedia , lookup

List of prime numbers wikipedia , lookup

Proofs of Fermat's little theorem wikipedia , lookup

Vincent's theorem wikipedia , lookup

Transcript
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