aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 33fe9eb3fce0652beab21b7c4832ec93ddf7eb60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# Real World Haskell solutions

These are solutions to exercises from me reading the first edition of the [the
Real World Haskell book](https://book.realworldhaskell.org/). Publishing the
solutions like this helps me in being more thorough in reading the book. I also
hope they will be helpful in your journey to the world of Haskell.

The goal is to provide solutions to all the exercises. I'm adding them gradually
as I'm progressing through the book.

There is often more than one solution to an exercise. If your solution is
different but meets the assignment, it is the right one.

My original intention was for the exercises to be solved as by a beginner, with
all the things that a seasoned Haskell programmer would have done
differently. The solutions should have mostly used only knowledge from the
preceding parts of the book. Exceptions to this were cases where such approach
would lead to too many additional lines of code or to distracting the reader
from the main idea of an exercise. Advanced topics from the subsequent chapters
should have been avoided, though.

However, in about two thirds of the book I finally had to admit to myself that
it was too challenging and got stuck. Then I took a detour to other Haskell
books that were more suitable for beginners. Now I returned and I'm going to see
how much difference it has made and whether I will be able to continue in the
exercises.

## Running the code on new systems

The book was published in 2008. Even though it's old, most of the code can still
be compiled with recent versions of GHC without any change. Only a few parts
required minor modifications or additions. These are described in the comments
in the source files of the exercise solutions.

Where more work was needed, I wanted to keep the code in its original form as
much as possible instead of rewriting it for new GHC or libraries. These cases
are described here.

### Chapter 23: GUI programming with gtk2hs

This chapter uses more libraries than the other chapters and I was not able to
install all of them using recent `stack` resolvers (sets of GHC and specific
package versions) and `Cabal` versions.

I decided to create a reproducible environment consisting of an older GHC and
compatible versions of the required libraries. Eventually, I was able to compile
and run the application.

See the [README](ch23/support/README.md) in the [ch23/support](ch23/support) directory.

## Exercises

There are a few kinds of exercises:

- Describe what happens when you run the code
- Answer a question
- Write an implementation

Solutions to the first two kinds of exercises are provided in comments in
Haskell source files.

### Ambiguity and mistakes in the assignments

Assignments of the exercises are taken exactly as they are in the printed
version of the book without correcting any mistakes. Those are corrected in
comments immediately following the assignments.

Some exercises are unclear or they seem to contain contradicting information. In
these cases I describe my additional assumptions and thought process in
comments.

### Solutions using code from the examples

Some solution implementations use [the example code from the
book](https://resources.oreilly.com/examples/9780596514983). The complete
examples repository these solutions are base on is added as a submodule in the
'examples' directory.

If a solution of an exercise depends on more source code from the examples, the
whole files are copied to a directory of that solution.

If not much code is needed, then just the required parts are copied directly to
the file with implementation and marked by comments.

### Platform

The solutions are implemented and tested in a Linux environment. This also
includes solutions that could have been made multiplatform.

### List of the exercises

Format of an exercise label is '{Module_}\<chapter\>\_\<group\>\_\<exercise\>'. Some
chapters contain more groups of exercises. To differentiate those, an exercise
group letter is included (the exact letters don't have a connection to the
book). To make the exercise groups more visible in the list the first exercise
of a group is in bold italics.

If a solution is intended to be used in solutions to other exercises, to reduce code
duplication, it is imported as a Haskell module. For this to work, the naming
conventions for Haskell modules need to be followed. The names of such source files
are prefixed with 'Module_'.


| Exercise       | Solved | Page | Chapter |
| -------------- | ------ | ---- | ------- |
| **_1_a_1_**    | yes    | 16   | 1. Getting started |
| 1_a_2          | yes    |      | |
| 1_a_3          | yes    |      | |
| 1_a_4          | yes    |      | |
| **_2_a_1_**    | yes    | 25   | 2. Types and functions |
| **_2_b_1_**    | yes    | 39   | |
| 2_b_2          | yes    |      | |
| 2_b_3          | yes    |      | |
| **_3_a_1_**    | yes    | 60   | 3. Defining types, streamlining functions |
| 3_a_2          | yes    |      | |
| **_3_b_1_**    | yes    | 69   | |
| 3_b_2          | yes, in 3_b_1 |      | |
| 3_b_3          | yes    |      | |
| 3_b_4          | yes    |      | |
| 3_b_5          | yes    |      | |
| 3_b_6          | yes    | 70   | |
| 3_b_7          | yes    |      | |
| 3_b_8          | yes    |      | |
| 3_b_9          | yes    |      | |
| 3_b_10         | yes, in 3_b_9 |      | |
| 3_b_11         | yes, in 3_b_9 |      | |
| 3_b_12         | yes, in 3_b_9 |      | |
| **_4_a_1_**    | yes    | 84   | 4. Functional programming |
| 4_a_2          | yes    |      | |
| 4_a_3          | yes    |      | |
| 4_a_4          | yes    |      | |
| **_4_b_1_**    | yes, in 4_b_2 | 97   | |
| 4_b_2          | yes    | 98   | |
| 4_b_3          | yes    |      | |
| 4_b_4          | yes    |      | |
| 4_b_5          | yes, in 4_b_6 |      | |
| 4_b_6          | yes    |      | |
| 4_b_7          | yes    |      | |
| 4_b_8          | yes, in 4_b_9 |      | |
| 4_b_9          | yes    |      | |
| 4_b_10         | yes    |      | |
| **_5_a_1_**    | yes    | 130  | 5. Writing a library: working with JSON data |
| 5_a_2          | yes, in 5_a_1 |      | |
| **_6_a_1_**    | yes    | 162  | 6. Using typeclasses |
| 6_a_2          | yes    |      | |
| **_8_a_1_**    | yes    | 205  | 8. Efficient file processing, regular expressions, and file name matching |
| 8_a_2          | yes    |      | |
| **_8_b_1_**    | yes, in 8_a_2 | 210  | |
| 8_b_2          | yes    |      | |
| 8_b_3          | yes    |      | |
| **_Module_8_c_1_** | yes    | 211  | |
| 8_c_2          | yes    |      | |
| **_8_d_1_**    | yes    | 212  | |
| **_9_a_1_**    | yes    | 221  | 9. I/O case study: a library for searching the filesystem |
| **_9_b_1_**    | yes    | 228  | |
| 9_b_2          | yes    |      | |
| Module_9_b_3   | yes    |      | |
| 9_b_4          | yes    |      | |
| **_9_c_1_**    | yes    | 232  | |
| 9_c_2          | yes    |      | |
| 9_c_3          | yes    |      | |
| **_9_d_1_**    | yes    | 234  | |
| 9_d_2          | yes    |      | |
| **_10_a_1_**   | yes    | 254  | 10. Code case study: parsing a binary data format |
| 10_a_2         | yes, in 10_a_1  |      | |
| 10_a_3         | yes, in 10_a_1  |      | |
| **_12_a_1_**   | yes    | 274  | 12. Barcode recognition |
| 12_a_2         | yes, in 12_a_1  |      | |
| 12_a_3         | yes, in 12_a_1  |      | |
| **_13_a_1_**   | yes    | 316  | 13. Data structures |
| **_14_a_1_**   | yes    | 352  | 14. Monads |
| **_15_a_1_**   | yes    | 382  | 15. Programming with monads |
| 15_a_2         | yes, in 15_a_1  |      | |
| 15_a_3         | yes    |      | |
| **_16_a_1_**   | yes    | 403  | 16. Using parsec |
| 16_a_2         | yes    |      | |
| 16_a_3         | yes    |      | |
| 16_a_4         | yes    |      | |
| **_18_a_1_**   | yes    | 436  | 18. Monad transformers |
| 18_a_2         | yes    |      | |
| 18_a_3         | yes, in 18_a_2  |      | |
| **_18_b_1_**   | yes    | 441  | |
| **_19_a_1_**   | yes    | 462  | 19. Error handling |
| **_Module_19_b_1_** | yes    | 465  | |
| 19_b_2         | yes    |      | |
| 19_b_3         | yes, in 19_b_2  |      | |
| **_23_a_1_**   | yes    | 529  | 23. GUI programming with gtk2hs|
| 23_a_2         | yes, in 23_a_1  |      | |
| 23_a_3         | yes    |      | |
| **_24_a_1_**   |        | 542  | 24. Concurrent and multicore programming |
| 24_a_2         |        |      | |
| **_24_b_1_**   |        | 551  | |
| 24_b_2         |        |      | |
| **_26_a_1_**   |        | 610  | 26. Advanced library design: building a Bloom filter |
| 26_a_2         |        |      | |

## Bug reports

If you find an error in a solution or anything that should be described more
clearly, feel free to let me know by opening an issue here or a pull request
here.