Programming in Haskell 2nd Edition Graham Hutton 2024 Scribd Download
Programming in Haskell 2nd Edition Graham Hutton 2024 Scribd Download
com
https://textbookfull.com/product/programming-in-
haskell-2nd-edition-graham-hutton/
https://textbookfull.com/product/programming-in-haskell-second-
edition-5th-printing-edition-hutton/
textbookfull.com
https://textbookfull.com/product/thinking-with-types-type-level-
programming-in-haskell-sandy-maguire/
textbookfull.com
https://textbookfull.com/product/haskell-the-ultimate-beginner-s-
guide-to-learn-haskell-programming-step-by-step-1st-edition-claudia-
alves/
textbookfull.com
https://textbookfull.com/product/asap-1st-edition-axie-oh/
textbookfull.com
https://textbookfull.com/product/financial-mathematics-for-actuaries-
second-edition-chan/
textbookfull.com
https://textbookfull.com/product/routledge-handbook-of-early-chinese-
history-paul-r-goldin-editor/
textbookfull.com
https://textbookfull.com/product/differential-equation-solutions-with-
matlab-fundamentals-and-numerical-implementations-de-gruyter-stem-
dingyu-xue/
textbookfull.com
Sexuality Education and New Materialism: Queer Things
Louisa Allen
https://textbookfull.com/product/sexuality-education-and-new-
materialism-queer-things-louisa-allen/
textbookfull.com
Programming in Haskell
Second Edition
Haskell is a purely functional language that allows programmers to rapidly develop clear, concise and
correct software. The language has grown in popularity in recent years, both in teaching and in industry.
This book is based on the author’s experience of teaching Haskell for more than 20 years. All concepts
are explained from first principles and no programming experience is required, making this book
accessible to a broad spectrum of readers. While Part I focuses on basic concepts, Part II introduces the
reader to more advanced topics.
This new edition has been extensively updated and expanded to include recent and more advanced
features of Haskell, new examples and exercises, selected solutions, and freely downloadable lecture
slides and code. The presentation is clean and simple, while also being fully compliant with the latest
version of the language, including recent changes concerning applicative, monadic, foldable and
traversable types.
GRAHAM HUTTON is Professor of Computer Science at the University of Nottingham. He has taught
Haskell to thousands of students and received numerous best lecturer awards. Hutton has served as an
editor of the Journal of Functional Programming, chair of the Haskell Symposium and the International
Conference on Functional Programming, vice-chair of the ACM Special Interest Group on Programming
Languages, and he is an ACM Distinguished Scientist.
Programming in Haskell
Second Edition
GRAHAM HUTTON
University of Nottingham
University Printing House, Cambridge CB2 8BS, United Kingdom
It furthers the University’s mission by disseminating knowledge in the pursuit of education, learning, and research at the highest international
levels of excellence.
www.cambridge.org
Information on this title: www.cambridge.org/9781316626221
10.1017/9781316784099
This publication is in copyright. Subject to statutory exception and to the provisions of relevant collective licensing agreements, no reproduction
of any part may take place without the written permission of Cambridge University Press.
A catalogue record for this publication is available from the British Library
Cambridge University Press has no responsibility for the persistence or accuracy of URLs for external or third-party Internet Web sites
referred to in this publication, and does not guarantee that any content on such Web sites is, or will remain, accurate or appropriate.
For Annette, Callum and Tom
Contents
Foreword
Preface
2 First steps
2.1 Glasgow Haskell Compiler
2.2 Installing and starting
2.3 Standard prelude
2.4 Function application
2.5 Haskell scripts
2.6 Chapter remarks
2.7 Exercises
5 List comprehensions
5.1 Basic concepts
5.2 Guards
5.3 The zip function
5.4 String comprehensions
5.5 The Caesar cipher
5.6 Chapter remarks
5.7 Exercises
6 Recursive functions
6.1 Basic concepts
6.2 Recursion on lists
6.3 Multiple arguments
6.4 Multiple recursion
6.5 Mutual recursion
6.6 Advice on recursion
6.7 Chapter remarks
6.8 Exercises
7 Higher-order functions
7.1 Basic concepts
7.2 Processing lists
7.3 The foldr function
7.4 The foldl function
7.5 The composition operator
7.6 Binary string transmitter
7.7 Voting algorithms
7.8 Chapter remarks
7.9 Exercises
11 Unbeatable tic-tac-toe
11.1 Introduction
11.2 Basic declarations
11.3 Grid utilities
11.4 Displaying a grid
11.5 Making a move
11.6 Reading a number
11.7 Human vs human
11.8 Game trees
11.9 Pruning the tree
11.10 Minimax algorithm
11.11 Human vs computer
11.12 Chapter remarks
11.13 Exercises
13 Monadic parsing
13.1 What is a parser?
13.2 Parsers as functions
13.3 Basic definitions
13.4 Sequencing parsers
13.5 Making choices
13.6 Derived primitives
13.7 Handling spacing
13.8 Arithmetic expressions
13.9 Calculator
13.10 Chapter remarks
13.11 Exercises
15 Lazy evaluation
15.1 Introduction
15.2 Evaluation strategies
15.3 Termination
15.4 Number of reductions
15.5 Infinite structures
15.6 Modular programming
15.7 Strict application
15.8 Chapter remarks
15.9 Exercises
17 Calculating compilers
17.1 Introduction
17.2 Syntax and semantics
17.3 Adding a stack
17.4 Adding a continuation
17.5 Defunctionalising
17.6 Combining the steps
17.7 Chapter remarks
17.8 Exercises
Bibliography
Index
Foreword
It is nearly a century ago that Alonzo Church introduced the lambda calculus, and over half a century ago
that John McCarthy introduced Lisp, the world’s second oldest programming language and the first
functional language based on the lambda calculus. By now, every major programming language including
JavaScript, C++, Swift, Python, PHP, Visual Basic, Java, ... has support for lambda expressions or
anonymous higher-order functions.
As with any idea that becomes mainstream, inevitably the underlying foundations and principles get
watered down or forgotten. Lisp allowed mutation, yet today many confuse functions as first-class citizens
with immutability. At the same time, other effects such as exceptions, reflection, communication with the
outside world, and concurrency go unmentioned. Adding recursion in the form of feedback-loops to pure
combinational circuits lets us implement mutable state via flip-flops. Similarly, using one effect such as
concurrency or input/output we can simulate other effects such as mutability. John Hughes famously stated
in his classic paper Why Functional Programming Matters that we cannot make a language more
powerful by eliminating features. To that, we add that often we cannot even make a language less
powerful by removing features. In this book, Graham demonstrates convincingly that the true value of
functional programming lies in leveraging first-class functions to achieve compositionality and equational
reasoning. Or in Graham’s own words, “functional programming can be viewed as a style of programming
in which the basic method of computation is the application of functions to arguments”. These functions do
not necessarily have to be pure or statically typed in order to realise the simplicity, elegance, and
conciseness of expression that we get from the functional style.
While you can code like a functional hacker in a plethora of languages, a semantically pure and lazy,
and syntactically lean and terse language such as Haskell is still the best way to learn how to think like a
fundamentalist. Based upon decades of teaching experience, and backed by an impressive stream of
research papers, in this book Graham gently guides us through the whole gambit of key functional
programming concepts such as higher-order functions, recursion, list comprehensions, algebraic datatypes
and pattern matching. The book does not shy away from more advanced concepts. If you are still confused
by the n-th blog post that attempts to explain monads, you are in the right place. Gently starting with the IO
monad, Graham progresses from functors to applicatives using many concrete examples. By the time he
arrives at monads, every reader will feel that they themselves could have come up with the concept of a
monad as a generic pattern for composing functions with effects. The chapter on monadic parsers brings
everything together in a compelling use-case of parsing arithmetic expressions in the implementation of a
simple calculator.
This new edition not only adds many more concrete examples of concepts introduced throughout the
book, it also introduces the novel Haskell concepts of foldable and traversable types. Readers familiar
with object-oriented languages routinely use iterables and visitors to enumerate over all values in a
container, or respectively to traverse complex data structures. Haskell’s higher-kinded type classes allow
for a very concise and abstract treatment of these concepts by means of the Foldable and Traversable
classes. Last but not least, the final chapters of the book give an in-depth overview of lazy evaluation and
equational reasoning to prove and derive programs. The capstone chapter on calculating compilers
especially appeals to me because it touches a topic that has had my keen interest for many decades, ever
since my own PhD thesis on the same topic.
While there are plenty of alternative textbooks on Haskell in particular and functional programming in
general, Graham’s book is unique amongst all of these in that it uses Haskell simply as a tool for thought,
and never attempts to sell Haskell or functional programming as a silver bullet that magically solves all
programming problems. It focuses on elegant and concise expression of intent and thus makes a strong
case of how pure and lazy functional programming is an intelligible medium for efficiently reasoning
about algorithms at a high level of abstraction. The skills you acquire by studying this book will make you
a much better programmer no matter what language you use to actually program in. In the past decade,
using the first edition of this book I have taught many tens of thousands of students how to juggle with
code. With this new edition, I am looking forward to extending this streak for at least another 10 years.
Erik Meijer
Preface
How is it structured?
The book is divided into two parts. Part I introduces the basic concepts of pure programming in Haskell
and is structured around the core features of the language, such as types, functions, list comprehensions,
recursion and higher-order functions. Part II covers impure programming and a range of more advanced
topics, such as monads, parsing, foldable types, lazy evaluation and reasoning about programs. The book
contains many extended programming examples, and each chapter includes suggestions for further reading
and a series of exercises. The appendices provide solutions to selected exercises, and a summary of some
of the most commonly used definitions from the Haskell standard prelude.
Acknowledgements
I am grateful to the University of Nottingham for providing a sabbatical to produce this new edition;
Thorsten Altenkirch, Venanzio Capretta, Henrik Nilsson and other members of the FP lab for our many
enjoyable discussions; Iván Pérez Domínguez for useful comments on a number of chapters; the students
and tutors on all of my Haskell courses for their feedback; Clare Dennison, David Tranah and Abigail
Walkington at CUP for their editorial work; the GHC team for producing such a great compiler; and
finally, Catherine and Ian Hutton for getting me started in computing all those years ago.
Many thanks also to Ki Yung Ahn, Bob Davison, Philip Hölzenspies and Neil Mitchell for providing
detailed comments on the first edition, and to the following for pointing our errors and typos: Paul Brown,
Sergio Queiroz de Medeiros, David Duke, Robert Fabian, Ben Fleis, Robert Furber, Andrew Kish,
Tomoyas Kobayashi, Florian Larysch, Carlos Oroz, Douglas Philips, Bruce Turner, Gregor Ulm, Marco
Valtorta and Kazu Yamamoto. All of these comments have been taken into account when preparing the
new edition.
Graham Hutton
Part I
Basic Concepts
1
Introduction
In this chapter we set the stage for the rest of the book. We start by reviewing the notion of a function, then
introduce the concept of functional programming, summarise the main features of Haskell and its
historical background, and conclude with three small examples that give a taste of Haskell.
1.1 Functions
In Haskell, a function is a mapping that takes one or more arguments and produces a single result, and is
defined using an equation that gives a name for the function, a name for each of its arguments, and a body
that specifies how the result can be calculated in terms of the arguments.
For example, a function double that takes a number x as its argument, and produces the result x + x,
can be defined by the following equation:
double x = x + x
When a function is applied to actual arguments, the result is obtained by substituting these arguments
into the body of the function in place of the argument names. This process may immediately produce a
result that cannot be further simplified, such as a number. More commonly, however, the result will be an
expression containing other function applications, which must then be processed in the same way to
produce the final result.
For example, the result of the application double 3 of the function double to the number 3 can be
determined by the following calculation, in which each step is explained by a short comment in curly
parentheses:
double 3
= { applying double }
3 + 3
= { applying + }
6
Similarly, the result of the nested application double (double 2) in which the function double is
applied twice can be calculated as follows:
double (double 2)
= { applying the inner double }
double (2 + 2)
= { applying + }
double 4
= { applying double }
4 + 4
= { applying + }
8
Alternatively, the same result can also be calculated by starting with the outer application of the function
double rather than the inner:
double (double 2)
= { applying the outer double }
double 2 + double 2
= { applying the first double }
(2 + 2) + double 2
= { applying the first + }
4 + double 2
= { applying double }
4 + (2 + 2)
= { applying the second + }
4 + 4
= { applying + }
8
However, this approach requires two more steps than our original version, because the expression
double 2 is duplicated in the first step and hence simplified twice. In general, the order in which
functions are applied in a calculation does not affect the value of the final result, but it may affect the
number of steps required, and whether the calculation process terminates. These issues are explored in
more detail when we consider how expressions are evaluated in chapter 15.
That is, we first initialise an integer variable total to zero, and then enter a loop that ranges an integer
variable count from 1 to n, adding the current value of the counter to the total each time round the loop.
In the above program, the basic method of computation is changing stored values, in the sense that
executing the program results in a sequence of assignments. For example, the case of n = 5 gives the
following sequence, in which the final value assigned to the variable total is the required sum:
total = 0;
count = 1;
total = 1;
count = 2;
total = 3;
count = 3;
total = 6;
count = 4;
total = 10;
count = 5;
total = 15;
In general, programming languages such as Java in which the basic method of computation is changing
stored values are called imperative languages, because programs in such languages are constructed from
imperative instructions that specify precisely how the computation should proceed.
Now let us consider computing the sum of the numbers between one and n using Haskell. This would
normally be achieved using two library functions, one called [..] that is used to produce the list of
numbers between 1 and n, and the other called sum that is used to produce the sum of this list:
sum [1..n]
In this program, the basic method of computation is applying functions to arguments, in the sense that
executing the program results in a sequence of applications. For example, the case of n = 5 gives the
following sequence, in which the final value in the sequence is the required sum:
sum [1..5]
= { applying [..] }
sum [1,2,3,4,5]
= { applying sum }
1 + 2 + 3 + 4 + 5
= { applying + }
15
Most imperative languages provide some form of support for programming with functions, so the
Haskell program sum [1..n] could be translated into such languages. However, many imperative
languages do not encourage programming in the functional style. For example, many such languages
discourage or prohibit functions from being stored in data structures such as lists, from constructing
intermediate structures such as the list of numbers in the above example, from taking functions as
arguments or producing functions as results, or from being defined in terms of themselves. In contrast,
Haskell imposes no such restrictions on how functions can be used, and provides a range of features to
make programming with functions both simple and powerful.
Summing numbers
Recall the function sum used earlier in this chapter, which produces the sum of a list of numbers. In
Haskell, sum can be defined using two equations:
sum [] = 0
sum (n:ns) = n + sum ns
The first equation states that the sum of the empty list is zero, while the second states that the sum of any
non-empty list comprising a first number n and a remaining list of numbers ns is given by adding n and the
sum of ns. For example, the result of sum [1,2,3] can be calculated as follows:
sum [1,2,3]
= { applying sum }
1 + sum [2,3]
= { applying sum }
1 + (2 + sum [3])
= { applying sum }
1 + (2 + (3 + sum []))
= { applying sum }
1 + (2 + (3 + 0))
= { applying + }
6
Note that even though the function sum is defined in terms of itself and is hence recursive, it does not
loop forever. In particular, each application of sum reduces the length of the argument list by one, until the
list eventually becomes empty, at which point the recursion stops and the additions are performed.
Returning zero as the sum of the empty list is appropriate because zero is the identity for addition. That is,
0 + x = x and x + 0 = x for any number x.
In Haskell, every function has a type that specifies the nature of its arguments and results, which is
automatically inferred from the definition of the function. For example, the function sum defined above has
the following type:
Num a => [a] -> a
This type states that for any type a of numbers, sum is a function that maps a list of such numbers to a
single such number. Haskell supports many different types of numbers, including integers such as 123, and
floating-point numbers such as 3.14159. Hence, for example, sum could be applied to a list of integers, as
in the calculation above, or to a list of floating-point numbers.
Types provide useful information about the nature of functions, but, more importantly, their use allows
many errors in programs to be automatically detected prior to executing the programs themselves. In
particular, for every occurrence of function application in a program, a check is made that the type of the
actual arguments is compatible with the type of the function itself. For example, attempting to apply the
function sum to a list of characters would be reported as an error, because characters are not a type of
numbers.
Sorting values
Now let us consider a more sophisticated function concerning lists, which illustrates a number of other
aspects of Haskell. Suppose that we define a function called qsort by the following two equations:
In this definition, ++ is an operator that appends two lists together; for example, [1,2,3] ++ [4,5] =
[1,2,3,4,5]. In turn, where is a keyword that introduces local definitions, in this case a list smaller
comprising all elements a from the list xs that are less than or equal to x, together with a list larger
comprising all elements b from xs that are greater than x. For example, if x = 3 and xs = [5,1,4,2], then
smaller = [1,2] and larger = [5,4].
What does qsort actually do? First of all, we note that it has no effect on lists with a single element, in
the sense that qsort [x] = [x] for any x. It is easy to verify this property using a simple calculation:
qsort [x]
= { applying qsort }
qsort [] ++ [x] ++ qsort []
= { applying qsort }
[] ++ [x] ++ []
= { applying ++ }
[x]
In turn, we now work through the application of qsort to an example list, using the above property to
simplify the calculation:
qsort [3,5,1,4,2]
= { applying qsort }
qsort [1,2] ++ [3] ++ qsort [5,4]
= { applying qsort }
(qsort [] ++ [1] ++ qsort [2]) ++ [3]
++ (qsort [4] ++ [5] ++ qsort [])
= { applying qsort, above property}
([] ++ [1] ++ [2]) ++ [3] ++ ([4] ++ [5] ++ [])
= { applying ++ }
[1,2] ++ [3] ++ [4,5]
= { applying ++ }
[1,2,3,4,5]
In summary, qsort has sorted the example list into numerical order. More generally, this function
produces a sorted version of any list of numbers. The first equation for qsort states that the empty list is
already sorted, while the second states that any non-empty list can be sorted by inserting the first number
between the two lists that result from sorting the remaining numbers that are smaller and larger than
this number. This method of sorting is called quicksort, and is one of the best such methods known.
The above implementation of quicksort is an excellent example of the power of Haskell, being both
clear and concise. Moreover, the function qsort is also more general than might be expected, being
applicable not just with numbers, but with any type of ordered values. More precisely, the type
qsort :: Ord a => [a] -> [a]
states that, for any type a of ordered values, qsort is a function that maps between lists of such values.
Haskell supports many different types of ordered values, including numbers, single characters such as
’a’, and strings of characters such as "abcde". Hence, for example, the function qsort could also be
used to sort a list of characters, or a list of strings.
Sequencing actions
Our third and final example further emphasises the level of precision and generality that can be achieved
in Haskell. Consider a function called seqn that takes a list of input/output actions, such as reading or
writing a single character, performs each of these actions in sequence, and returns a list of resulting
values. In Haskell, this function can be defined as follows:
These two equations state that if the list of actions is empty we return the empty list of results, otherwise
we perform the first action in the list, then perform the remaining actions, and finally return the list of
results that were produced. For example, the expression seqn [getChar,getChar,getChar] reads
three characters from the keyboard using the action getChar that reads a single character, and returns a
list containing the three characters.
The interesting aspect of the function seqn is its type. One possible type that can inferred from the
above definition is the following:
seqn :: [IO a] -> IO [a]
This type states that seqn maps a list of IO (input/output) actions that produce results of some type a to a
single IO action that produces a list of such results, which captures the high-level behaviour of seqn in a
clear and concise manner. More importantly, however, the type also makes explicit that the function seqn
involves the side effect of performing input/output actions. Using types in this manner to keep a clear
distinction between functions that are pure and those that involve side effects is a central aspect of
Haskell, and brings important benefits in terms of both programming and reasoning.
In fact, the function seqn is more general than it may initially appear. In particular, the manner in which
the function is defined is not specific to the case of input/output actions, but is equally valid for other
forms of effects too. For example, it can also be used to sequence actions that may change stored values,
fail to succeed, write to a log file, and so on. This flexibility is captured in Haskell by means of the
following more general type:
seqn :: Monad m => [m a] -> m [a]
That is, for any monadic type m, of which IO is just one example, seqn maps a list of actions of type m a
into a single action that returns a list of values of type a. Being able to define generic functions such as
seqn that can be used with different kinds of effects is a key feature of Haskell.
1.6 Chapter remarks
The Haskell Report is freely available from http://www.haskell.org. More detailed historical
accounts of the development of functional languages in general, and Haskell in particular, are given in [1]
and [2].
1.7 Exercises
1. Give another possible calculation for the result of double (double 2).
This letter irritated and annoyed Millie. Her hands were full enough
already without having Ellen's heart added to everything else. And
why need Ellen be so mysterious, warning her about people? That
was underhand. Did she suspect anybody she should speak out.
Millie walked about cautiously for the next few days lest she should
find herself alone with Ellen, when the woman looked so miserable
that her heart was touched, and one morning, meeting her in the
hall, she said:
"It was kind of you to write that note, Ellen. Of course we'll have a
walk one day."
Ellen stared at her under furious eyebrows. "If that's all you can
say," she exclaimed, "thank you for nothing. Catch me giving myself
away again," and brushed angrily past her. . . .
So on the morning after the theatricals down came the storm. It
began with the housekeeper, Mrs. Martin. Sitting under Eve Millie
examined the household books for the last fortnight.
"The butcher's very large," she observed.
"Honk!" Mrs. Martin remarked from some unprobed depths of an
outraged woman. She was a little creature with an upturned nose
and a grey complexion.
"Well it really is too large this time," said Millie. "Twenty pounds for a
fortnight even in these days——"
"Certingly," said Mrs. Martin, speaking very quickly and rising a little
on her toes. "Certingly if I'm charged with dishonesty, and it's
implied that I'm stealing the butcher's meat and deceiving my
mistress, who has always, so far as I know, trusted me and found no
fault at all and has indeed commented not once nor twice on my
being economical, but if so, well my notice is the thing that's
wanted, I suppose, and——"
"Not at all," said Millie, still very gently. "There's no question of any
one's dishonesty, Mrs. Martin. As you're housekeeper as well as cook
you must know better than any one else whether this is an unusual
amount or no. Perhaps it isn't. Perhaps——"
"I may have my faults," Mrs. Martin broke in, "there's few of us who
haven't, but dishonesty I've never before been accused of; although
the times are difficult and those who don't have to buy the things
themselves may imagine that meat costs nothing, and you can have
a joint every quarter of an hour without having to pay for it, still that
hasn't been my experience, and to be called a dishonest woman
after all my troubles and the things I've been through——"
"I never did call you a dishonest woman," said Millie. "Never for a
moment. I only want you to examine this book with me and see
whether we can't bring it down a little——"
"Dishonesty," pursued Mrs. Martin, rising still higher on her toes and
apparently addressing Eve, "is dishonesty and there's no way out of
it, either one's dishonest or one isn't and—if one is dishonest the
sooner one leaves and finds a place where one isn't the better for all
parties and the least said the sooner mended——"
"Would you mind," said Millie with an admirable patience, "just
casting your eye over this book and telling me what you think of it?
That's all I want really."
"Then I hope, Miss," said Mrs. Martin, "that you'll take back your
accusation that I shouldn't like to go back to the kitchen suffering
under, because I never have suffered patiently under such an
accusation and I never will."
"I made no accusation," said Millie. "If I hurt your feelings I'm sorry,
but do please let us get to work and look at this book together.
Time's short and there's so much to be done."
But Mrs. Martin was a woman of one idea at a time. "If you doubt
my character, Miss, please speak to Miss Platt about it, and if she
has a complaint well and good and I'll take her word for it, she
having known me a good deal longer than many people and not one
to rush to conclusions as some are perhaps with justice and perhaps
not."
Upon this particular morning Millie was to lose her temper upon
three separate occasions. This was the first occasion.
"That's enough, Mrs. Martin," she said sharply. "I did not call you
dishonest. I do not now. But as you seem incapable of looking at
this book I will show it to Miss Platt and she shall discuss it with you.
That's everything, thank you, good morning."
"Honk!" said Mrs. Martin. "Then if that's the way I'm to be treated
the only thing that's left for me to do is hand in my notice which I do
with the greatest of pleasure, and until you came, Miss, I should
never have dreamt of such a thing, being well suited, but such
treatment no human being can stand!"
"Very well then," said Millie, cold with anger. "If you feel you must
go, you must. I'm sorry but you must act as you feel."
Mrs. Martin turned round and marched towards the door muttering
to herself. Just before she reached it Victoria and Clarice entered.
Mrs. Martin looked at them, muttered something and departed
banging the door behind her.
Millie could see that Victoria was already upset, her large fat face
puckered into the expression of a baby who is not sure whether it
will cry or no. Clarice, her yellow hair untidy and her pink gown
trembling with unexpected little pieces of lace and flesh, was quite
plainly in a very bad temper.
"What's the matter with Mrs. Martin?" said Victoria, coming through
into the inner room. "She seems to be upset about something."
"She is," said Millie. "She's just given notice."
"Given notice!" cried Victoria. "Oh dear, oh dear! What shall we do?
Millie, how could you let her? She's been with us longer than any
servant we've had since father died and she cooks so well
considering everything. She knows our ways now and I've always
been so careful to give her everything she wanted. Oh Millie, how
could you? You really shouldn't have done it!"
"I didn't do it," said Millie. "She did it. I simply asked her to look at
the butcher's book for the last fortnight. It was disgracefully large.
She chose to be insulted and gave notice."
"Isn't that vexing?" cried Victoria. "I do think you might have
managed better, Millie. She isn't a woman who easily takes offence
either. She's taken such a real interest in us all and nothing's been
too much trouble for her!"
"Meanwhile," Millie said, "she's been robbing you right and left. You
know she has, Victoria. You as good as admitted it to me the other
day. Of course if you want to go on being plundered, Victoria, it's no
affair of mine. Only tell me so, and I shall know where I am."
"I don't think you ought to speak to me like that," said Victoria. "It's
not kind of you. I didn't quite expect that of you, Millie. You know
the troubles I have and I hoped you were going to help me with
them and not give me new ones."
"I'm not giving you new ones," Millie answered. "I'm trying to save
you. However——"
It was at this point that Clarice interrupted. "Now I hope at last,
Victoria," she said, "that your eyes are opened. It only supports
what I was saying downstairs. Miss Trenchard (Clarice had been
calling her Miss Trenchard for the last fortnight) may be clever and
attractive and certainly young men seem to think her so, but suited
to be your secretary she is not."
Millie got up from her seat. "Isn't this beginning to be rather
personal?" she said. "Hadn't we all better wait until we are a little
cooler?"
"No we had not," said Clarice, trembling with anger. "I'm glad this
occasion has come at last. I've been waiting for it for weeks. I'm not
one to be underhand and to say things behind people's backs that I
would not dare to say to their faces; I say just what I think. I know,
Miss Trenchard, that you despise me and look down upon me. Of
that I have nothing to say. It may be deserved or it may not. I am
here, however, to protect my sister. There are things that she is too
warm-hearted and kind-natured to see although they do go on right
under her very nose. There have been occasions before when I've
had to point circumstances out to her. I've never hesitated at what
was I thought my duty. I do not hesitate now. I tell you frankly, Miss
Trenchard, that I think your conduct during these last weeks has
been quite disgraceful. You have alienated all Victoria's best friends,
disturbed the servants and flirted with every young man that has
come into the house!"
This was the second occasion on which Millie lost her temper that
morning.
"Thank you," she said. "Now I know where I stand. But you'll
apologize please for that last insult before you leave this room."
"I will not! I will not!" cried Clarice.
"Oh dear, what shall I do?" interrupted Victoria. "I knew this was
going to be a terrible day the moment I got out of bed this morning.
Clarice, you really shouldn't say such things."
"I should! I should!" cried Clarice, stamping her foot. "She's ruined
everything since she came into the house. No one knows how I
worked at that horrible play and Bunny Baxter was beginning to be
so good, most amusing and knowing his part perfectly until she
came along. And then she turned his head and he fancies he's in
love with her and the whole thing goes to pieces. And I always said,
right away from the beginning, that we oughtn't to have Cissie
Marrow as prompter, she always loses her head and turns over two
pages at once—and now I've gone and made myself the laughing-
stock of London and shall never be able to act in public again!"
The sight of Clarice's despair touched Millie, and when the poor
woman turned from them and stood, facing the window, snuffling
into a handkerchief, her anger vanished as swiftly as it had come.
Besides what were they quarrelling about, three grown women?
Here was life passing and so much to be done and they could stand
and scream at one another like children in the nursery. Millie's
subconscious self seemed to be saying to her: "I stand outside you.
I obscure you. This is not real, but I am real and something behind
life is real. Laugh at this. It vanishes like smoke. This is not life." She
suddenly smiled; laughter irradiated all her face, shining in her eyes,
colouring her cheek.
"Clarice, I'm sorry. If I've been a pig to you all these weeks I surely
didn't mean to be. It hasn't been very easy—not through anybody's
fault but simply because I'm so inexperienced. I'm sure that I've
been very trying to all of you. But why should we squabble like this?
I don't know what's happened to all of us this year. We stood far
worse times during the War without losing our tempers, and we all
of us put up with one another. But now we all seem to get angry at
the slightest thing. I've noticed it everywhere. The little things now
are much harder to bear than the big things were in the War. Please
be friends, Clarice, and believe me that I didn't mean to hurt you."
At this sudden softening Clarice burst into louder sobbing and
nothing was to be heard but "Ouch! Ouch! Ouch!" proceeding from
the middle of the handkerchief.
All might now have been well had not Victoria most unfortunately
suddenly bethought herself of Mrs. Martin.
"All the same, Millie," she said. "It wasn't quite kindly of you to
speak to Clarice like that when you knew that she must be tired
after all the trouble she had with her acting, and I'm sure I thought
it went very nicely indeed although there was a little confusion in the
middle which I'm certain nobody noticed half as much as Clarice
thought they did. And I do wish, Millie, that you hadn't spoken to
Mrs. Martin like that. I simply don't know what we shall do without
her. We'll never get any one else as good. I'm sure she never spoke
to me rudely. She only wants careful handling. I do so detest registry
offices and seeing one woman worse than another. I do think you're
to blame, Millie!"
Whereupon Millie lost her temper for the third time that morning and
on this occasion very thoroughly indeed.
"All right," she said, "that finishes it. You can have my month's
notice, Victoria, as well as Mrs. Martin's—I've endured it as well as I
could and as long as I could. I've been nearly giving you notice a
hundred times. And before I do go let me just tell you that I think
you're the greatest coward, Victoria, that ever walked upon two feet.
How many secretaries have you had in the last two months? Dozens
I should fancy. And why? Because you never support them in
anything. You tell them to go and do a thing and then when they do
it desert them because some one else in the house disapproves. You
gave me authority over the servants, told me to dismiss them if they
weren't satisfactory, and then when at last I do dismiss one of them
you tell me I was wrong to do it. I try to bring this house into
something like order and then you upset me at every turn as though
you didn't want there to be any order at all. You aren't loyal,
Victoria, that's what's the matter with you—and until you are you'll
never get any one to stay with you. I'm going a month from to-day
and I wish you luck with your next selection."
She had sufficient time to perceive with satisfaction Victoria's
terrified stare and to hear the startled arrest of Clarice's sobs. She
had marched to the door, she had looked back upon them both, had
caught Victoria's "Millie! you can't——" The door was closed behind
her and she was out upon the silent sunlit staircase.
Breathless, agitated with a confusion of anger and penitence,
indignation and regret she ran downstairs and almost into the arms
of young Mr. Baxter. Oh! how glad she was to see him! Here at any
rate was a man—not one of these eternal women with their
morbidities and hysterias and scenes! His very smile, his engaging
youth and his air of humorous detachment were jewels beyond any
price to Millie just then.
"Why! What's the matter?" he cried.
"Oh, I don't know!" she answered. "I don't know whether I'm going
to laugh or cry or what I'm going to do! Oh, those women! Those
women! Bunny—take me somewhere. Do something with me. Out of
this. I'm off my head this morning."
"Come in here!" he said, drawing her with him towards a little poky
room on the right of the hall-door that was used indifferently as a
box-room, a writing-room and a room for Beppo to retire into when
he was waiting to pounce out upon a ring at the door. It was dirty,
littered with hat-boxes and feminine paraphernalia. An odious room,
nevertheless this morning the sun was shining with delight and
young Baxter knew that his moment had come.
He pushed Millie in before him, closed the door, flung his arms
around her and kissed her all over her face. She pulled herself away.
"You . . . You . . . What is the matter with every one this morning?"
He looked at her with eyes dancing with delight.
"I'm sorry. I ought to have warned you. You looked so lovely I
couldn't help myself. Millie, I adore you. I have done so ever since I
first met you. I love you. I love you. You must marry me. We'll be
happy for ever and ever."
There were so many things that Millie should have said. The simple
truth was that she had been in love with him for weeks and had no
other thought but that.
"We can't marry," she said at last feebly. "We're both very young.
We've got no money."
"Young!" said Bunny scornfully. "Why, I'm twenty-seven, and as to
money I'll soon make some. Millie, come here!"
She who had but now scolded the Miss Platts as though they were
school children went to him.
"See!" he put his hands on her shoulders staring into her eyes, "I
oughtn't to have kissed you like that just now. It wasn't right. I'm
going to begin properly now. Dear Millicent, will you marry me?"
"What will your mother——?"
"Dear Millicent, will you marry me?"
"But if you haven't any money?"
"Dear Millicent, will you marry me?"
"Yes."
She suddenly put her arms around him and hugged him as though
he had been a favourite puppy or an infant of very tender years. She
felt about him like that. Then they simply sat hand in hand on a pile
of packing-cases in the corner of the room. He suddenly put his
hand up and stroked her hair.
"Funny!" she said. "Some one did that the other day and I hated it."
"Who dared?"
She laughed. "No one you need be jealous of."
Poor Ellen! She felt now that she loved all the world, Clarice and
Mrs. Martin included.
"You won't mind if you keep our engagement dark for a week or
two?" he asked.
"Why?" She turned round and looked at him.
"Oh! I don't know. It would be more fun I think."
"I don't think it would. I hate concealing things."
"Oh, darling Millie, please—only for a very little time—a week or two.
My mother's away in Scotland and I don't want to write it to her, I
want to tell her."
"Very well." She would agree to anything that he wanted, but for a
very brief moment a little chill of apprehension, whence she knew
not, had fallen upon her heart.
"Now I must go." She got up. They stood in a long wonderful
embrace. He would not let her go. She came back to him again and
again; then she broke away and, her heart beating with ecstasy and
happiness, came out into the hall that now seemed dark and misty.
She stood for a moment trying to collect her thoughts. Suddenly
Victoria appeared out of nowhere as it seemed. She spoke
breathlessly, as though she had been running.
"Millie . . . Millie . . . Oh, you're not going? You can't be. . . . You
can't mean what you said. You mustn't go. We'll never, never get on
without you. Clarice is terribly sorry she was rude, and I've given
Mrs. Martin notice. You're quite right. She ought to have gone long
ago. . . . You can't leave us. You can do just what you like, have
what you like. . . ."
"Oh, you darling!" Millie flung her arms around her. "I'm sorry I was
cross. Of course I'll stay. I'll go and beg Clarice's pardon—anything
you like. I'll beg Mrs. Martin's if you want me to. Anything you like!
I'll even kiss Mr. Block if you like. . . . Do you mind? Bunny Baxter's
here. Can he stay to lunch?"
"Oh, I'm so glad!" Victoria was tearfully wiping her eyes. "I thought
you might have gone already. We'll never have a word again, never.
Of course he can stay, for as long as he likes. Dear me, dear me,
what a morning!"
The hoarse voice of Beppo was heard to announce that luncheon
was ready.
These are some letters that Millicent and Henry wrote to one
another at this time:
Telegram:
July 27.
Who's Him? Let me know by return.
Henry.