Skip to content

Commit 7a1ddcc

Browse files
committed
feat: ch 09 to last exercise
1 parent 07d9152 commit 7a1ddcc

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

09-lists/01-exercises.lhs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33

44
> module Chapter9Exercises where
55

6+
\begin{code}
7+
import Data.Bool (bool)
8+
import Data.Char
9+
\end{code}
10+
611
\section{9.5 EnumFromTo}
712

813
\begin{code}
@@ -66,5 +71,112 @@ e2' = [(x, y) | x <- mySqrs, y <- myCubes, x < 50, y < 50]
6671
6772
-- 3. determine how many tuples inhabit your output list
6873
e3' = (length e1', length e2') -- 25, 15
74+
\end{code}
75+
76+
77+
\section{9.8 Spines and nonstrict evaluation}
78+
79+
Bottom Madness: will the following expressions return a value or be ⊥?
80+
81+
\begin{code}
82+
-- b1 = [x^y | x <- [1..5], y <- [2, undefined]] -- ⊥
83+
b2 = take 1 $ [x^y | x <- [1..5], y <- [2, undefined]] -- value ([1])
84+
-- b3 = sum [1, undefined, 3] -- ⊥
85+
b4 = length [1, 2, undefined] -- value (3)
86+
-- b5 = length $ [1, 2, 3] ++ undefined -- ⊥
87+
b6 = take 1 $ filter even [1, 2, 3, undefined] -- value ([2])
88+
-- b7 = take 1 $ filter even [1, 3, undefined] -- ⊥
89+
b8 = take 1 $ filter odd [1, 3, undefined] -- value ([1])
90+
b9 = take 2 $ filter odd [1, 3, undefined] -- value ([1, 3])
91+
-- b10 = take 3 $ filter odd [1, 3, undefined] -- ⊥
92+
\end{code}
93+
94+
For each expression below, determine whether it’s in NF, WHNF, or neither.
95+
96+
1. [1, 2, 3, 4, 5] -- NF
97+
2. 1 : 2 : 3 : 4 : _ -- WHNF
98+
3. enumFromTo 1 10 -- neither
99+
4. length [1, 2, 3, 4, 5] -- neither
100+
5. sum (enumFromTo 1 10) -- neither
101+
6. ['a'..'m'] ++ ['n'..'z'] -- neither
102+
7. (_, 'b') -- WHNF
103+
104+
105+
\section{9.9 Transforming lists of values}
106+
107+
More Bottom
108+
109+
\begin{code}
110+
-- mb1 = take 1 $ map (+1) [undefined, 2, 3] -- ⊥
111+
mb2 = take 1 $ map (+1) [1, undefined, 3] -- value (2)
112+
-- mb3 = take 2 $ map (+1) [1, undefined, 3] -- ⊥
113+
114+
itIsMystery xs = map (\x -> elem x "aeiou") xs -- creates list of bools predicated on vowels
115+
116+
mb5a = map (^2) [1..10] -- [1, 4, 9, 16 etc.]
117+
mb5b = map minimum [[1..10], [10..20], [20..30]] -- [1, 10, 20]
118+
mb5c = map sum [[1..5], [1..5], [1..5]] -- [15, 15, 15]
119+
120+
mb6 = map (\x -> bool x (-x) (x == 3))
121+
\end{code}
122+
123+
124+
\section{9.10 Filtering lists of values}
125+
126+
How might we write a filter function that would give us all the multiples of 3 out of a list from 1-30?
127+
128+
\begin{code}
129+
getMultiple3 = filter (\x -> x `mod` 3 == 0)
130+
howManyMult3 = length . getMultiple3
131+
removeArticles = unwords . filter (\s -> not $ s `elem` ["a", "an", "the"]) . words
132+
\end{code}
133+
134+
135+
\section{9.11 Zipping lists}
136+
137+
\begin{code}
138+
myZip :: [a] -> [b] -> [(a, b)]
139+
myZip [] _ = []
140+
myZip _ [] = []
141+
myZip (x:xs) (y:ys) = (x, y) : myZip xs ys
142+
143+
myZipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
144+
myZipWith _ [] _ = []
145+
myZipWith _ _ [] = []
146+
myZipWith f (x:xs) (y:ys) = f x y : myZipWith f xs ys
147+
148+
myZipB :: [a] -> [b] -> [(a, b)]
149+
myZipB = zipWith (,)
150+
\end{code}
151+
152+
153+
\section{9.12 Chapter Exercises}
154+
155+
Data.Char:
156+
157+
1. isUpper :: Char -> Bool; toUpper :: Char -> Char
158+
159+
\begin{code}
160+
getUppers :: String -> String
161+
getUppers = filter isUpper
162+
163+
capitalize :: String -> String
164+
capitalize [] = []
165+
capitalize (c:cs) = toUpper c : cs
166+
167+
allCaps :: String -> String
168+
-- allCaps [] = []
169+
-- allCaps (c:cs) = toUpper c : allCaps cs
170+
allCaps = map toUpper
171+
172+
capFirst :: String -> Char
173+
capFirst = toUpper . head
174+
\end{code}
175+
176+
Cipher: see 03-cipher.hs
177+
178+
Implementing standard functions:
179+
180+
\begin{code}
69181
70182
\end{code}

09-lists/03-cipher.hs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module Cipher where
2+
3+
import Data.Char
4+
5+
-- 65 A to 90 Z, 97 a to 122 z
6+
caesar, unCaesar :: Int -> String -> String
7+
caesar shift = map (translate shift)
8+
unCaesar = caesar . negate
9+
10+
toAlphaNum :: Char -> Int
11+
toAlphaNum c
12+
| isUpper c = code - 65
13+
| isLower c = code - 71
14+
where code = ord c
15+
16+
translate :: Int -> Char -> Char
17+
translate shift c
18+
| isAlpha c = letters !! ((toAlphaNum c + shift) `mod` 52)
19+
| otherwise = c
20+
where letters = ['A'..'Z'] ++ ['a'..'z']

09-lists/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,32 @@ Comprehensions:
4040
- `[x^y | x <- [1..5], y <- [2, 3], x^y < 200]`
4141
- `[(x, y) | x <- [1, 2, 3], y <- ['a', 'b']]` is (1, a), (1, b), (2, a) etc.
4242
- `[x | x <- "Three Letter Acronym", elem x ['A'..'Z']]` is "TLA"
43+
44+
---
45+
46+
`:sprint` command can indicate (somewhat) what expressions have been evaluated.
47+
48+
```
49+
λ: let blah = enumFromTo 'a' 'z'
50+
λ: :sprint blah
51+
blah = _
52+
λ: take 3 blah
53+
"abc"
54+
λ: sprint blah
55+
blah = 'a' : 'b' : 'c' : _
56+
```
57+
58+
**WHNF** (Weak Head Normal Form) – evaluated to at least a data constructor.
59+
60+
- `(1, 2)` WHNF & NF
61+
- `(1, 1 + 1)` WHNF (not NF)
62+
63+
`length` is strict in the spine but not the values. Using `_` in pattern matching can be used to ignore values.
64+
65+
`take 2 $ map (+1) [1, 2, undefined]` prints `[2, 3]`.
66+
67+
---
68+
69+
- `bool :: a -> a -> Bool -> a`
70+
- `chr :: Int -> Char`
71+
- `ord :: Char -> Int`

0 commit comments

Comments
 (0)