Lab 5 Patterns for List Processing CIS 252 C Introduction to
Document Sample


Lab 5: Patterns for List Processing CIS 252 C Introduction to Computer Science
Overview. This lab gives you some practice with some common idioms for binding of the function arguments to the pattern (x:xs)—play the role of the
list processing. These idioms—mapping, filtering, and folding—are so common generator x <- lst.
that Haskell (and most other functional programming languages) includes spe- As another example, consider the following function (make sure you understand
cial functions that encapsulate them. We’ll cover those functions in class soon, what it does by trying it out on some test data):
but they are not the focus of this lab.
This lab covers material discussed in §7.4 and §9.1 of Thompson. addPairs :: [(Int,Int)] -> [[Int]]
addPairs pairList = [[m+n] | (m,n) <- pairList]
§1. Mapping (Applying to All)
Here is a version of addPairs written using explicit recursion:
Last week’s lab focused on list comprehensions which provide a mechanism for
defining new lists out of old lists. For example, the following function accepts a addPairs [] = []
list of integers and doubles all of the elements in it: addPairs ((m,n):rest) = [m+n] : addPairs rest
doubleAll :: [Int] -> [Int] Once again, notice that the recursive definition uses exactly the same transfor-
doubleAll lst = [ 2*x | x <- lst] mation as the list-comprehension version, and tacks (using the : operator) the
first-element result onto the result of the recursive call.
This comprehension includes a generator x <- lst and a transformation 2*x. Note: Occasionally, you may find that you need to put parentheses around
Because the comprehension doesn’t include any tests to filter out elements, the the transformation portion of the recursive definition, due to operator prece-
resulting list will always contain the same number of elements as the initial list. dence. For example, a:b:list gets interpretted as a:(b:list); if you mean
Thus, for example, doubleAll [1,3,5,7,10] will return a five-element list. (a:b):list, you must include the parentheses.
Here is a version of doubleAll written using explicit recursion: Finally, sometimes you’ll need to pass around an extra argument, if the func-
tion itself takes more than one argument. For example, consider the following
doubleAll [] = [] generalization of doubleAll:
doubleAll (x:xs) = 2*x : doubleAll xs
multAll :: Int -> [Int] -> [Int]
The equation for the empty list is straightforward: doubling every element of multAll m lst = [ m*x | x <- lst]
an empty list should result in another empty list. The second equation handles
nonempty lists and is explicit about how the new list is generated: we transform The explicit-recursion version of this function must pass around the arguent m on
the head of the list using the same transformation as in the list comprehension each call:
(2*x), and we tack it on to the front of the list obtained by transforming the rest
of the list (via the recursive call). Each recursive call has the effect of generat- multAll m [] = []
ing the next element to be operated on; thus the recursive calls—along with the multAll m (x:xs) = m*x : multAll m xs
Page 1 January 25, 2008
Lab 5: Patterns for List Processing CIS 252 C Introduction to Computer Science
§2. Filtering (Element Selection) §3. Folding (Combining Results)
We’ve seen in list comprehensions how one can filter out some of the elements The list-comprehension notation is useful for converting lists into new lists, but
of the original list via adding tests to the list comprehension. For example, the it doesn’t provide a way to convert information in lists to a nonlist form. For
following function accepts a list of integers and doubles all the elements in it that example, a list comprehension won’t help in summing the elements of a list or in
are less than 10 (it drops the rest): finding the maximum element in the list.
However, the same type of pattern we’ve seen in the explicit-recursion functions
doubleSome :: [Int] -> [Int]
above can be used in this type of situation. The basic idea is that we can operate
doubleSome lst = [ 2*x | x <- lst, x < 10]
on individual elements of a list and combine that answer with the result obtained
Here is a version of doubleSome written using explicit recursion: by a recursive call.
For example, consider the following function, which sums up the elements of a
doubleSome [] = [] list of integers:
doubleSome (x:xs)
| x < 10 = 2*x : doubleSome xs sumUp :: [Int] -> Int
| otherwise = doubleSome xs sumUp [] = 0
sumUp (x:xs) = x + sumUp xs
This function is similar to the recursive definition of doubleAll, except that we
don’t always tack on the element 2*x. Instead, we only tack on those elements
Note that this definition has a similar form to what we’ve seen already, except
2*x for which the test x < 10 is satisfied. Recursive calls still provide the mech-
that it uses the operator + to combine the results, rather than the operator :. The
anism for “marching down” the list; at each point, we look at the first element of
other difference is that it no longer makes sense to return the empty list in the
the list to determine whether to include its transformation in the final result.
first equation, because sumUp needs to return an integer.
Similarly, in Lab 4 we saw the function:
You can also perform transformations on the individual elements of the list being
sampleFun :: [(Int,Int)] -> [[Int]] processed. For example, the following function sums the squares of the elements
sampleFun pairList = [[m+n] | (m,n) <- pairList, n == 2*m] of a list:
Here is a version of sampleFun written using explicit recursion: sumSquares :: [Int] -> Int
sumSquares [] = 0
sampleFun [] = [] sumSquares (x:xs) = x*x + sumSquares xs
sampleFun ((m,n):rest)
| n == 2*m = [m+n] : sampleFun rest Finally, the following function concatenates all of the elements of a list of lists,
| otherwise = sampleFun rest to form a single list:
Page 2 January 25, 2008
Lab 5: Patterns for List Processing CIS 252 C Introduction to Computer Science
cat :: [[a]] -> [a] getShorty :: Int -> [[a]] -> [([a],Int)]
cat [] = []
cat (x:xs) = x ++ cat xs such that (getShorty n ls) returns a list of pairs, containing exactly
those elements in ls with length less than n, paired with their length. For
For example, see what the value of cat [[1,2],[3,4],[],[6,7,8]] is. example,
Here, the built-in append operator (++) is used to combine the results. Even
getShorty 4 [[1..5],[17],[8,100],[],[4,6,7,9]]
though cat returns a list, the number of elements in that list bears no relation to
the number of elements in the original list. Similarly, in the first equation, the should return [([17],1), ([8,100],2), ([],0)], while
two occurrences of [] play two different roles: it just happens to be the case that
the result of catenating 0 lists is the empty list. getShorty 6 ["sammy","puncher","terry","yancey",
"zeke"]
§4. Your Problems should return [("sammy",5),("terry",5),("zeke",4)].
Important note: When filling in blanks below for list comprehensions, realize 4. Define a function getShorty’ that computes the same thing as
that blanks to the right of <- may or may not require tests. For example, the blank getShorty, but is defined by filling in the blanks in:
below might be filled in with “[1..5], even x” or simply with “[1..5]”:
getShorty’ n ls = [ | <- ]
[ x | x <- ]
5. Write a recursive function
1. Use explicit recursion to write a function multPairSum :: [(Int,Int)] -> Int
prependAll :: String -> [String] -> [String]
such that multPairSum lst returns the product of the sums of pairs
such that (prependAll s ss) prepends each string in ss to the string s. in lst. For example, (multPairSum [(1,2),(50,10),(37,63)])
For example, should return 18000, since (1 + 2) × (50 + 10) × (37 + 63) = 3 × 60 ×
100 = 18000. Question: What is the product of 0 factors? The correct
prependAll "st" ["ang", "be", "", "lo"] answer is not 0...
returns ["angst","best","st","lost"].
What To Do & When To Do It
2. Define a function prependAll’ that computes the same thing as
prependAll, but is defined by filling in the blanks in: Hand in the source code for your functions, along with a transcript that demon-
strates convincingly that the code works as required.
prependAll’ s ss = [ | <- ]
This lab is due by noon on Monday, February 18. You should place it in the
3. Use explicit recursion to write a function labeled bin in CST 3-212.
Page 3 January 25, 2008
Related docs
Get documents about "