Skip to content

Commit e732208

Browse files
committed
Complete Chapter 12
1 parent 801f027 commit e732208

File tree

10 files changed

+309
-4
lines changed

10 files changed

+309
-4
lines changed

ch12/BinaryTree.hs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module BinaryTree where
2+
3+
4+
data BinaryTree a
5+
= Leaf
6+
| Node (BinaryTree a) a (BinaryTree a)
7+
deriving (Eq, Ord, Show)
8+
9+
10+
-- 1
11+
unfold :: (a -> Maybe (a,b,a)) -> a -> BinaryTree b
12+
unfold f a =
13+
case f a of
14+
Nothing -> Leaf
15+
Just (l, m, r) -> Node (unfold f l) m (unfold f r)
16+
17+
18+
-- 2
19+
-- >>> treeBuild 0
20+
-- Leaf
21+
-- >>> treeBuild 1
22+
-- Node Leaf 0 Leaf
23+
-- >>> treeBuild 2
24+
-- Node (Node Leaf 1 Leaf) 0 (Node Leaf 1 Leaf)
25+
-- >>> treeBuild 3
26+
-- Node (Node (Node Leaf 2 Leaf) 1 (Node Leaf 2 Leaf)) 0 (Node (Node Leaf 2 Leaf) 1 (Node Leaf 2 Leaf))
27+
treeBuild :: Integer -> BinaryTree Integer
28+
treeBuild n
29+
| n < 0 = Leaf
30+
| otherwise = unfold f 0
31+
where
32+
f k
33+
| k == n = Nothing
34+
| otherwise = Just (k+1, k, k+1)

ch12/CountTheBeforeVowel.hs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module CountTheBeforeVowel where
2+
3+
4+
countTheBeforeVowel :: String -> Integer
5+
countTheBeforeVowel s =
6+
case words s of
7+
[] -> 0
8+
[w] -> 0
9+
theWords ->
10+
let
11+
classifiedWords = map classify theWords
12+
count (IsThe, StartsWithVowel) accum = 1 + accum
13+
count _ accum = accum
14+
in
15+
foldr count 0 $ zip classifiedWords (tail classifiedWords)
16+
17+
18+
data Classification = IsThe | StartsWithVowel | SomethingElse
19+
20+
21+
classify :: String -> Classification
22+
classify s
23+
| s == "the" = IsThe
24+
| startsWithVowel s = StartsWithVowel
25+
| otherwise = SomethingElse
26+
27+
28+
startsWithVowel :: String -> Bool
29+
startsWithVowel [] = False
30+
startsWithVowel (c:cs) = isVowel c
31+
32+
33+
isVowel :: Char -> Bool
34+
isVowel c = c `elem` "aeiou"

ch12/CountVowels.hs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module CountVowels where
2+
3+
4+
countVowels :: String -> Integer
5+
countVowels = len . filter isVowel
6+
7+
8+
len :: [a] -> Integer
9+
len [] = 0
10+
len (_:xs) = 1 + len xs
11+
12+
13+
isVowel :: Char -> Bool
14+
isVowel c = c `elem` "aeiou"

ch12/Either.hs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
module Either where
2+
3+
4+
-- 1
5+
-- >>> lefts' [Left 1, Left 2, Left 3]
6+
-- [1, 2, 3]
7+
-- >>> lefts' [Left 1, Right 2, Left 3]
8+
-- [1, 3]
9+
lefts' :: [Either a b] -> [a]
10+
lefts' = foldr left []
11+
where
12+
left (Left a) as = a:as
13+
left (Right _) as = as
14+
15+
16+
-- 2
17+
-- >>> rights' [Right 1, Right 2, Right 3]
18+
-- [1, 2, 3]
19+
-- >>> rights' [Right 1, Left 2, Right 3]
20+
-- [1, 3]
21+
rights' :: [Either a b] -> [b]
22+
rights' = foldr right []
23+
where
24+
right (Right b) bs = b:bs
25+
right (Left _) bs = bs
26+
27+
28+
-- 3
29+
-- >>> partitionEithers' [Left 1, Right 2, Left 3]
30+
-- ([1, 3], [2])
31+
partitionEithers' :: [Either a b] -> ([a], [b])
32+
partitionEithers' = foldr partition ([], [])
33+
where
34+
partition (Left a) (as, bs) = (a:as, bs)
35+
partition (Right b) (as, bs) = (as, b:bs)
36+
37+
38+
-- 4
39+
-- >>> eitherMaybe' (+1) (Left "hello")
40+
-- Nothing
41+
-- >>> eitherMaybe' (+1) (Right 1)
42+
-- Just 2
43+
eitherMaybe' :: (b -> c) -> Either a b -> Maybe c
44+
eitherMaybe' _ (Left _) = Nothing
45+
eitherMaybe' f (Right b) = Just $ f b
46+
47+
48+
-- 5
49+
-- >>> either' (+1) (*5) (Left 2)
50+
-- 3
51+
-- >>> either' (+1) (*5) (Right 2)
52+
-- 10
53+
either' :: (a -> c) -> (b -> c) -> Either a b -> c
54+
either' f _ (Left a) = f a
55+
either' _ g (Right b) = g b
56+
57+
58+
-- 6
59+
-- Same as eitherMaybe' but written in terms of either'
60+
eitherMaybe'' :: (b -> c) -> Either a b -> Maybe c
61+
eitherMaybe'' g = either' (const Nothing) (Just . g)

ch12/Maybe.hs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
module Maybe where
2+
3+
4+
-- 1
5+
-- >>> isJust (Just 1)
6+
-- True
7+
-- >>> isJust Nothing
8+
-- False
9+
isJust :: Maybe a -> Bool
10+
isJust Nothing = False
11+
isJust _ = True
12+
13+
14+
-- >>> isNothing (Just 1)
15+
-- False
16+
-- >>> isNothing Nothing
17+
-- True
18+
isNothing :: Maybe a -> Bool
19+
isNothing Nothing = True
20+
isNothing _ = False
21+
22+
23+
-- 2
24+
-- >>> mayybee 0 (+1) Nothing
25+
-- 0
26+
-- >>> mayybee 0 (+1) (Just 1)
27+
-- 2
28+
mayybee :: b -> (a -> b) -> Maybe a -> b
29+
mayybee b _ Nothing = b
30+
mayybee _ f (Just a) = f a
31+
32+
33+
-- 3
34+
-- >>> fromMaybe 0 Nothing
35+
-- 0
36+
-- >>> fromMaybe 0 (Just 1)
37+
-- 1
38+
fromMaybe :: a -> Maybe a -> a
39+
fromMaybe a ma = mayybee a id ma
40+
41+
42+
-- 4
43+
-- >>> listToMaybe [1, 2, 3]
44+
-- Just 1
45+
-- >>> listToMaybe []
46+
-- Nothing
47+
listToMaybe :: [a] -> Maybe a
48+
listToMaybe [] = Nothing
49+
listToMaybe (x:_) = Just x
50+
51+
52+
-- >>> maybeToList (Just 1)
53+
-- [1]
54+
-- >>> maybeToList Nothing
55+
-- []
56+
maybeToList :: Maybe a -> [a]
57+
maybeToList Nothing = []
58+
maybeToList (Just x) = [x]
59+
60+
61+
-- 5
62+
-- >>> catMaybes [Just 1, Nothing, Just 2]
63+
-- [1, 2]
64+
-- >>> catMaybes [Nothing, Nothing, Nothing]
65+
-- []
66+
catMaybes :: [Maybe a] -> [a]
67+
catMaybes [] = []
68+
catMaybes (Nothing:xs) = catMaybes xs
69+
catMaybes (Just x:xs) = x : catMaybes xs
70+
71+
72+
-- 6
73+
-- >>> flipMaybe [Just 1, Just 2, Just 3]
74+
-- Just [1, 2, 3]
75+
-- >>> flipMaybe [Just 1, Nothing, Just 3]
76+
-- Nothing
77+
flipMaybe :: [Maybe a] -> Maybe [a]
78+
flipMaybe [] = Just []
79+
flipMaybe (Nothing:_) = Nothing
80+
flipMaybe (Just x:xs) =
81+
case flipMaybe xs of
82+
Just ys -> Just (x:ys)
83+
Nothing -> Nothing

ch12/Natural.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
module Natural where
22

3+
34
data Nat
45
= Zero
56
| Succ Nat
67
deriving (Eq, Show)
78

9+
810
natToInteger :: Nat -> Integer
911
natToInteger Zero = 0
1012
natToInteger (Succ n) = 1 + natToInteger n
1113

14+
1215
integerToNat :: Integer -> Maybe Nat
1316
integerToNat k
1417
| k < 0 = Nothing

ch12/ReplaceThe.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module ReplaceThe where
2+
3+
import Data.List (intercalate)
4+
5+
-- This may not be the solution they had in mind.
6+
7+
8+
replaceThe :: String -> String
9+
replaceThe s = intercalate " " $ map theToA (words s)
10+
where
11+
theToA :: String -> String
12+
theToA "the" = "a"
13+
theToA s = s

ch12/Unfolds.hs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module Unfolds where
2+
3+
4+
-- 1
5+
-- >>> take 10 $ myIterate (+1) 0
6+
-- [0,1,2,3,4,5,6,7,9]
7+
myIterate :: (a -> a) -> a -> [a]
8+
myIterate f a = a : myIterate f (f a)
9+
10+
11+
-- 2
12+
-- >>> take 10 $ myUnfoldr (\b -> Just (b, b+1)) 0
13+
-- [0,1,2,3,4,5,6,7,8,9]
14+
myUnfoldr :: (b -> Maybe (a, b)) -> b -> [a]
15+
myUnfoldr f b =
16+
case f b of
17+
Nothing -> []
18+
Just (a, b') -> a : myUnfoldr f b'
19+
20+
21+
-- 3
22+
-- >>> take 10 $ betterIterate (+1) 0
23+
-- [0,1,2,3,4,5,6,7,8,9]
24+
betterIterate :: (a -> a) -> a -> [a]
25+
betterIterate f = myUnfoldr (\a -> Just (a, f a))

ch12/ValidateTheWord.hs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module ValidateTheWord where
2+
3+
4+
newtype Word' = Word' String deriving (Eq, Show)
5+
6+
7+
vowels = "aeiou"
8+
9+
10+
mkWord :: String -> Maybe Word'
11+
mkWord s =
12+
let
13+
(nVowels, nConsonants) = foldr count (0, 0) s
14+
count c (nv, nc)
15+
| c `elem` vowels = (nv + 1, nc)
16+
| otherwise = (nv, nc + 1)
17+
in
18+
if nVowels > nConsonants
19+
then Nothing
20+
else Just (Word' s)

ch12/chex.txt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,32 @@ The kind of a is * and the kind of f is * -> *.
1010

1111
String Processing
1212

13-
To be completed...
13+
1. See ReplaceThe.hs.
14+
15+
2. See CountTheBeforeVowel.hs.
16+
17+
3. See CountVowels.hs.
1418

1519
Validate the word
1620

17-
To be completed...
21+
See ValidateTheWord.hs.
1822

1923
It's only Natural
2024

21-
See Natural.hs
25+
See Natural.hs.
26+
27+
Small library for Maybe
28+
29+
See Maybe.hs.
30+
31+
Small library for Either
32+
33+
See Either.hs.
34+
35+
Unfolds
36+
37+
See Unfolds.hs.
38+
39+
Finally something other than a list!
2240

23-
The rest has to be completed...
41+
See BinaryTree.hs.

0 commit comments

Comments
 (0)