Chapter 9 Outline¶
– Chapter 9 spans from pages 299 to 346, for a total of 47 pages.
9.1 Lists
p1. What lists are used to represent.
p2. Learning objectives.
9.2 The list datatype
p1. “The list datatype is defined like this:”
f1. Definition of the list datatype.
p2. The type and data constructors of list.
p3. Arity of constructors. (tycon)
[] aunary,a : [a]binary, (datacon)[]unary.p4. “In English, one can read this as:”
f2. Anatomy of the list datatype declaration.
p5. The cons
(:)data constructor is binary, takes a recursively defined argument, and represents a product relationship.p6. Lists in Haskell are similar to singly-linked lists.
9.3 Pattern matching on lists
p1. We can match on the
(:)and[]data constructors. Here we match on the first argument of(:).f1. Definition, type query, and sample use of
myHeadin GHCi.
p2. We’ll match on the second argument of
(:)inmyTail.f2. Definition, type query, and sample use of
myTailin GHCi.
p3. Both
myHeadandmyTaildon’t handle the case of an empty list,[].f3. GHCi session showing that exceptions are thrown when
myHeadandmyTailare applied to[].
p4.
f4. Definition of
myTailas source code, with a base case for[]added.
p5. “With that addition, our function now evaluates like this:”
f5. GHCi session showing
myTailapplied to a finite list and the empty list.
p6. Using
Maybe.p7. Let’s try an example using
MaybewithmyTail.f6.
:info Maybe
p8. “Rewriting
myTailto useMaybeis fairly straightforward:”f7. Definition of
safeTail.
p9. Description of
safeTail. See if you can rewrite the myHead function using Maybe.p10. Later the book will cover
NonEmpty, which avoids the empty list problem.
9.4 List’s syntactic sugar
p1.
f1. GHCi session demonstrating equivalence of
[1,2,3]++[4]and(1:2:3:[])++(4:[]).
p2.
[x,y]syntax saves typing.p3. Cons cells and spines.
p4. The spine is the connective structure between nested cons cells.
9.5 Using ranges to construct lists
9.5.1 Exercise:
EnumFromTo
9.6 Extracting portions of lists
p1. Let’s first look at
take,drop, andsplitAt.f1. Type signatures of
take,drop, andsplitAt.
p2.
p3.
f2.
takeapplied to finite lists
p4.
f3.
takeapplied to an infinite list
p5.
f4.
dropapplied to finite lists
p6.
f5.
splitAtapplied to finite lists
p7. Next we’ll look at
takeWhileanddropWhilef6. Type signatures of
takeWhileanddropWhile.
p8. These functions will take or drop elements that meet the condition and then stop when it meets the first element that doesn’t satisfy the predicate function.
p9.
f7. Take while the elements are less than 3
p10.
f8. Take while the elements are less than 8
p11.
f9.
takeWhileproduces an empty list when the first element does not meet the predicate.
p12. “In the final example below, why does it only return a single a?”
f10.
takeWhile (=='a') "abracadabra"
– (The second element evaluates to
Falsein our predicate function, sotakeWhilestops taking elements after the first element.)p13. Now we’ll look at
dropWhile.f11. Examples of
dropWhlieapplied to finite lists
9.6.1 Exercises: Thy Fearful Symmetry
1
p1.
f1.
2
p1.
f1. The
PoemLinesmodule.
p2.
f2. The result that
putStrLn sentencesshould print.
p3.
f3. Stub for the
myLinesfunction.
p4.
f4. A list named
shouldEqualthatmyLines sentencesshould produce.
p5.
f5. A small test implemented as a
mainfunction.
3
p1.
9.7 List comprehensions
p1. List comprehensions are a language construct inspired by set builder notation in mathematics. You use them to create new lists from an existing generator list, which may be filtered along the way by a guard.
p2.
f1. A simple comprehension,
[ x^2 | x <- [1..10]], followed by a lot of explanatory text.
p3.
f2.
[ x^2 | x <- [1..10]
9.7.1 Adding predicates
p1.
p2.
f1.
p3.
p4.
p5.
p6.
f2.
p7.
p8.
f3. A list comprehension with a predicate, evaluated in GHCi.
p9. We can use multiple generators to zip two lists.
f4. Two list comprehensions that performs a cross product on two lists into a list of pairs, evaluated in GHCi.
p10.
p11.
f5.
mySqr, a comprehension of square numbers from n..10, evaluated in GHCi.
p12. We can use that list as a generator for another list comprehension.
f6.
9.7.2 Exercises: Comprehend thy lists
p1.
f1.
9.7.3 List comprehensions with strings
p1.
f1.
p2.
f2.
p3.
f3. An acronym generator.
p4.
p5. “All right, so we have our acro function with which we can generate acronyms from any string:”
f4.
acroapplied to different arguments in GHCi.
p6. “Given the above, what do you think this function would do:”
f5.
9.7.4 Exercises: Square Cube
p1.
f1.
1
2
3
9.8 Spines and non-strict evaluation
p1. The structure that connects elements together in composite datatypes is known as the spine.
f1. An ASCII art representation of the list
[1,2]as a tree of data constructors and their term-level arguments.
p2.
p3. Evaluation proceeds down the spine (left to right), but construction proceeds up the spine (right to left).
p4.
f2. ASCII art pointing out the spine of a list.
p5.
9.8.1 Using GHCi’s :sprint command
p1.
p2.
p3.
p4.
f1.
p5.
p6. “Next, we’ll take one value…”
f2.
p7.
p8.
f3.
p9.
p10.
f4.
p11.
f5.
p12.
9.8.2 Spines are evaluated independently of values
– page 320
p1. All expressions are evaluated to WHNF by default.
p2. WHNF vs NF.
p3. Examples of expressions, and whether they are WHNF or NF.
f1.
(1, 2)
– page 321
p4.
f2.
(1, 1+1)
p5.
f3.
\x -> x*10
p6.
f4.
"Papu" ++ "chon"
p7.
f5.
(1, "Papu" ++ "chon")
p8.
f6. Showing a fully evaluated list in GHCi.
– p9 is split between pages 321 and 322
p9.
– page 322
f7. A demonstration of WHNF evaluation in GHCi.
p10.
p11.
f8. The spine of a list that isn’t spine strict and is awaiting something to force the evaluation. (The first cons cells, no arguments evaluated.)
p12.
p13.
– page 323
p14.
f9. Tree representation of the spine of an unevaluated list with two elements.
p15.
f10. GHCi
x = [1,undefined]; length xreturns2.
p16.
f11. Source code for a
lengthfunction.
p17.
– page 324
p18.
f12. A complicated tree representation showing forced cons constructors, with unevaluated arguments.
p19.
f13. Demonstration of applying
lengthto a list withundefinedin the spine.
p20. Printing the list fails, but it gets as far as printing the first
[1***.p21. It’s possible to write functions that will force both the spine and the values.
p22. We’ll write our own sum function for the sake of demonstration:
f14. Source code for
mySum.
p23.
– page 325
f15. The evaluation steps of
mySum [1..5]
p24.
9.8.3 Exercises: Bottom madness
9.8.3.1 Will it blow up?
9.8.3.2 Intermission: Is it in normal form?
9.9 Transforming lists of values
– page 326
p1. HOFs are use more often than primitive recursion to transform data.
p2. The
mapfunction applies a function to every element of a list.fmapdoes the same, but for any type that implementsFoldable.
– page 327
f1. Examples of using
mapandfmapin GHCi.
p3. The types of
mapandfmaprespectively are:f2.
p4.
f3.
p5.
f4.
:t map (+1)
p6.
p7.
f5.
– page 328
p8.
f6.
:t fmap (+1)
p9.
f7. The definition of
mapfrom thebasepackage, heavily annotated. Spans pages 328 and 329.
– page 329
p10. “How do we write out what
map fdoes?”f8.
map (+1) [1, 2, 3]
p11.
f9.
map (+1) (1 : (2 : (3 : [])))
p12.
f10. Shows one step of the evaluation process for
map (+1) [1,2,3].
p13.
f11.
p14.
f12.
– page 330
p15.
f13.
p16. “Finishing the reduction of the expression:”
f14.
p17. “Using the syntactic sugar of list, here’s an approximation of what map is doing for us:”
f15.
p18.
f16.
p19.
f17.
– page 331
p20. Map is not applied to every element at once. Each element is mapped if and when its evaluation is forced.
f18.
p21.
f19.
p22.
p23.
– page 332
p24.
f20.
p25.
f21.
p26.
f22.
Prelude> map (\x -> if x == 3 then (-x) else (x)) [1..10]
p27.
– page 332
9.9.1 Exercises: More bottoms
1
2
3
– page 333
4
5
a
b
c
6
9.10 Filtering lists of values
p1. We showed a few examples of
filterearlier.f1.
filter even [1..10]
p2. Filter has the following definition:
– page 334
f2. The definition of filter.
p3. Filter takes a predicate function and a list and returns a list containing only the elements that satisfy the predicate.
p4. Examples of
filterthat we’ve already seen.
f3.
filter (== 'a') "abracadabra"p5. The following examples does the same thing as filter even, but with a lambda as input.
f4.
p6. We covered list comprehensions as a way of filtering lists, as well. Compare the following:
f5. Example of filter vs a guarded list comprehension.
p7.
p8. We recommend at this point that you try writing some filter functions of your own to get comfortable with the pattern.
– page 335
9.10.1 Exercises: Filtering
1
2
3
9.11 Zipping lists
p1.
p2.
f1.
p3.
f2.
p4.
f3.
p5.
f4.
p6. “We can use unzip to recover the lists as they were before they were zipped:”
f5.
p7. “Be aware that information can be list in this process, because zip must stop on the shortest list:”
f6.
p8. “We can also use zipWith to apply a function to the values of two lists in parallel:”
f7. zipWith
p9. “A brief demonstration of how
zipWithworks:”f8.
9.11.1 Zipping exercises
9.12 Chapter exercises
p1.
9.12.1 Data.Char
p1.
1
2
3
4
5
6
9.12.2 Ciphers
p1. Save these exercises in a module named
Cipher, since we’ll be coming back to them later.p2. The Caesar cipher shift by \(n\) numbers forward in the alphabet.
p3. Write a basic Caesar cipher.
p4. Try to implement the cipher before googling a solution.
p5. The first lines should look like:
f1. A module header and import statement for
Cipher.
p6.
ordandchrmay be useful to you.f2. A GHCi session where the types of
chrandordare queried.
p7. You want your shift to wrap back around the alphabet.
p8. Also, write an
unCeasarcipher.
9.12.3 Writing your own standard functions
p1.
p2.
– page 341
f1. myAnd
p3. “And now the fun begins:”
1
2
3
4
5
6
7
8
9
10
9.13 Definitions
Product type
Sum type
Cons
Cons cell
Spine
9.14 Follow-up resources
Data.List documentation for the base library. http://hackage.haskell.org/package/base/docs/Data-List.html
Haskell Wiki. Ninety-Nine Haskell problems. https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems