Vous êtes sur la page 1sur 222

Ptentice Hall Series in COmJIUitr Science

Series c<litors: Tony Hoare and Richard Bird

APT, K.R., From Logic Programming to Prolog .


ARNOLD, A., Finite Tnmsition Systems
ARNOLD, A. and GUESSARIAN, L,MatltematicsforComputerScience
BARR, M . and WELLS, C., Category Tlreoryfor Computing Science (2nd edn)
Introduction to Functional
BEN-ARI, M.,Principlesof Concurrentand Distributed l'rogramming
E!EN -ARl, M., Matlrematical Logic for Computer Science
I!EST, E., Semantics ofSequential and Parallel Programs
Programming using Haskell
BIRD, R., ~nd DE MOOR, 0 ., The Algebra ofProgrammirrg
BIRD, R., and WAD LER; P .,lmrodnction to Functional Programming
BOMAN, M., BUBENCKO, JR, J.A,JOHANNESSON, P. and WANGLER, B., Conceptual Modelling
BOVET, D.P. and CRESCENZI, P., Introduction to tlte T!reoryofComplexity
DE BROCK. B.. Foundations ofSemantic Databases
Second edition
BRODA, EISEN BACK, K.HOSHNEVJSAN and VICKERS, Reasoned Programming
BRUNS, G.,Distribtttcd SystenzsAnalysiswitlr CCS
BURKE, E. and FOXLEY, E., l..Qgic arrd Its Applications
DAHL, 0.-J., Verifiable Programming
ELDER, J., CompilerConstmction
Richard Bird
fREEMAN, T.L. arid PHILUPS, R.C.,l'arallel Numerica/Aigoritlrms
GOLDSCHLAGER, L. and LISTER, A., Compwer Science: A modern introtiuction (2nd edn) University of Oxford
HA YES,l. (ed.), Specification use Swdies (2nd edn)
HINCHEY, M.G. and BOWEN, J.P.,ApplicationsofFomral Met/rods
'' JIOARE, C.A.R., communicatirlg Sequential Processes
HOAR E, C.A.R. and GORDON,MJ.C.,Mec!ranized Reasoning and Hardware Design
IIOARE, C.A.R. nndJONES, C.B. (eds), Essay~ in Compwing Science
HUGHES, J.G., Darabase Technology: A software engineering approach
HUGHts, J.G., Object-oriented D8wbases
!NMOS LTD, Occam 2 Reference Manual ....__
JONES, C. B. nnd SHAw; R.C.F.(eds), Case Studies irr S,ystematic Software De>elopment
JONp;S, G.,Programmingin Occam
JONES, G. und GOLDSMITH, M.,Programmitrg in Occam 2
JONES, N.D., GOMARD, C.K. andSESTOFT, P.,Partia/ Evaluation lllrdAutomatic Program Generation
JOSEPH, M., PRASAD, V.R., andNATARAJAN, N.,/1 M11ltiprocessorOperating System
jOSEPH, M. (ed.), Real-time Systems: Specificmion, verification and analysis .,
KALDEW AIJ, A., Programming: Theclerivation ofalgoritlrms
KING, P.J.B., Compillerand Communications Systems Performatzc,: Modelling
LALEMENT, R., Computation as Logic
McCABE, F.G., High-levd Programmer's Guide to tire 68()()()
MEYER, B., Object-oriented SoftWare Construction
MILNER, R., Commrwication arul Concurrency
MORGAN, C., ~ogranrmingfrom Specifications (2nd edrz)
NISSANKE, N., Realtime Systenzs
OMOND!, A.R., ComputerAritiJm elic Syslems .
PATON, COOPER, WI LLIAMSandTRINDER, Database Programming Langr~ages
PEYTO N-JON ES, S. 1..; Tlte Implementation of Functionall'rogramming Ltingztages PEARSON
PEYTON-JONES,S. and LESTER,V., lmpiementins Fzmctional Languages .
POTT'ER, 13., SINCLAIR, J. and 11LL, D.,Anlntrotlrtclion to Formtzl Specificatiotl and Z (2nd cdn) \ Prentice
:l.OSCOE, A.W. (cd.), A Classical Mind: Essays inlwnourofC.A.R. Hoare
.
. Hall
:\OSCOE, A.W., Tire 17zeoryand t'rocticeo[Concurrettcy .
il.OZENUERG, G. and SALOMAA,A, Comcrstonesof Umlecidability
Harlow, England - London New York Boston San flanclsco Toronto Syd n :y Singapore Hong Kong
SLOMAN, M. and KRAMER, J., Di.~tribmcd Systems and Compwer Networks . Tokyo Sl'OUI Taipei New Delhi Cape lown Madzid Mexico City Amstcnam Munich Potis Milan
SHARP, R., Principles ofProtocol Design
Series listing contirtued at back of book

. .. . -
-~..~...,.,,, ,. _ _.___........ ...............~,.. :....... ,... ....,~.t..w t'... -u t ,,
' t
--
~. ' .. .. ... , f ' .. . ,, ....., . . . .. ... . .
~ ' ' .'
Pearson Educatio n Limited
Edinburg h Gate
Harlow
Essex CM20 2JE Contents
Eng land

Visit us on the W6rld !l7ida Wlib at:


hrrp://www.pean;oned.co. uk

0 Prentice Hall Europe 1998 L ..


Fjrst published 1988 q
This second edition pu~lished 1988 by l
Pre ntice Hall l----
All rights reserved. No pa.rt of this publication may be reproduced: st~red Preface to the second edition ix
in a retrieval syst~rn. or tmnsmitted, in any from, or by uny means, ~Jectronic,
lllechanic'al, photocopying, recording or otherwise without either t11e prior permissio n,
in writing, from the publisher or a licenu p.!rrnitting restricted copying in
i Fundamental concep ts 1

the United Kingdom issued by the Copyright Licensing Agency Ltd, 1.1 Sessions and scripts ' 1
90 1ouenham Court Road, London WI T 4LP. 1.2 Evaluation
4
1.3 Values 7
Printed and bound in Great Britain by
Bell & Bain ltd., Glasgow 1.4 Functio ns 9
1.5 Definitions 17
Library of Congress Cataloging-in-Publication Data 1.6 Types 21
1.7 . Specifications 25
Available from the publisher 1.8 Chap ter notes n
..
British library Cataloguing in Publicat ion Data 2 Simple dataty pes 29
.. .
2.1 Boolea ns 29
A catalogue record fo~ihis book is available from 2.2 Characters
the British library 35.
2.3 Enumerations ,. 38
ISBN-10: 0-13-484346-0 2.4 Tuples 41
JSBN-13: 978-0-13-4843469 2.5 Other types 46
lO 9 g 2.6 Type synonyms 48
07 06 . 2.7 Strings so
2.8 Chapter notes 55

3 Nnmbers 57
3.1 Narural numbers 57
3.2 Induction 63
3.3 The fold function 70
3.4 Haskell numbe rs 75
3.5 Example: the rationa ls 78
3.6 Example: linear and binary search 81
vii
ConteJJts Contents
vi
8.4 Bags 276
86
3.7 Church numbers Flexible arrays 281
89 8.5
3.8 Chap ter notes Que ues 287
8.6
8.7 Chap ter notes 292
91
4 Lists
91
4.1 Ust nota tion Infinite lists
295
95 9
4.2 Ust oper ations 9.1 Review 295
109
4.3 Map and filter 9.2 Infinite lis ts as limits 298
116
4.4 Zip
9.3 Proper ties of infin ite lists 303
120
4.5 The fold functions 9.4 Cyclic stru ctur es 306
128
4.6 Laws of fold 9.5 Example: the pape r-rock-scissors game 3 11
137
4.7 Cha pter notes 9.6 Stream-based interaction 319
9.7 Chap~er note s 322
139
5 Exam ples
139
5.1 Converting numbers to word s 10 Mon ads
325
142 325
5.2 Producing a Class list 10.1 Mon adic inter actio n
150
5.3 Arbi trary-precision arithmetic 10.2 Variation s on an eval uato r 334
161 343
5.4 Printing a calen dar 10.3 Monad laws
169 351
5.5 Text 'processing 10.4 Com bining monads
10.5 Chap ter note s 359
179
6 Trees , 179 361
6.1 Binary trees 11 Pars ing
187 361
6.2 Binary sea_r:ch trees 11.1 Sequ enci ng
192 364
6.3 Binary heap trees 11.2 Alternation
195 367
6.4 Rose trees 11.3 Repe titio n
202' 369
6.5 Example: Hu(fnian tree s 11.4 Efficiency
209 373
6.6 Example: Meertens ' num ber ll .S Cha pter note.s
21 5
6.7 Chap ter note s
375
217 12 An auto mati c calcu la.tor
7 Effic ienc y 12.1 Basic cons ider ations 375
217 381
7.1 Lazy evaluation
222 12.2 Expressio ns, laws, and calcu lations
7.2 Asym ptotic analysis 12.3 Matching s and subs tilut ions 387
228 391
7.3 Accumulating para mete rs 12.4 Subexpressions and re~niting
233 ..
395
7.4 Tup ling 12.5 Testing the calcu lator
239
'

7.5 Controlling space 12.6 Cha pter note s 407


244
7.6 Fusi on, finite differencing, and deforestation
249 409
7.7 Chap ter note s App endb<: Som e s tand ard func tjons
251 417
8 Absuacl da taty pes Bibli ogra phy
251
8.1 Basic co ncep ts
262 Index 425
8.2 Modules
264
8.3 Sets
Preface to the second edition

..
The second edition is a thoroughly reorganised and expanded version of the
first. Nevertheless, I have remained true to the aims of the original, as e>..'})ressed
in the opening two paragraphs in the preface to the first edition:
This is an introductmy textbook on programming in general and
functional programming in particular. No knowledg~ of computers
or .experience in writing programs is assumed. The book is the.refore
suitable for teaching a course in programming to first-year under-
. .. graduates, but it can also be used as an imroduction to functional
programming for students who are already experienced program-
mers.
In order to get the most ont of the book, the studem should know
some mathematics, or at least possess a general appreciation of the
principles of mathematic~ reasoning. Our primary aim in writing
this book is to convey a view of progranuning as a mathematical
activity, and mathematical reasoning lies at the heart of ow subject.
Functional programming involves notation and concepts of a kind
. which should be familiar to anyone with a little mathematical experi-
ence. For example, any student who has used the b~sic tl'igonomet-
ric functions to formulate problems in geometry, and has applied
simple trigonometric laws and identities to derive solutions to these
problems, will soon appreciate tha t a similar activity Is being sug-
gested for computational problems and their solution by functional
programs. It follows that the kind of mathematical understanding
required is not very complicated or specialised, just the general aQU-
ity to follow manipulation s of formulae through applyiitg algebraic
laws, and the appreciation of why such manipillatio.ns can be useful
in the task of solving practical problems.
:.
::'.
.
Preface to (/Je second edition xi -: .
X Preface to d1e second edition

Advice to the instructor .


One major change in the present edition has been to use a specific language, ,
Haskell, to express fw1Ctional programs. At the time the fust edition appeared, .
the d esign of lazy functional languages was in a s tate of flux, with a number of The second edition has grown by over a hundred pages, and the material prob~
closely re~atcd but different dialects competing for attention. We tried to take ably cannot be fully covered in a single course. A first course in functional pro-
account of th e changing state of affairs by using a neutral notation, similar to gramming can be based on the first six chapters, with Chap ter 3 being treated
but not iden tical with Miranda (Miranda is a trademark of Research Software more lightly than the others. In our e>.:perience, studen ts only begin to appreci- .

Limited), one of the more popular lazy functional languages at that time. Ten ate what a fWlctional style of programming can offer when the subject of lists is
years later, the situation has stabilised somewhat in that Haskell, a relative of broached. The remaining material can be adapted for a second course on pro-
Mark Jones' popular language Gofer, is now widely regarded as the language of gramming, emphasising modularity and data structures. The material has also
choice among lazy functional programmers. In particular, HUGS (the Haskell been used for a cowse on algorithm design and efficiency, as well as courses ;

Users' Gofer System) was designed as a simple interactive system suitable for on the mathematics of program proof and synthesis. ;.

use on PCs with modest capabilities. References to Haskell and HUGS, and how Formal teaching should be supported by laboratow and. practical work, and
to get hold of them, are gtveri at the end of Chapter 1. The version of Haskell many of the examples and case studies have been used as the basis of practical
we use in this book is Hasl<ell1.3 (and also HUGS 1.3). Haskell itself is currently projects with considerable success ..Most of the individual sections also contain ,.
undergoing modest evolutio n and standar disation, and it is intended.to publish a variety of exercises for selt study. It is planned to publish answers to these
details of Standard Haskell in the summer of 1998. However, since we do not t:J.uestions on the Web; sec the URL
cover all.details. of Haskell, It is unlikely that any proposed standardisation w!ll
http://www.comlab.ox.ac.uk/oucl/p ubl ications /books/functional/
affec t the te((t in any s ignificant way. . . '
:rhe second major change concerns the organisation of material. The present This web site will also contain many of the programs listed in the text, as well
edition inttoduces the idea of defining new datatypes early on. The core of as pointers to Haskell and HUGS, and to additional material.
the first part of the book is now devoted to the study of three recursive data-
types: natural numbers, lists, and ttees. Each datatype is introduced along wilh
the idea of defining r~cursive functions over the datarype, and also along with Acknowledgements
the method of proof by induction to establish properties of these recursively '

defined functions. Thus, three important ideas are introduced as different as- This edition, like the first, took rriore time than expected. My greatest debt of
pects of a single coheren t whole. The examples and case studies have also been gratitude is to Phil Wad.ler. Apart from the reasons cited above, he generously
allowed me to complete the text by myseii. The second edition was writren
...
changec\ or updated. There arc compietely new chapter s on abstract datatypcs,
efficiency, and monadic functional programming. The bibliography has expan- during a sabbatical year from teaching and administrative du ties, and l am
ded considerably, and there now are brief chapter notes at the end of each truly grateful to the University of Oxford and Lincoln College for supporting .
chapter. h m:d-prcsscd academics in this way.
The third major change is that, owing to a number of commitments and The book has benefited enormously from the continued support, enthusi-
a chartge of environment, my co-~uthor Philip Wadler could only give limited asm, and constructive advice of colleagues and students, both at Oxford and
assistance in the preparation of the text. Ikprovided 'detailecl:cornments and other universities. The suggestions of colleagues in the Programming Research
sugge~tions on an early draft of the first six chapters, as well as material that Group at Oxford have been par ticularly relevant, s ince they have been per-
formed the basis ol' the chapter on monadic programming. Although his major sonally responsible .f or te.ach.i..ng the material to their tutorial studen ts while
contributions to the understanding of functional programming over the past a lecture course was in progress. Other people who have ~\>T.itten or emailed
ten years permeate the book, 1 alone take responsibility for errors of under- Phil or me with suggestions, or simply to point out typos and silly mistakes in
standing, mis takes, or inappropriate emphasis. lf and when the need for a the first edition, include: Nils Andersen, r=ran.klin Chen, Sharon Curtis, Martin
third edition arises, l hope t~1at we can again join forces to produce it. Filby, Simon Finn, Jeroen Fokker, Maar ten Fokkinga, j eremy Gibbons, R9bert
Giegerich, Kevin Hammond, Gerard Huet, Michael Hinchey, Tony Hoare, lain
Houston, John Hughes, Graham Hutton, Stephen Jarvis, Gera.i.nt Jones, Mark
~
'
'

I xii Preface to the second edition

Jones, John Launchbury, Paul Licameli, David Lester, lain MacCullum, Ursula
Chapte~ 1
Martin, Lambert Mcertens, Ertk Meijer, Quentin MUler, Oege de Moor, Chris Oka-
saki, Oskar Permvall, Simon Peyton Jones, Mark Ramaer, Hamilton Richards, .Fundamental concep ts
Dan Russell, Don Sailllella, Antony Simmons, Deepak D'Souza, John Spanonda-
kis, tvlike Spivey, Joe Stoy, Bernard Sufrin, Masato Takeichi, Peter Thiemann,
David Twner, Colin Watson, and Stephen Wilson. In particular, Jeremy Gibbons
and Rob Hoogerwoord read drafts of the manuscript and suggested a number
of corrections.
I would also like to thank Jim Davies for getting my ~TEX in~o shape, and
Jackie Harbor of Prentice Hall for .continued support. The text was prepared
on an Apple Macinto.s h Powerbook 180, using BBEdi as~ editor, and Oift;X as
. the L"f&X p~ocessor. All three systems were a delight to use.

Oxford
' I Programming in a functional language consists of building definitions and us-
Richard Bird
'
December, 1997 ing the computer to evaluate expressions. The primary role .of the programmer
is to construct a function to solve a &riven problem. This function, ~-vhich ~ay
involv'e 'a number o.f subsidiary ftmctions, is described ina notation that obeys
. normal mathematical principles. The primary role of the computer is to act
as an evaluator or calculator; its job is to evaluate expressions anci print the
results. In this respect the compu ter acts much like an ordiriary pocket calcu-
lator. What distinguishes a functional calculator from the humbler variety is
.'t the programmer's ability to make definitions to increase its powers of calcula-
:7I tion. Expressions that contain occurrences of the names of func tions defined
'qy the programmer are evaluated using the given definitions as simplification
I;
! mles for converting expressions to printable form.
' ~

'!
I 1.1 Sessions and scripts
To illustrate the idea of using a computer as a calculator, imagine we are sitting
I
in front of a terminal screen displaying a prompt sign
l
~
I ?,
I in a Window. We can now type an expression, followed by a newline character.,
and the computer will respond by displaying the result of evaluattilg the ex-
pression, followed by a new prompt on a new line, indicating that the process
can begin again with another expression.
One kind of expression we might type is a number: ..
? 42
42
...

2 1 I Fundame nw l concepts 1. i I Sessions and srripi'S 3

Here, the computer's response is simply to redisplay the number we typed. ? square 14198724
Th.e decimal numeral 42 is an expressi on in its simplest possible form and 201 578206334976
evalualing it results in no further simplification.
? square (smaller (5 , 3 + 4))
We might type a slightly more interesting kind of expression:
25
? 6X 7
42 Integer arithmetic is exact: tl'iere is 110 restriction on
N olice, ii1 passing, 't hat
the sizes of integers that can be computed.
Here, the compute r can simplify the expression by performing the multiplica-
tion. In this book we will use common mathematical notations for writing ex-
a
The purpose of definition is to introduce a binding associating. a given
name with a given deffuitio n. A set of bindings is called an en'virorui1ent or
pressions; in particular, the multiplication operator will. be denoted by the sign context. Expressions are always evaluated in some context and cait contain oc-
x, rather than the asterisk * used in Haskell.
cmrence s of the names t'ound in that cot'! text The Haskell evaluator v.ill use the
We will not elaborate for the moment on the possible forms of numerical definitio ns associat ed with these names as r ules for simplifying expressions.
and other kinds of expression that can besubmitted for evaluation; the import- Some express ions cim be evaluated without having to provide a corite~t. In
ant point to absorb now is' that one can jus t type eXpressions and have .them Haskell a number of operations are given as p rirnitive In the sense 'that the ruJes
evaluated. This sequence of intcrac'tions between user and computci is called of simplification are built into the evaluator. For example, the basic operatio ns
a session. of arithmetic arc provided as prinlitive. Other commonly useful operations are
The .second and intellectually more challenging aspect of functi~nal pro- predefined in special scripts, called preludes or libraries, that can be loaded
grillnrning consists of building definitions. A list of definitio ns is called a script. when we s tart the computer.
Here is an example of a simple script:
At any s tage a pro~ammer can return to the script in order to add or modify
square Integer - In teger definitio ns. The new script can then be resubmitted to the evaluato r to provide
square x = XX X a new context and another s.ession started. For example, suppose we return to
the above script and change it to read:
smaller (Integer, Integer) - Integer
smaller (x,y} = if x < y then x else y sq11are .... Float - Float
squarex = XXX
rn this script, two function s named sqtwre and smaller have been def4ted. The ' ....
function square tal<es an integer as argument and returns its squan::.; the func (Float, Float, Float) - Float
i
delta
tion smalle,r takes a pair of integers as argumen t and retUrns the smaller value. delta (a, b, c) - sqrt (square b - 4 x a x c)
The syntax for making defini tions follows that of Haskell, the programming
language adopted in this book, and will be explained in due course. Notice,
'i The type assigned to square has been changed to Float - Float. ln Haskell the
however , that definitions are written as equations bet\veen certain kinds of ex type Floa( consists of the single-precision floating-point numbers . The function
pression; these expressions can contain variables, here denoted by the symbols delta depends on a predefined function sqrt for taking square roots.
x and y . Furthermore, each function is accompanied by a description of its rype; Having resubmi tted the script, we can enter a new session and type, for
for example, (Integer, Integer) - Integer describes the type of functions that example :
take a pair of integers as argumen t, and deliver an integer as result. Such type ..
descriptions are also called type assignm ents or cype signatures. ? dell'a (4 .2, 7, 2.3)
Having created a script, we can submit it to the compute r and enter a session. 3.2187
For exall!-ple , the following session is now possible:
To surrunarise the importa nt points made so far:
'?square 3 768
14197824 Scripts are collections of definitions supplied by the progratruner.
'

'
'I
4 I
I 1 Fundamental concepts 1.2 I Evaluation 5
Definition sare expressed as equations between certain kinds of expres- expressions involving square. The expression '49' cannot be further reduced,
.sion and describe mathematical flmctiqns. Definitions are accompanied so that is the result displayed by the computer. An expression is said to be
by type signatures. can onical, or in normal form, if it cannot be further reduced. l-Ienee '49' is in
During a session, expressi~ns are submitted for evaluation; these expres- normal form.
sions can contain refer'ences to the !'unctions defined in the script, as well Another
. reduction sequence for square ( 3 + 4). is .
as references to other functions defined in preludes or libraries.
. - square (3 + 4)
In Haskell, at least two. different- kinds of munber can be used in com-
{def.injtion of square}
. I putations: arbitrary-precision integers (clements of Integer}, and single-
precision floating-point numbers (elements ofF/oat). (3+4)x( 3+4)
= {definition of + (applied to.first term))
Exercises
7 X (3 -1: 4) .
1.1.1 Using the flll}'ction square, design a ftinctio~ 'quad that raises its argu- !definition of+)
ment to the fourth power. ,
- . 7x7
1.1.2 Define a function greater that retums the {,'l'eater of its two arguments .
{definition of x)
1.1.3 Define a function for computing the area of a circle with given radius r
"' (use 22/7 as an approximation torr). 49
In this reduction sequence the rule for square is applied first, but the final result
1.2 Evaluation , . is the same. A characteristic feature of functi'onal programming is that if r.vo
different reduction sequences both tenltinare,then they lead to the same result. .
:.

.j
The computer evaluates an expression by reducing it ro its simplest equivalent In other words, the meaning of an expression is its value and the task of the
form and displaying the result. The terms evaluation, simplificarion, and r e- computer is simply to obtain it.
,.
duction Will be used interchangeably to describe this process. To give a brief Letus give another example. Consider the script
flavour, consider the expression square (3 + 4); .one possible sequence is
:: three .. Integer - Integer
,.... squarf? (3 + 4) chreex = .. . 3
I

{definition of + ) infinity .. Integer


square?. infinity - infinity + 1
= {definition of square} It is not d ear what integer, if any, is defined by the second equation but the
7x7 computer can neverthele ss use the equation as a rewrite rule. Now consider
simplification of three infinity. If we try to simplify infinity first, then we get
{definition of x} the reduction sequence
49
.; three infiniey
The first and third steps refer to use of the btLilt-in rules for addition and multi-
:
(de1'initioo of infinity} .
plication, while the second step refers to the use of the rule defining square
supplied by the programmer. That is to say, the definition square x = x x xis three (infinity + l)
interprete d by the computer simply as a left-to-right rewrite n tle for reducing = (definition of infinity}
.,.
:'
...

1.3 I Values 7
6 1 I Fundam emal concepts

termin ate for all given expressions. (Hint: Define an approp riate notion of
~.

three ((infini ty .+ 1) + 1)
expres sion size, and show that each reduction step does indeed reduce size.)
{and.so on ...}
1.2.4 Carrying on from the previous question, suppos e an extra syntactic rule
is added to the language: (iii) if e1 and ez are expressions, then so is add (e1, e2).
The corresp onding reducti on rules are
This reduction sequence does not terminate. If, on the other hand, we try to
simplify three first, then we get the sequence add (zem, ez) - ez
three infinity .
add (succ (e1 ),. ez). = succ(a dd(e,,e 2))
add (pred (e, ) , e2) - pred (add (e1, e2)
= {definition of three}
3 SimplU'y the expres sion add (succ (pred (zero)) , zero).
Count the number of differen t ways the reduction rules can be applied to the
This sequence termina tes in one step. So, some waysof simplifying an expres- above express ion: Do they always lead to the same final result?
sion may terminate while others do not. In Chapte r 7 we v.ill describ e a re-
duction strategy, called lazy evaluation, th(\t guaran tees termina tion whenever
,;
1.2.5 Now suppos e we define the size of an .expres sion by the following rules:
termina tion is possibl e, and is also reasona bly effiCient. Haskell is a lazy func- size (zero) :: 1
tional language, and we will explore what conseq uences such a strateg y has in = 1 +size (e)
size (succ (e))
the rest of the book. Howev er, whichever strateg y is in force, the essential point .;
size (pred (e)) = 1 +size (e)
is that e~ressions are 'evaluated by a conceptually simple proces s of substi-
tution and simplification, using both primitive rules and rules supplied by the size (add Ce1. e2)) - 1 + 2 x (size (eJ) +size Ce2))
progra mmer iii the form of definitions. Show tha,t applica tion of any of the five reducti on ntles given above reduces
expr~ss ion size. Why does tWs prove that the proces s of reducti on must always

Exercises
~
. terminate f?r any given in~tial_exprcssion?

1.2.1 lnorde r tO evaluate X X y, the expressionS X and Y are reduce d tO norma)


form and then multiplication is performed. Does evaluation of square infinity '
1.3 Values
terminate? ' In functional programming, as in mathematics, an express ion is used solely
1.2.2 How many terminating re.ductlon sequen ces are there for the expression . to describe (or denote) a value. Among the kinds of value an expres sion may
square (3 + 4)? . denote are include d: numbe rs of various kinds, truth values, characters, tuples,
functions, and lists. All of these will be described in, due course. As we will
,

1.2.3 Imagine a language of expressions for repres.enting integers defined by


,

also see, it is possibl e to introduce new kinds of value and define operati ons
'

the syntax rules: (i) .z.ero.is an express ion; (ii) if e is an expression, then so are
succ (e) and pred (e). An evaluat or reduces express ions in this language by
for generating and manipulating them.
It is import ant to distinguish between values and their represe ntation s by
applying the followi ng rules repeatedly until no longer possible:
.,,, express ions. The simplest equivalent form o.f an expression, whatever that
succ (pred (e)) = e I may be, is not a value but a represe ntation of it. Somewhere, in outer space
pred (succ ( e)) - e perhaps, one can imagine a univers e of abstrac t values, bur on earth they can
only be recogn ised and manipulated by concrete represe ntations. There may
SimplU'y the expression succ (pred (succ (pred (pred (zero)) ))). ,i
be many representation s for one and the same value. For exampl e, the abstrac t
nun1ber forty-nine can be represe nted by the decimal numeral 49, the roman
'
in how many ways can the reducti on rules be applied to tbis expression? Do
they all lead to the same final resUlt? Prove that the process of reduction must numeral XLIX, or the expression 7 x 7. Computers usually operate with the
8 1 I Fundamental concepts 1.4 I Functions 9

binary represem(ltion of numbers in which forty-nine is represented by a certain It is possible, conceprually at least', to applyfunctions to .1. For example,
bit-pattern consisting of a number of Os followed by 110001. with the definitions three x = 3 and square x = x x x, we have
The evaluator for a functional language prints a value by ptinting its canon- ? three infinity
ical representation; tllis representation is dep endent bmh on the syntax ~:,riven
3
for forming expressions, and the predse definition of the reduction rules.
Some values have no canonical representations, for example function val- ? square infinity
ues. It is difficult to imagine a canonical representation for the function sqrt :: {Interrupted!}
Float - Float; one can describe tllis function in various ways but non~ of the
descriptions can be regarded as canonical. Other values may have reasonable In the first evaluation the value of infinity was not needed to complete the cal-
representations, but no finite ones. For example, the number ~ has no fini te c~,uarion, so it was never calcul~ted. This is a consequence of the lazy evaluation
decimal representation. It is possible to get a computer to print out the decimal reduction strategy mentioned earlier. On the othei hand, in the second evalu-
expansion of rr digit by digit, but the process will never terminate. ation the value of infinity is needed to complete the computation: one cannot
... compute x x x witho.ut knowing the value of x. Consequently, the evaluator
For' some expr'essions the proce;s of 'r eduction never stops and never pro-
duces \any result. For exan1ple, the expression infinity defined in the previous goes into an infinite reduction s~quence in an attempt ro simplify infinity to
section leads to an infinite reduction seqi.lence. Recall. that the definition was nqrmal form. Bored by waiting for an answer t):lat we know will never come, we
.,
bit the the internipt key.. . '
Iff' 1. = 1.; then f' is said to 'be a striCI' function; ~therwise it isnohstricc.
'
in{inity Integer '
infinity - infinity+ 1 ,,., Thus. sq~rare is a strict function. wllile three iS nons trier. Lazy evaluation allows
nonstrict functions to be dcftlled, some other strategies do not.
Such expressions do not denote well-defined values in the normal mathemat-
ical sense. As another example, assunling the operator 1 denotes numerical .. Exercises
division, returning a number of type Float, the expression 110 does not denote
a well-defined floating-point number. A request to evaluate i/O may cause 1.3.1 Suppose we define mtlltiply by
the evaluator to respond \'Vith an erTor message, such as 'attempt to diVide by (Integer, Integer) - Integer
., multiply
zero', or go into an infinitely long sequence of calculations without producing
multiply (x, y) = if x :: 0 then 0 else x x y
any result.
In order lhat we can say that, without exception. every syntactically well- The symbol ::is used for an equality test between two integers. Assume that
formed expression denotes a value, it is converuent to introduce a special sym- evaluation of e 1 == e2 proceeds by reducing e1 and e2 to normal form and testing
bol 1. , pronounced 'bottom', to stand for the undefined value of a particu- whether
. . nvo results are identical. Under lazy evaluation, what would
the . be the
lar type. In particular, the value of infiniry is the undefined value 1. of type value of multiply (0, infinity)? What would be the value of mulliply (infinity, 0)?
Integer and 1 I 0 is the undefined value 1. of type Floar. Hence we can assert . . .
1.3.2 Suppose we define the function h by the equation hx (gx) . Show that
I

that 110 = 1..


= (

The computer is not expected to be able to produce the value 1.. Confronted
r
if a:nd .g are both s trict, then so is h.
with an expression whose value is 1.. the computer may give an error message,
or i t may remain perpetually silent. The former situation is detectable, but 1.4 Functions
the second one is not (after all, evaluation might have terminated normally the
., Naturally enough, the most important kind of value in ftmctional programming .
moment after the programmer decided to abort it). "tlms, 1. is a special kind
of value, rather like the special value oo in mathematical calculus. Like special
'
,' ' is a function value. Although we cannot display a ftmction value, we can apply
values in other branches of mathematics, 1. can be admirred to the universe functions to argt.lrnents and display the restilts (provided, of c9urse, that' the
of values only if we state precisely the properties iris required to have and its result can be displayed). Mathematically speaking, a funttion f is a rule of
relationship With other values. correspondence that associates each element of a given type A with a un:ique
10 I I Fundamental conceprs 1.4 I Fupctions 11
, .
., .
element of a sec~nd type B. TI1e. type A is called the source Lype, and B the resp_ondence ,between ar~:,11.unents and results, not how this corre~pondence is
rarget lype of t~e function. We express this in.fonnation by writing f ::A- B.. described. -
This formula asserts that the type of f is A - B. In othe.r words, the type For.instance, we can define the function whid1 doubles its argument in the
expression A - B denotes a type whenever A and B do, and describes the type following two ways:
of functions from A to B. For example, we have already_met the functions

i double, double' lnl'eger .., Integer
three Integer - Integer double,,.; . - x+x
square Integer -:- Integer qouble' ,x = 2 XX
delta .. (Float, Float , Float) - Float
The two definitions describe ilifferent procedures for obtaining the correspond-
The definition of three describes a rule of correspot1dence that associates every ence, one invqlving adCUtio'u and the other invoiving multiplication, but double
in~eger, including the special integer 1.., with the single number 3. The definition and double' det'ine the samefunction
~ . value and we. can assert. double = double'
.

of square a~sociates every well-defined integer with its squa(e, and associates as a mathematicru truth, Regc.uded as procedures for ey~uation, one definition
l. with the nndefined integer 1.. may be n1ore orless 'efl'icient' tban tl1e other, but the notion of efficiency is
A function f ::A - .B is said to tal<e arguments in A and retUrn results in B. :: not one tlwt can. be attached to (unction values, themselves. This is not to say,
If x denotes an element of A, then we write f(x), or just f x, to denote th~ re~ult
:'
of course, that efficiency is not important; after all, we want expressions to be
of applying the function f to x. This value is the unique elen~:ent of B associated evaluated in a reasonable an1ount of tune. The point is that efficiency is an
with x by the rule of correspondence for f. The former-notation, ((x), is the intensional property of definitions, not an extensional one ..
one normally employed in mathematics to denote functional application, but f-xtellSiOnality means that we can prove ( = g by proving that f X = g X for
the parentheses are not really necessary and we Will USe the second form, { X, ,. all x. Depending on the definitionS off' and g, we may also be able .to prove
instead. Ori the other hand, parentheses are necessary when tl:le argument is ~
f = g .directly. The former kind of proof is called an applicalive or point-wise
not a simple constant or variable. For example, we have to writ.e square (3 + 4) " style of proof, while the latter is called a point-free style. We will see examples
(ifthat is what we mean) because square3 + 4 riteans (square 3) + 4. The reason of both styLes during the cowse of the book.
why this is so is because application has a higher precedence than + (see belmv).
. Similarly, we have to \Nrite square (square 3) and not square square 3.
1.4.2 Currying
We \-vill. be careful never to confuse a fw1ction with its application to an
rut.tument. ln some mathematics texts one often finds the phrase 'the function A useful device for reducing the number of pruentheses in an expression is
f(x)', when what is really meant is 'the function f'. ~-such texts, functions the idea of replacing a structur'ed argument by a sequence of simpler ones..To
rue rarely considered as values which may themselves be used as arguments illustrate, consider again the function smaller defined earlier:
to other functions and the traditional way of spea)<ing causes no confusion..' In
. functionat'programming, however, functions are values with exact~y the s.ame ., smaller (Integer, Integer) - Integer
status as all other values; in particular, they can be passed as argume~ts to smaller (x, y) = if_x s y then x else y
~ther functions and returned as results. Accordingly, we cannot afford to be
casual about the difference between a function and the result of applying it to ;
The ft.inctiOll smallei takes a single argument consisting of a pair of .integers,
ru1 C).rgument.
: '

:
and returns an integer. Anotbet: way of defll.ling eSsentially the same ftmction
is to write
'
. 1.4.1 E.'Ctensionality ' smallerc .. Integer - (Integer - lnteger)
smallerc xy - if x s y then x else y
Two functions are equal if .they give equal results for equal argunients. Thus,
f = g if and. only if f x = g x for all x. This principle is called the principle .,' The fwKtionsmal/erc takes two argurnems, one after the other. More precisely,
ofexrensionality. It says that the il:n:POrtant thl.rig ' ab~ut a fimction is the cor smallerc is a fw1ction that takes an integer x as argument and returns a function

'.
,

..
..
12 1 I Fundamental conccprs .1.4 I Ftmctions 13

sma/lerc x; the function smallerC'X takes an lnteger y as argument and returns Ti1e function quad ntises its .argurrient to rhe fourth power. Suppose, on the
other hand, that we had defined rwice by
.!.
an integer, namely the smaller of x andy.
Here is another example: twice (Integer- Integer .Integer ) -Integer
plus (Integer, integer) - Integer twice({, X) = { (f X)
plus (x, y) = x+y
Now there is no way we can \)arne the func.tion that applies a function twice
without also mentionin g the argument to which the second function is applied.
'
plusc integer - (Integer - Integer)
- x +y Instead of saying 'quad, ~here quad = rwice square', we would have to say
plusc x y
'quad, where quad x = twice (square, x) for all x'. The second style is Clumsier.
For each integer x the function plusc x a dds x to an integer. In particular,plusc 1 !
If we want to, we can always convert an uncmried function Jnto a curried
is the successor function that increments its argument by 1, and pfusc 0 is the " one. The function curry takes an uncurried flmction and returns a curried
identity function on lntegers. version of. the same function; Its definition is
This simple device for replacing strUctured arguments by a sequence of
:: ((ex, /3)- y) - (ex- /3- y)
simple' ones is knowri as currying, after the American logician Haskell B. Curry
curry
(after whom rhe programming language ' Haskell'is 'also named). for currying [o r
curry xy = f (x,y)
. '
work properly in a consistent manner, we require that the operation of func The type signature of curry will be explained in Section 1.6. Note that curry is
tiona) application associates to the left in expressions. Thus, .< itself an example of a cunied function: curry takes three arguments, one after
smallerc 3 4 means (smallerc 3) 4 the other. We can now refer to curry f as the curried version of(. for example,
means (plusc x) y J plusc = curry plus.
plusc xy '
It is left as an exercise to define a fun<;tion uncurry that goes the other way
square square 3 means (square square) 3 <)'
and converts a cunied function into a noncurrie d one.
,, '

.,.
~:i
Although square square 3 is a syntactically legal expression , it makes no sense
~;I becausesquare takes a single integer argumenr, not a function followed by J 1.4.3 Operators
.. , an lnteger. In fact, the expression will be rejected by the computer hccause .,
. '
it carmot be assigned a sensible type. We will return to this polnt in a later Some functions are written between t4eir (two) arguments rather than preccd
'. ' '
:)
ing them. For example, we write
;,. ,; section. .~ .
~
There are two advantages of curryil1g functions. Firstly, etirrying can help ',_ 3 + 4 'r ather than plusc 3 4
to reduce the number of parentheses that have to be written in expressions. t
3 5 4 rather than leq 3 4
Secondly, curried functions can be applied to one argument only, giving another
(
!
.. .
A func tion written using infix notation is called an operator. To remove. am
function that may be useful in its own right. For instance, consider the function
.~

\'
twice that applies a function twice in succession: biguity, special symbols are used to denote operators. Occasionally, we will
;
.'

use names rather than symbols for operators, but write them in bold font For
(Integer - Integer) - (Integer -:- Integer) .,
example, we write (15 div 4) and (15 mod 4), using names in bold font for 'the
twice ;

f {f x)
v

'
twice{ x - operators associated with integer division and remainder. The Haskell conven
This is a perfectly legitimate definition in Haskell. The first argument to twice ' tion is to enclose the name ln back quotes; for example, in Haskell one woul'd
is a function (of type Integer - Jnceger), and the second argument is an integer. ' . write (15 'div' 4) and (15 'mod' 4).
Applying twice to the first argument (, we get a fLmction twice f that applies f Enclosing an operator in parenthes es converts it to a curried prefix function
twice. We can now define, for instance,
,,
that can be applied to its aq,>Umenrs like any other function. For example,

quad Integer - Integer (+)34 - 3+4


quad = twice square (5} 3 4 = 35 4
..
.~

.',
.."', .
.'

14 1 I Fundamental coni:epis IA/ Functions 15

. In particular, plusc ;, ( + ). Like any oth~r name, an operator enclosed in paren Thus, 1 + 3 I 4 x 2 = 1 + ((3 I 4) x 2). Furthermore, functional 'application, the
theses cqn be used in expressions and passed as an argument ~o functions. For operator denoted by a space, takes precedence over every other.operator. For
example, example, square 3 + 4 means (square 3) + 4.

plus "' uncuny ( +)


1.4.6 Association
introduces plus as another name for the ui.l.curried version of addition. Another device for reducing parentheses is to provide an order of association
for an operator. It is clear that when the same operator occurs twice in succes-
1.4.4 Sections sion, the rule of prei::edertce is not sufficient to iesolve a.mbiguily. Operators
can assoc!ate either to the left or to the right. We have already encow1ten:d
TM notatit;mal device of enclosing a binary operator in parentheses ro convert
one example of declaring such a preference: functional application associates
it into a normal prefix function can be extended: an argument can also be
to the left in expressions. In arit~etic, operators on the same level. of preced-
enclosed aiong with the operator. If e denotes an arbitl'ary binary operator,
ence are usually declared to associate to the left as well. Thus 5 - 4 ...:. 2 means
then (xED) and (mx) are functions v.'ith the ddihi.tions
(5 - 4) - 2 and not 5 - ( 4 - 2). One operator that associates to the right is the
(xe) y - x l!l y function type operator (- ); thus,
(ey)x- xey :- ' ... A - B ..:. C . mearts A - (B - . C)
These nvo forms are called sections. Fbr example: It is not necessary to insist that an order of association be prescribed for e'.rery
(x-2) is the 'doubling' function operatoi. lf no preference is indicated,' then i)arentheses must be used to avoid
(> d) is the 'positive nwnber' test ambiguity. In fact, to avoid complicating a basically simple idea, we wilJ al-
ways use parentheses to disambiguate . sequences of d.i.fferent operators
. with
(1/) is the 'reciprocal' function
the same prec('!dence.
( /Z) is the 'Q.alving' function
( + 1) is the 'sw;:cessor' function
Any declaration of a specific order of association $hould not be confused
.\\>ith_a different, though related, property of operators known as associal'iVily.
There is one exception m the rule for forming sections: (-x) is
inteq>r~ted .' '.
An operator e is.s .a id to be associative if
as the unary operation of negation applied to the number X. SectiOilS are'not . (x e y) l!l z == x e (y e z)
used heavily in what follows, but on occasion. they provide a simple means for
describing expressions conveniently and without fuss. for all values x, y, and z of the appropriate type. For example, + and x are
associative operators. For such operators, the choice of an order of association
1.4.5 Precedence. has no. effect
. . . on meaning..

Wh~n several opera~ors.appe~ tqgether in an e~pression, c~rtain ~ules_~{p.fe ~


cede11ce are proVided to resolve possible. ambiguity. The precedence rules for
. 1.4. 7 Functional composition
the common arithmetic operators 'a re absorbed in childhood without ever being The composition of two functions f and g is denoted by f g and is defined by
stated formally. Their sole pmpose in life is to allow one to reduce the number the equation
of paren.theses in an expression. .
l.n partiCli.lar,. exponentiation, which we will denote by I, takes precedence ( ) ({3 - y)- (a- {3) - (a - y)
over multiplicati.on, which in tmn take::? preced~nce o.ver (lddition; for example, (f g) x - f (g x)
' ; I

?l+314X2 The type signature will be explained in Section 1.6. Lrl words, f . g applied to
163 x is ddined to be the outcome of first applying g to x. and then applying f to
16 1 I Fundamental concepts 1.5 I Definitions 17

the result. Not every pair of functions can be composed since the types have 1.4.2 Suppose w~:curry the arguments. ohhe fun'ction delta, so that. we can
to match up: we require that g has rype g ::ex - {3 for some types 01 and {3, and write delta a b c rather than delta (a, b, c). What is 'the type of the curried
that (has type { :: /3 - y for some type ;y: Then we obtain f g :: ex - y. For version?
example, given square :: Integer - Integer, we can define 1.4.3 In mathematics one often uses logarithms to various bases; for example,
quad :: Integer - Integer Iog 2 , loge, and log 10 . Give an appropriate type of a fun~ tlon log that takes a
quad - square square base and returns the logar ithm 'function for that base.
1.4.4 Describe one appropriate type for the definite integral function of math-
By the definition of composi.tion, this gives exactly rhe same function quad as
ematical .an~lysis,
. .. , . .
as used in th.e phrase 'the integral of f from a to b'. ,

quad .. Integer - Integer 1.4.5 Give examples of functions with the following types:
quad x - square (square x)
(Integer - Inc~ger) - Integer :
This example illustrates the main advantage of using flUlctional composition in {If!leger - Jnteg~r) - (Integer - Integer}
programs: definitions can be v>rlnen more condsely. Whether to use a point '
free style or a point-wise Style is partly a 9uest\on of taste, and we will see func- 1, 1.4.6 Which, if any, qf .the t:ouowing statements is true?
.
.. .. ,..' .~: .. ,:,. ~ ; .. : . .:. .
tions defined in both styles in the 1:emainder of the book. However, whatever :,.. ,. :' f:. .~ ._;,~.::, I" :: .-~ t,. .

the style of expression, it is good programming practice to constmct complic- ... {X)x - (X X)
ated functions as the composition of simpler ones. (+)X = (x + )
Functional composition is an associative operation. We have ' ( - )X - (- X)

({ . g) . h = f . (g . h) .~
1.4.7 Define a function uncuny that conver ts a curried function into a noncur

ried version. Show that


for all flUlctions {, g and h of the appropriate types. Accordingly, there is n o .,
'
need to put in parentheses when \"'l'iting sequences of compositions. . curry (Ltncurry f) x y - f xy
uncuny (curry() (x,y) = f (x ,y)
,. ' o: ,
0
;., '' 1 ':.ow' :, I o

Exercises
' 0 '. ' '., , '' <

' for all x and y.


1.4.1 Suppose f and g have the following types: ''
~~

f .. Integer - Integer ., 1.5 Definitions


g .. Integer - (Integer -Integer) ... .,
J
So far, we hav.e seen one or two simple definitions of funct ions, but definitions
Let h be defined by of other kinds or value ar'e possible: For example,
..
}
h
pi Float
hxy - { (g X y)
\1 pi - 3.141 59
Fill in the correct rype assignment for h.
declares a single-precision approximation to rr. .
Now determine which, if any, of the following statements is true: The definition or smaller seen earlier made use of a conditional expression.
h - f .g Recall that the definition was
hX = ( (g X) smaller (Integer, Integer) - Integer
hXY = ((g) X Y smaller (x, y) = if x .$ y then x else y
\

'
18 1 I Frmdame/ltal. concepts J.5/ Definitions . 19

The condition X < yevaluates to a boolean or. truth value, True or False. Boolean J.5.1 Recursive definitions
values will be considered in detail in the following chapter.
Another waY. to express essentially the same definition of smaller is to Wiite Definitions can also be recutsive. Here is a well-known example:

sma.ller :: (Integer. Integer) - Integer fact .. Inceger - Integer


smaller (x, y)
.. fact n - if n == 0 then 1 else n x fact (n - 1)
I X ~y -
. . ' '
X ' ' The function fact is the factorial fw1ction. Recursive definitions aie evaluated
~. X> y - y ]ike any other definition. For example. one reduction sequence for evaluating
. . ~ ' '
fact 1 is
This form of definition uses guarded equations. The syntax of guarded equa
tions follows t!1at of Haskell and consists of a sequence of clauses delin)ited {act1 '

by a vertical bar. Each clause consists of a condition, <;>r guard, and an ex


{definition of {actl
pression, which is separated from the guard by an = sign. I.n the definition of
smaller (x, y) the guards are (x ~- y) and (x > y), while the associated expres- .if l == 0 then 1 else 1 x fact (1 -1 ) ... ~ :'

sions are x and y. , . , = . {since ( 1 ==0) eva1uates to False}


We ~ use guarded equations only spru:ingly in what follows, preferring
.conditiona1 expressions instead. The mai.n advantage of. guarded equations is 1 X {qi:t (1- 1}
when 'there are three or more clauses in a definition. To illustrate, consider {definition of fact}
the fl.mction signum that takes an integer argument x and returns -1 if x is
1 x (if (1 - 1) == 0 then 1 else (1 - 1) x fact ((1 - 1) - 1))
negative, 0 if x is zero, and 1 if x is positive. .Using guarded equations, we
would wr.ite , {definition of (- )}
signum :: Integer - Integer 1 x (if 0 == 0 then 1 else (1 - 1) x {act((l - 1) - 1))
signum x {since (0 == 0) evaluates to True)
x<O - -1
.1X 1
X== 0 = 0 <

X> 0 = 1 {definition of x}
1
Using conditional expressions, we would have to 'WTite something like
There are, of course, other reduction' sequences of (act 1, but all lead to the
signum Integer
' .
- Integer .same result
signumx - if x < 0 then - 1 else . The. above definition of (act is not completely satisfactory: if we apply {act
ifx == 0 then 0 else 1 .. . .to anegative integer, then the computation never terminates. For example,
'
The dcfiniti_on using guarded equations is clearer because the three conditions fact( -1)
are made exi>licit. Note that an equality test is '-vritten in the form x == y. This.
is to distlilguish it from a definition, which is v.rritten in the form ~ = y. Equa,lity = {definition of {act }
and comparison
. tests
'
are considered ftirther
.
in the following chapter. if -1 == 0 then 1 else (- 1) x {acl(-1 -1}
{since ( - 1 == 0) evaluates to False)

., .
(-1) x fact (-1 ~ 1)
{as before)
20 1 I Fundamental concepts 1.6 I Types 21

(- 1) x '((-2) x {a ce (- 1 - l-1)) One can also write

and so on. Although it is rhe case that {ace x = J. for negative x, we would r (Float. Floac) - Float
prefer that the computation terrrunated with a suitable error message rather f (x,y) - (a + 1) x (b + 2)
than proceeding indefiriitely with a futile computation. One way of achieving where a= (x + y)/2; b = (x + y)/3
this is ro rewrite the definition as . .
In the second form, a semicolon is used to separ.ate the two definitions. A local
fact :: Integer - Integer d~f!nition can be used in conjunction with a definilion that relies on guarded
{act n equations. Consider the following definitjon:
. .. ' ' . . ' .
\ ' .
= error "negative argument to fact''
'

n <0 f ::Integer - Integer - integer


,'
n :: 0 - 1
fxy
n x {ac((n - 1)
n>0 -
X~ 10 = x+ a
-.; . .... ,.. . .
X> 10 = x- a
The predefined,, function enor takes a siring as argument; when evaluated it
causes immediate terminarion of the evaluator and displays the giv~n error where a = square (y + 1)

'rn rhi.,s d~t~ti~n. the ~h~r~ ci~~se quftlifies both guarded equations.
message:

? fact (-1)
-, Exercises ' ..
Program error: negative argument to fact
1.5.1 The f ibonacci numbers fo, f1 .... are dcfmed by the rule that fo = 0, f1 = 1
There are other ways to define face and we will discuss them later in the book.
and ~~ ~ 2 = { 11 + [,,+1 for all n ~ 0. Give a definition of the function fib that takes
an integer nand retums (,,.
1.5.2 Local definitions 1.5.2 Define a function abs ::Integer - Integer that returns the absolute value
The final piece of notation we will introduce here is called a local definition. ~n of an integer. .
mathematical descriptions one often finds an expression qualified by a phrase '
1
..
of the form 'where .. .'. For instance, one might find 'f(x,y) = (a + l )(a + 2), ' 1.6 Types
where a = (x + y)/2'. The same device can be used in a formal definition:
"' In t't.mctional programming the universe of values is partitioned into oman-
f (Float, Floal) - Float ised collecrions, called types. So far, we ha\;'c mentioned Integer and Float,
f(x,y)- (a+1) x(a+2) where a = (x+y)/2 but there are also other kinds of number, lncluding Int and Double, as well as
booleans (elements or'Bool), characters (elements of Char), lists, trees, and so
The special word where is used to introduce a local definition whose context on. Moreov~r. we have already seen how to put types together to make aninfin-
(or scope) is the expression on the righ t-hand side of the definition of f. ire variety of other types; for example Integer - Float. and (Float, Float). and
When there are two or more local definitions we can lay them our in one of 1 so on. In the next chapter we will see how some of these'types can be defiried,
nvo styles. for example, one can write : and how to define new types.
~~
ij Each type has associ~1ted with it certain operations which are riot meaningful
f (Fioac, Float) -Float for other types. For instance, one cannot sensibly add a number to a character
f(x,y)- (a+l)x(b+ 2) or multiply two functions together. Il is an important principle of many pro:
wberea - (x+y)/2 gramrning languages that every w Ql}l' expression can be assigned a type.
b - (x+y)/ 3 ..., Moreover, this type can be de ~e&'iift$1. /) e co~scituents of the expression
. s lvfa~~ltlfii/IJ o
-z. ; lhft/'fll,?,'y!(; '
'? rm,1!y!(; ,..,./
* ..,c:> /
. * "' \ ,. "
22 1 I Fundmnenlal concepts 1.6/ Types 23

alone. In other words, just as the value of a11 expression depends only on the However, the two uses of functional composition in these expressions have
values of its ~omponent expressions, so does its type. This principle is called different types, namely
strong typing.
The major consequence of the discipline imposed by strong typing is that . (.) :: (Integer - Integer) - (Integer - Integer) - (Integer -Integer)
<my ~xpression which caru1ot be assigned a sensible type is regarded as not (.) :: (Integer - Floal) - (Integer - Integer) - (Integer..:.. Float)
being well formed and is rejected by the computer before evaluation. Such . '
Thus, the operation of ftmctional composition is assigned different types in
expressions are simply regarded as illegal. We saw one exampieearlier: the
different expressions. .
expression squaresquare3 is rejected by the computer as not being well ~ormecl.
The problem of a;;sign\ng a single type to ( ) is solved by introducing Lype
Similarly, the script
variables. The type assigned to ( ) is
quad Integer - 'nteger () :: ({J- y)- (ex- /3)- (a- y)
.quad x = square square x
Here, ex, {3, and y denote type variables. We will use greek letters to denote
is rejected by the computer since the expression square square x is not well type variables. Like other kiJlds of variable, a type variable. c~n be inst~l,ll~iated
formed. to different types i,l l different ci.rcmnstances. A type contauung type vanables
' '
One great advantage of strong typing is that it enables a range of errots, from is called a polymorphic type.
si.lllple typogmpWcal mistakes to muddled definitions, to be detected before Here is another example. Lool< again the preVious definition of {act:
evaluation. The other great advantage is that it steers the programmer into
a certain discipline of thought, namely to consider appropriate types for.the . fact :: Integer - Integer
values being defined before considering the definitions themselves. Jn other
.. words, adherence to the discipline of SlTOng typing can help significantly in the - error "negative argument to fact"
design of clear and well-structured programs. - 1
There are two stages.of analysis when an expression is submitted for evalu- - 11 x fact(n-1)
ation. The expression is firs~ checked to see whether it conforms to the correct
synta'C laid down for constructing expressions. lf it does not, the computer cons.i der the function error. It takes a string as argument, so its type is String -
signals a syntax error. If it does; then the expression is analysed to see if it pos- A for some type A. In the program above it is clear that A= Integer; only with
sesses a sensible type. lf the expression fails to pass tWs stage, the computer this type assignment is the program for fact well formed. After all, the second
signals a lype t1ror. Only if the expression passes both.stages can the process and third clauses deliver integers, so the first one should do too. It doesn't
of evaluation begin. Similar remarks apply to definitions c~eated in a script matter what integer is delivered, because th~ sole purpose in evaluating error
is to abort the computation with an error message. If, however, th.e general error
function had type error :: String '- integer, it would have .limited ~sefulness.
1.6.1 Polymorphic types
Instead, the type assigned to error is Stling - ex. Once again, the problem is
Some functions and operations work .w ith many types. For example, suppo~e resolved by making use of type variables. . .
As a final example for now, consider the function curry de~ned in Sec-
square I1iteger - Integer tion 1.1.2 by the equatiol).
sqrt Integer - Float
curry f x y = f (x, y)
Then the expressions square square and sqrt square are both meaningfUl and This function is used to co~vert functions with type (A, B) - C ~nto functions
they have the folloWing types: . .
with type A - B - C. No properties of any specific types A, B,. and C are
square. :: _Integer_- Integer required in the definitio.n of curry, so ills assigned the polymorphiC lyp.e
.square
.. ':

sqrt square :: Integer - Float curry :: ((ex, fJ) - y) ~ (ex- /3- y)


24
1 I Fundamental concepts 1.1/ Specifications 25

The rightmost pair of parentheses could have been omined, since the type Ex.ercises ..
operator (-) associates to the right, but it is clearer in this case to put them
in. 1:6.1 Give suitable polymorphictype assit,'11ments for the following functions:
We now have the beginnings of a language of expressions that denote types.
or
Th.is language contains cons tam expressions, such as Integer Float, variables,
const xy - X ' ..
such as 0< and {i, and functions that take types to other types, such as the subst f g x - (X '(g X)
flU1ction type operator (- ).. apply f x - fx
flip f X)I - fyx
1.6.2 Type c~asses 1.6.2 Define a function swap so that

A careful reading of the first part of this chapter reveals that we have used flip (curry n. = cuny <f. swap)
(curried) multiplication with two different type signantres:
for all f :: (e<, P) ""' J''
( x) :: Integer - Integer - Integer
1.6.3 Can you find polytnoipl1ic type assignments for the following functions?
(x) Float- Float - Float '

. . strange f g = g <f g)
like ( ) and error, ir seems that (x) should ~e assigned a polymorphic type, stranger f = ff
namely
1.6.4 Find a polymorphic type assignment for
(X) :: 0<- ()( - 0<
square x = xxx
Bur one can argue that tl1is type is too general. For instance, we cannot sensibly
multiply two characters or two booleans.
. In Haskell the resolution is to group together kindred types in.to' rype classes.
1.7 . Specifications
ln particular, Integer at)d Float belong to the same class, the class of numbers.
The type assigned to (x) is . . In ~omputing: a spe.cification is a description of what t~s~ a progran1 i.s.. to ~er
form while an implemenrarion is a program that sansfies the spectficatton.
(x) :: Num ex=> 0<- 0<- ex Specifications and implementations serve different ptirposes: specificati~ns are
expressions of the prograrruner's intent (or client's expectati~ns) a_nct therr p~r
The rightha.i1d side should be read as the type 0< - a - 0< restricted to those pose is to be clear as possible; implenfentations rue expresswns for e~e~ution
0< that are instances of the type class Nilm. by computer and their purpose is to be efficient enough to execute w1thin the
The same device is used for the numeric constants. For example, 3 can be time or space available. The link between the tw~ is the requirement that the
used to describe a certain floating-point number as well as an integer; accord- implementations satisfies; or meers, the specification, and the programmer may
ingly, the type assigned to 3 is Num ex => ex. In words, any type, provided it is a be obliged t.o provide a proof that tl1is iS' indeed the case.. . . ..
munber tyPe. A specification for a function is some statement of the mtended rel~twns?tp
There are other kindred types apart from numbers. For example, there are between rugumenrs and results. A simple example is given by the followmg .
the types whose values can be displayed, the types whose values can be com- specification of a function increase:
pared for equality, the types whose values can be enumerared, and so on. A
increase :: Ii1teger - Integer
type that is an instance of one type class may also be an .instance of another.
For example, we can compare nwnbers for equality and we can also display
increase x > square x, whenever x :<!: 0
them. We will explain in the fo]Jovring chapter how type classes can be created This specificalion s<ws that the result of increase shoui'd be stricrly.greater
and how specific types can be declated ro.be instances of these classes. than the square .of its argument, whenever the argument is nonneganve. The
26 1 I Fundamelltal concepts l.B I C/mpter notes 27

specification does not say how increase should be c9mpute d, but gives only a In search of better things, we may calculate:
property that any implementation should have. The specirication is not part of
our prognuriming language, even thou-gh it is expresse d in asimilar style. quadx
On_e possible impleme ntation is to take increase x. = square (x. + 1). The - {specification)
proof that this definitio n satisfies its specifica tion is as follows:
xxxxx xx
increase x.
- {since x is associative}
= !definitio n of increase} (x x x) x (x x x)
square (x + 1)
- {definition of square}
= !definition of square}
Square x x square x
"

(x + l) x (x. + 1)
- {definition of ~quare}
.... .
- {algebra}
_ .:"

square (square x)
X X' X+ 2X X+ 1
The result is that we can impleme nt quad ~~ith two multiplications instead of
{since x ;a: O.implies 2 x x + 1 > 0}
"

> three, a s ignifican t saving with arbitrai-y -precision arithmetic.


XXX In this case, we didn't invent the impleme ntation of quad first, but developed
it from the specifica tion. The derivation was not entirely mechani cal:, the creat
!definition of sqLwrel ive step was to employ the associativity of multiplication to put in brackets in a
squarex clever way. Admittedly, this example is absurdly simple, but we will see other,
more convincing, examples of systema tic program developme.n t, or program
The proof format used above will be followed in the rest of the book. Indeed,
synthesis, later on in the book.
.we have used it already mthe cllscussion of reductio n sequenc es. A reductio n This paradigm of software developm ent.- first write a clear specification,
sequenc e Is also a kind of proof, albeit one conduct ed vvi.th a very r estricted set then develop an acceptably efficient impleme ntation - has been the focus of
of reasonin g rules. So restricte d, in fact, that a compute r can b~ instructe d to active research over the past twenty years, and should not be taken as a cut-
carry out all the steps in a purely mechani cal fashion: and-dried method applicable in all circums tances. Two potentia l soUl'ces of
Above, we invented a definitio n of increase first, and then verified tha t it difficulty are that the formal specifica tion may not match the client's informa l
met.lts s pecification. There are m~y other functions 't hat will satisfy the spe-
requirem ents, and the proof that the impleme ntation meets the spe cific ~tion
cification and, since that is the only requirem ent, all are equally good. may be so large that it cannot be guarante ed to be free or error. Nevertheless.
One way of spec\fyipg_a funcbon is to state the rule of correspo ndence ex- by trying to follow the approac h wheneve r we can. the reliability or program s
plidtly. The 11otation of functional p~ol,TJ.'arnming can be very expressi ve, and
can be greatly increased.
sometim es the most sensible specification of a func tion is a legitimat e program.
The specification can then be executed directly. However, it may prove to be
so grossly inefficient that the possibility of executio n will be mostly of theor- Exercises
etical in~eres r. Having written an executab le specification, the program mer is 1.7.1 Give .another definitio n of increase that meets Its specification .
not necessar ily relieved of the burden (or pleasure) of producin g an equivale nt
but acceptab ly effident alternative.
As one very simple example of the idea, consider the specification 1.8 Chapter notes
,: quad. Integer - Integer The interactive use of a flmttibnal languagc, as described in the text, is provided
quad X - X X X. X X. X ,v. by the HUGS (Hask~ll Users Gofer Sys tem) environment develope d by Mark
28 l I FundameJJCal conceprs
Chapter'2
Jones of Notringham University. HUGS is available by FTP from
ftp://ftp.cs.nott. ac.uk/haskell/hu gs Simple datatypes
Haskell proper is a non-interactive language. Haskell compilers are available
from Chalmers, Glasgow, and Yale Universities, by Ffp from
ftp://ftp.cs.eha lmers.se/pub/hask el l
ftp://ftp.dcs _. glasgow.ac. uk/pub/haskell
ftp ://nebula. cs. yale. edu/pub/haske 11
The language used in this book follows Haskell 1.3, although not all features
of Haskelll.3 will be covered. Furthermore, normal mathematical symbols are
preferred over Haskell ones, which use a restricted character set. For example,
Haskell uses * for multiplication. The ke}'\.YOrds if, then, else, and where are This chapter inrroduc ~:; some basic datat)-'Pes, including booleans, characters,
reserved words in Haskell. tuples, and strings. We will describe how the values of each type are represented
Web pages for Haskell, which include an on-line version of the Haskell 1.3 and give some useful ,operaeions for manipulating them. We will also describe
report, extensions to Haskell, and information about i-Iaskell implementations, the mechanism for declaring new daratypes, and {,rive an overview of some of
can be found at rhe follo\oving site: the major type classesin Haskell. One class cif data types not discussed in this
chapter consists of numbers in their various manifestations. Nwnbers will be
http://www.haske l l. org/ dealt with in the following chapter. However, it is clil'ficult to give interesting
. .. examples of programs that do not make use of numbers in some form or other,
A tutorial introduction to Haskell is given in Hudak, Fasel, and Peterson (1996). so we will just assume for the while th~t they exist and are available for service.
Another elementary text on lazy functionhl programming that uses Haskelll.3
is Thompson (1996).
While this text was being prepared there has been another release, Haskell
1.4. Currently the Haskell committee are aiming to move towards a standardisa- 2.1 Booleans
tion; Standard HaskE:U, of the lan~;,1.1Uge. None of the changes under discussion
is likely to affect the details described in the text. As we saw in the first chapter, we need truth values in order to define a function
Orher nonstrict functional languages include Gofer and Miranda (Miranda using conditional expressions. At the very least we would Like to test whether .
is a trade-mark of Research Software Ltd.). Miranda, which is fairly close to two values are equal and, if the notion makes sense, to see whether one value
Haskell, is described in Thompso? (1995} and Clack, Myers, and Poon (1 995). is smaller or greater than another. There are two tmth values, True and False.
Another popular functional language is ML, which differs from Haskell in that These two values comprise the data type Bool of boolean values (muned after the
it is strict rather than lazy. Ml is described in Paulson (1996). nineteenth-century logician George Boole). Notice that the names True, False,
For further information about the denotational aspects of programming lan- and Boo! each begin with a capital letter.
guages, consult Stoy (1977) or Gordon (1979). The implementation oflazy func- The data type Boo/ can be introducecy with a daratypc, dec:lara~ion:
tional languages .is covered in Peyton Jones (1987) and Peyton Jones ~d Lester
(1991). The formal derivation of programs from their specirications is the ~ub dara Bool = False I True
jcct of Morgan(l996) and Kaldcwaij (1990), although the target programming
language is procedural, not functional. For a ftmctional and relational neat This declaration introduces Boo/ for the mune of the datatype, and the two
ment of program derivation in a categorical setting, consult Bird and de Moor values False and True for its members. Having mtroduced Boo/, we can define
(1 997). This is an advanced text, suitable for those particularly interested in functions that take boolean arguments by parcern matching. For exan1ple, "the
the mathemarics of programming, and can be studied after the present one.
..

30 2/ Simple data!ypes . 2. i I Booleans 31


negation function is defined by definition of A is by four equations:

not . :: Boo! - Boo/ False 11 False - False


hot False - True False /1. True - False
not True - False True A False - False
True /1. Tme - True
The two equations are used by the computer as rewrite rules to simplify ex-
pressions of the form not e. First e is reduced to normal form. If tins process This versitm uses pattern match.irig on both arguments, so 11 isstrict in both
terminates and results in False, then the first equation is used; if reduction arguments.
results in True, then the second equation is used. If e cannof be reduced to With eithel' definition, /1. is an associative operation, so there.is no need to
iwrmal form, then the value of not e is undefined. Thus, not .L = J. and not put in parentheses when "vriting expressions such as x A y /1. z. Similar remarks
is a strict function. Noli ce that the two occurrences of J. here refer to the apply to v. Howev.er, it is always good practice to put in parentheses when
undefined boolean value. It follows that there are not two but three boolean wJiting expressions involving both A and v. Both operators have a pre~edence
values, llt1rnely False, True, and L In fact, eveiy dataLype declani.tion ~tro- below that of the equality and comparison operators (considered next), so
duces an extra anonymous value, the urideffued value of the data type. .
x < z means (x :=;; < z)
. Two basic functions oi1 booleans ar~ the operations of conjunctio~, d~noted
~ yAy y) A (y

by the binary operator A, and disjunction, denoted byV : These oper~tions can.
be defined by .
2.1.1 Equality and comparison operators
. (A), (V) .... Bool ~ Boo/ - Boot
There are two equality operators== and* They are defined for boolean argu
False Ax - False ments by
True 0 x - X
~=)
.... Bdol - Boo/ - Boo/
False v x - X .. x == Y - (x A y) v (not x 11 not y)
.rruev x - True

The definitions use p~ttern matchirig on the iefthand argument. For example, (;e) .... Boo/ - Boo/ - Boo/
in order to simplify expr~ssions of the form el /1. e2' the computer first reduces X*Y - not ex:: y)
e1 to normal form. If ~he result is. False, then the first equation for A is used,
so the computer ~n.'ecliately retur.ns the l'inal value False: If e1 reduces tQ It is imponant to observe the distinction between == and "" The symbol == is
True, then the second equa.tion is used, so e2 is evaluated. It follows from this used lO denote a computable test for equality, while ""is used both in definitions
description of how pattern matching works that and in its normal mathematicalsense. In mathematics, the assertion double =
squa're is a false statement, and the assertion 1. = J. is a tiue statemeilt, since
anything equals itself. However, functions caimot be tested for equality, and the
J. A False = J.
result of evaluating J. == J. is .l not True. This is not to say that the evaluator
False A J. = False
is an urunathematfcal macl1ine, just that its behaviour is described by a limited
True A J. - J.
sef of ma~hematical rules chosen so that they can be executed mechanically.
,,
,. ' ..
The whole purpose of introducing"an equality test is tobe able to use it with
T~us A is strict il~ its lefthand argument,. but. not strict in its righthapd argu
a range of different types, not just elements of Bool. In other words, (==) and
ment. t\fialogous. remarks apply to.\/. . .
( :t=) 'a re overloaded operatlons. These operations Will be defined differently for
We could have defined A and v differently. For example, an afternative different datatypes ami the proper way to iritroduce them is first to declare ...
32 2 I Simple dacarypes .2.1
.. / ..
Boo/cans
. . ,. 33

a type class Eq consisting of all those types for which (==) and (*).are to be: . .. .Now.we ~an declare' Boo] to b~ ari in:stance of..Ord by writing .
..
defined. The declararion of Eq takes the form . .
instance Ord Bool where +
<
cliiss Eq a where F.alse < False - False
( ==}, ( *) :: a ~ IX ..: Bool
False < True - Tme ..
Tme <False - False
True < True
.
This declaration states that the type class Eq contains two member f{mctions - False
(or methods), namely(==) and ('F). These functions are assigned the type
The alterniltive defili.ition, nam,ely x <.y = not'x v y, doesn't quite work in the
way expected (see Exercise 2.1. 2). . '
(==),(*) ... Eqa=>a-a-Bool

To declare that a certain type is an instance of the type class Eq we have to give 2.1.2 Example: leap years
an instance . .For example,
. . declarario]l. .
Let us now give a couple of examples Involving boolean values~ First, .suppose
instance Eq Boo/ where we want a function .'to d eterrrline whether a year is a leap year or not. In. the '
Gregorian calendar, a leap year is a year that is divisible by 4, except that if it
(x == y) - ~x 1\ y) v (no/ x 1\ not y)
is divisible by 100, then it must. also be divisible by 400. We can express rhis in.
(X'F-Y) = nOC(X==Y)
a f1Umber of equivalent ways. One is to define
This declares Boo/ to be an equality type by giving specific definitions of (==) Jeapyear :: hit - Bool
and ( *) for boolean arguments. We will see how to give other instances of Eq 'Jeapyear y = (y mod 4 == 0) 1\ (y mod 100 * Dv y mod 400 :; 0)
in later sections. .
. If we wish, booleans can also be comp'a red with ( <), (~). (~). ~nd (>).These The type lnt describes the type of limited-precision integers and is considered
operations are also overloaded and make sense Vl>ith elements from a nurnber fmther in the following chapter. We could have used Integer in place of Int;
of different types. Recognising this fact, we. can set up another type class Ord, but it is unlikely that we would yvant to consider years with vety large numbers . . .
:
which is declared in the following way: of digits. Note that the three occU:rrences of (==) in the definition of leapy~a/
refer to the equality test on Int. Number types, including Int, are also instances
class (Eq a) => Ord lX where of the type class Eq.
( <). (~). (> ), (>) .. a- a- Boo/ Another way of defining leapyear. is to us_e a conditional expression:
. .
(X < y) =. (x < y) V (X== y)
leapyeary
(x ~ y) - (x.> y) v (x == y) :. .
= if (y mod 100 == O) then (y mod 400 == o) else (y mod 4 == 0)
:
'
(x >y) - not(x~y)

The first line says that Ord is a sabclass of Eq, that is, only equality types can 2.1.3 Example: triangles
be ordered. This makes sense since, in any sensible instance definition of(~).
we would expect x == y if and only if x ~ y and y ~ x. The last three lines Next, suppos~ we want to construct a function, analyse. say, that ta~es th,ree
give default. definitions of ~he operations (~). (~ ), and (> ). Haskell provides po~itiv~ integers x, y and z in nondecreasing order. These numbers repr,esent .

for default definitions ro save us the trouble of having to repeat them for each the lengths of the Sides of a possible triangle. The function analyse is to de-
ins.tance declaration. It is therefore sufficient to g~ve the definition of (<) for termine whether or not the three sides do in fact form a 'p roper triangle and; if
each instance. Not.e that the default definitions make use of the fact that Ord they do, whether the triangle is scalene (three different'lengths), isosceles (two
is a subclass of Eq since they mak~ use of an equality test(="). equal lengths), or equilateral (three eq1.1allengths). Three sides form a proper
34 2 I Sirnple daracypes 2.2 I Characters 3S
triangle if and only if the length of the longest side is less than the sum of the 2.1.5 Rewrite the definition of analyse so that the cases in the case analysis do
lengths of the other two sides. not depend on the order in which they are given.
Thus, analyse is to relurn one of four dis tinct values. We could use four
2.1.6 Define a function sort3 that sorts three integers into nondecreasing order.
distinct ~umbers for this purpose, but we cab also use four values created
Hence define a function, analyse' say, that does not depend on the'assumption
specially for the purp<?sc:
that its arguments are in nondecreasi.ng order.
data Triangle = Failure I Isosceles I Equilateral I Scalene 2.1.7 How many equations would you have to wrile to defme Tl'iangle as an
instance of the type class Ord?. (See Section 2.3 for.other ways of achieving lllis
This declaration inttoduces a new datatype Triangle with four values. With end.)
that, the program is
2.1.8 Are there any munbers that can be compared by(==) but cannot sensibly
analyse:: (Inc; lnl ,Jnt) - Triangle be compared by ( <)?
' '
.analyse (x, y, z ) . 2.1.9 The defii1itiori of(==) on a datatYve shouid ehsure that this operation is:
x+y sz - Failure (i) refleXive, that is, x == x for all x; (ii) transitive; that i's, X. == y and y == z
.X == Z - Equilateral imply x == z; and (iii) symmetric, that is, x == y implies y == x.. Show that these
(X == y) _v (y :: Z) = Isosceles properties hold for the definition of(==) on Boo/.
otherwise - Scalene 2.1.1.0 What properties of ( <) would you expect to hold in any instance dec
laxation?
The name otherwise is bow1d to the value Tme, so the final condition suc.ceeds
whenever the preceding conditions return False. Tlus definition of analyse is
correct only on the assumption that x s y :::;; z. Note again that the occurrences 2.2 Characters
of (==) and (:::;;) in this definition refer to comparison operations on values of
Mathematicians would be happy if given just numbers and booleans to play
type Int. . .'
with , but computer scientists prefer to Jill their terminal screens with more
interesting kinds of symbol. The built-in datatype Cl1a r is provided for this
Exercises purpose and contains 256 characters, including both visible signs and con-
. trot characters. Characters are denoted by enclosing them in s ingle quotation
2.1.1 Define 1\ and v using cond\tional expressions. marks. For example:
2.1.2 The definition of ( <) given in the text for arguments of type Boo/ has ? 'a'
False < True. This reflects the fact that False comes before True in the declara-
'a'
tion of the values of type Boo!. Naturally, one also expects that both False <
False and True < T rue evaluate to False.. ? '7'
. .
Now consider the alternative definition (x < y) = not x v y, where v is defined ' 7'
by panern matching on the left arJJu.ment. Why is this d efinition of ( < ) not. ? I
correct?
f

1 '

2.1.3 In logic, impl.ica~ion, dmoted by=>, is defined by the condition.that x => y i'

is false only if x. is true and y is false. Give a fO'r!llal definition of implication Characters are expressions in their simplest possible forms, so they are sin1ply
as _an operation on Boot. . . redisplaycd by the evaluator, including the quotation marks. lt is important to
tmderstand that the character '7' is quite a different entity from the d ecimal
2.1.4 Rewrite the declaration of the type class Eq by giving a defalllt definition number 7: the, former denotes a character, while the latter denoles anum-
of(*). , bcr. The third example above shows one way of denoting the space character.
36 2 I Simple dacacypes :Z.2J Characters 37
'
For the J?urposes of this book, ir is conventenno introduce special symbols Thismakes use of the fact that Intis als.o an equality type. (n a similar vein, we
for denoting the two most important no.nvisible control characters: space and can declare
newline. The newline character will be denoted by the sign ,-., and the space
character. by 'u'. . instance Ord Char where
Two primitive functions are provided for processing characters, ord and (x < y) = (ordx < ordy)
chr. Their types are
.' .
The tillear ordering on letters is, in part, just what one would expect. For ex-
ord :: Chm - Int ample:
chr Int - Char ? ''0' < '9'. " . ... ; : ..
Recall that Tnt describes the type of limH~d-precision integers. The fu'nction True
ord converts a character c (o an integer ord c .in the range 0 ~ o~d c < 256, and
? 'a' < 'z'
the function chr does the reverse, converting an integer back into the character
it represents. Thus chr (ord c) == c for all characters c. For example: True
. .
'

. ..
? ord 'b' ? 'A'< 'Z'
.. j "
,.
98 Tme .:
..
? chr98 .. Upper-case letters precede lower-case letters in the enumeration, !'O
'b' ..
? 'A' <'a'
? chr (ord 'b' + 1) Tme
'c' Using tllis information we can define simple functions on characters. For in-
? ord ;-+' stance, here are tiu-ee functions for determining whether a character is a digit,
a lower-case letter, or an upper-case letter:
10
. .~.. ~ .. ... - ~.~.:~: - , .,;, ~ '- . .
.. isDigit, isLower, ;sUpper:: Char - Boo/
..

The correspondence between characters and the first 256 nonnegative intege rs isDigit c - CO'~ c). A (c ~ '9') '
provides an alternative way of describing Char. One can thirik of Char as being
isl.ower c . - ('a' ~c) A (c ~ 'z')
mtwduced by a dataLype declaration
isUpper c - ('A'~ c) 1\ (c ~ 'Z')
data Char = CharD I CharJ I ... I Char255
Next, we can definea fnnctlon for converting lower-case letters to upper-case:
in which the naming conv<;nlion for values of Char is nonst;,mdard. For ex . ,.
ample, instead of Chiu-98 we write 'b', and instead of CharlO we wrile ,-+'.The capitalise
integer ord c describes the posWon of character c in the ~mm1eration. capiealisec - if isLower c then chr (o(fsec + ord c) else c
As with Bool, iris possible to define functions on Char by panern matching, where offset = ord 'A' - ord 'a'
but the number of patterns is so large that a definition by case analysis is
preferable. . This ~lefinition 1,1ses the fact that the lower. a nd upper-case letters have codes
Characters can be compared and tested for equalitY. We can declare Char. which. are in numetjcal seque~1ce, but do not depend on their. actual values.. In
to be an equality Lype by writing particular, we can calculate

instance Eq Char where capitalise ~a " -


(x ==y) - (ord x == ord y) {definition ant:l ;_.;rower 'a' = Tn~el
2;3 I Evumerations 39
38 2 I Simple datalypes

better idea is to code elements of Day as integers, and use integer compari sons
chr (offset+ ord ' a')
.instead. Since the same idea can be employed with other enumera ted types, we
I

= {definition of offsel} inl1'0duce a new type class Enum that describes types whose elements can be
+ ord 'a') enumerated. The declarati on is
chr (( ord 'A'- ord 'a')

- {arithmetic} ~ dass Enum e< where


chr (ord 'A') toEnum .. IX - Int
Inc -
= {romEnu m :: IX
{since cltr (ord c) = c for all c)

'A' A type is declared an instance of Enum by giving definitio ns of toEnum and


{romEnum, .fupction s. that convert between elements of
the type and Int. In
In the calculalion we do not need to know the codes for '/\' and 'a'. ins tance declarations, {romEnu ni should be a lef'tiJive rse to toEnum, that is to
A list of characte rs is called a string. Strings vcll be considered in a later say, '
.

. section, where it will be sho;vn how they can be used to give complete control
over what appears on a terminal screen. fromEnu m (toEnum x) = x

Exercises for all x. This requirement, like the requirem ent that {<) be a transitive rela
tion for Ord, cannorb e expresse d in HaskelL The specification of fromEriUm
2.2.1 Define a function hextlet that takes a letter of the alphabet and re~s as a left-inve rse of toEnum is noncons tructive and does not provide a default
. the letter coming immediately after it. Assume that letter 'A' follows 'Z'. definition. It is the task of the progranuner to give a constructive dcl'inition of
{romEnu m that meets the specification.
2.2.2 Define a function digitva/ that converts a digit ch aracter to its corres
ponding numerical value. Now we can declare Day to be a member of Enum wHh the inst~nce declara
tion
.
2.3 Enumerations
'
instance Enum Day where

We have seen in the case of Boo/ and Char that one way to define a new data type
toEnwnS un - 0
toEnum Mon = 1
is 'by explicit enumera tion of its values. Here is anothe~ example. Suppose = . 2
we are intereste d in a problem that deals with the days of the week. We can
toEnwn Tue

introduce a new type Day with the declarati on


toEnum Wed = 3
toEnum Thu - 4
data Day . = I
Sun
- ,.
I. Man I Tue I We I Thu I Fri I Sat toEnum Fri - 5
- 6
The effect of this definHion is to bind the name Day to a new type that consists
toEnumS at
... ,. ,

of eight distinct values, seven of which are reP,resen ted by the constant s .Sul1,' .
'
TJ:le function {romEnu m can also be defined by seven equation s, as we will see in
J'lon, and so on, and the eighth by the ubiquito us .l, which is assumed to be the following chapter when ~e discuss pattern matching with natural numbers.
a value of every type. The seven new constan ts are called the constru(.'tors of EXactly the same idea of associating values of an enumera ted type with in
the datatype Day. By convention, construc tor names are distingu ished from tegers was used in the discussion of Char. In fact, we can declare
other kinds of name by beginning them with an uppercase letter. The name of ' .
a dedared data type also begins with ailupper-case letter: instance Enu m Char where
It is posslble to compare elements of type Day, so Day can be declared as - ord
toEnu m
an instance of the type classes Eq and Ord. However, a ctefl.rti~ion of (== ) and
==
{<)base d on pattern matchin g would involve a large number of equations. A
{rom Enum cl1r
.:\ . ... :'.

40 2 I Simple datarypes 2.4 I Tuples 41


Given the function toEnum on Day, we can riow declare .,
Exercises
instance Eq Day where 2.3.1 Define a function dayBe{ore that remrns the day before a. ,,given day.
(x == y) =- ( toEnum x == toEnum y) ..
2.3.2 Define a data type Direction whose values describe the four major points
of the compass, and define a function reverse for reversing direction.
ii1s tance Ord Day where . . .'

(x < y) = (toEnum x < toEnum y) 2.3.3 D~clare Boo/ as a member of the. type class Enum by giving an explicit
instance
. declaration,
Here are some simple examples of the use of the t)'P.e Ody. First, we might ' f :

define
.. 2.4 Tuples
workday .... Day- Boo/ . . . .
workday d - (Mon :!': d) A (d :S Fri) One way of combining types to form new ones is by pairing them. For example,
the type (Integer, Char) consists of all pairs of values (X, c) for wmch X is
restday .... Day- Boo/ an arbitrary-precisi.on int~g~r. and .c is a character. I~ partlctt!ru1, .(3, 'a'). and
restday d - (d == Sat) v (d ==Sun) (1765341, '+') are both v~lues' of this type. The tYI)e (A, B) corresponds to the
cartesian product operation of set theory, where the notation Ax B is more
Next, we can use toErwm and {romEmm1 to define a function dayAfter that often seen. , . .
returns the day after a given day:
The polymorphic type (e<, /3) is, in effect, the same as the datatype Pair_e< /3
dayA(ter
introduced by the datatype declaration
Day - Day
dayAfter d = {romEnum ((coEnuin d + 1) mod 7) data Pair e< f3 == MkPair lX f3
Tn particular, dayA{rer Sat = Sun. The data type Pair tX f3 has a s ingle constructor MkPair. Unlike the constructors
of Boo/ and Char, this constructor is a function; irs type is
2.3.1 Autom'a tic instance declarations
MkPair ::. oc - /3 - Pair a f3
We have now met three type classes, Eq, Ord, and Enum. The instance declil.t
ations for Bool, Char, and Day are in each case the obvious ones: the order in What distinguishes Mk.Pairxy from (x, y) is simply that the Janer form employs
which elements are presented in the data type declaration gives all the necess- a special and more traditional syntax.
ruy information. Haskell allows a shortcut to save the programmer the bother Two basic functions on pairs are (stand snd, defined by
,, .: I ., '

of writing out these lnstances directly. For instance, one can declare Day by
writing fst .... (ex, /3) - rx
{st (x , y) - X
data Day I I
- Sun Mon Tue
. I. Wed I Thu I Fri I Sat snd .... (tX,/3)- f3
deriving (Eq, Ord, Enum)
snd (x, y) - y
The deriving clause causes the evaluator to generate instance declarations of
The definitions of {st and snd use pattern matching: the expression (x~ y) on.
the named type classes automatically, and these instances will be the ones we
the left of the equations is a pattern that is matched by any pair of values. Thus
have seen above. An automatically derived instance declaration of Enum is
f'sc e is evaluated by reducing e to the form (x, y) for some x and y, and then
possible only for a datatype that is declared by listing irs values explicitly.
returning x.
42 I Tuples
2 I Simple data'types 2.4
43

Like other typ~s. the type (<X, {J) contains an additional value, namely the Contrast this with the following definition of cr-oss:
undefined value .!... In particular, undefined = ..L,. where
. cross' ({,g) (x, y) = (f x, g y)
undefined ::. ( e<, {3)
u~defined = undefined The value ..L fails to match the pattern (x, y), so cross' ({,g) 1 = ..L and so
cross' is a strict function. The function cross is 'lazier' than cross' and is to be
The value (..L, ..L) is different from ..L. To see why, consider the definiti.on preferred because it can deliver additional res.ults.
.... . .
The functions pair and cross fonn part of a group of general-purpose func-
test :: (<X, {3) - Boo/ :; #

tions that can be used i.n .an alternative, point-free style ofprogramrning. For
. test (x, y) "' True
instance, the function leq = uncuny (s), the uncurried version of (s) on an
. . enumerated datarype, can be defined in terms of the same fw1Ction leq/nt on
Since test is. defined by pattern matching, we have test ..L = ..L. On the other
hand; tesl ( ..L, ..L) = True. In the evaluation of test p, pattern matching is re- Jnt by
quired to reduce p t.o the form (x, y) , but i.t is not required to detcnni.ne the (Enum e<) => (<X, e<) ..:. Boo/
*
values of x .andy. Since ..L True it follows that (..L, ..L) * ..L. . .
leq
leq .
..
= leq.lnt cross (toEnum, l'oEnum)
More generally, if <X is instantiated to an ~nui9erated type with m declared .
c'o nstructors, and similarly {3 is instantiated to an e~umerated type with 11 de- As ariqther example, the function workday of the previous section can also be
clared constructors; then ( e<, $) will have 1 + ( m + 1) x (n + 1). values in total. defined by
We can also define functio~s that take pairs of functions as arguments; for
example, workday = uncurry (A) pair ((Mon :S ), ( :S Fri))

pair (<X- {3, <X- y) - ex...: (/3, y) This point-free style works best when binary operators are typed as uncurried
pair({,g)x- (fx,gx) functions. Since Haskell assigns curried types to operators, we have to uncurry
them explicitly.
cross (e<:.. {3,J'- c5)- (e<,y)- ({J,c5) The functions pair and cross satisfy a nwnber of properties that are useful
. CI'QSS ((,g) . "' pdir (( (St, g Srrd) . . ' in point-free calculations:

The word cross comes from category theory, where the notation f x g used is {st pair({, g) - f
instead of cross ({,g). Note that cross({, g) ..L' = (f ..L,g ..L), which we can see snd pair ({,g) - g
by arguing: pair({, g) h - pair (f h, g h)
cross ({;g) ..L cross({, g) pair (h, k) - pair (f h,g k)

- {definition of cross} Here is a proof of the fourth equation, which uses the other three:
pqir (f {st, g snd) ..L cross ({,g) . pair ( h, 'k)
= {defillition of pair! = {definition of cross}
( (f fst) ..L, ('g snd) .1.) pair (f f'st, g snd) pair (f1, k)
- {def}ni.tion of composition] {third property}
.<f (fsL.l),
.' g (snd .1)) pair ((. fst pair (h, k), g snd pair (h, k))
are strict} .
.
..
- . {since both" fst ana srid = . {first and second properties}
<f ..L,g ..L.) pair(( h, g k)

. .
., ...
44 2 I Simple c(aratypes 2,4/ Tuple$ '45

The calculation is condt1cted entirely with functions, and there is 'n o appeal to 2.4.1 Comparison operations
the principle of extensionality described iri Section 1.4. In Chapre'r 12 we will
construct a program. th<\t performs such proofs auromarically. . .. We .can compare ~lements of (pc, /1) for eq~:~alily only if the elements of both
As weJIas forming pairs of values, we can also form triples, quadruples and a and {3 can themselves be compared for equality. Here is the appropriate
so on. Note, however, that each of the types (a,(#. y)),
((a, .8), y), and (a, }3, y) instance declaration:
is distinct from the others: the first is a pair whose second component is also
instance (Eq a, Eq {3) ~ Eq (<x, /3) where
a pair, the second is a pa'ir whose first componetit is a pair, and the third is a
triple. Pairs, triples, quadruples, and so on, all belong to different types. . (x;}') == (u, v) = (x == u) A (y == v)
For completeness, Haskell also providesa nullary tuple. By definirion, the
Similarly, we can declare pairs to be an ordered type:
unit expression 0 has type (). The type 0 has just two members, 1. and ().
One use of () is to rurn constailts into functions; for example, instance (Ord ei, Ord /3) ~ Ord (a, /3) where
pifun 0- Float (x,y)<(u,v) = (x<il)V(x== uAy<v)
pifun 0 - 3.14159 Tltis particular. way of ordering pairs of values is called the lexicographic or :
By lifting constants to the function level, one can move even further along the dering. In particular,
path to a point-free Style of programming. For irlstante, one can write .
? (l, undefined) < (2, undefined)
square square pi{tm instead of (sqtwre. square) pi True ~ .. . . '

The expression on the left is the composition of three ftmctions, while rhe ? (undefined,!) < ~undefined, 2)
/
expressioi1 01"_1 the right consists of the co~nposition of two functions applied {lnlerrupted!}
to an argument. With lifted constants we do not need to mix composition with
application. " The first computation terminates because v is defined by pattern matching,on
Finally, as a practical example in the use of tuples, here is a fundioh that the left argument. Hence
returns a pair of numbers, the two real roots of a quadratic equation with coef-
ficients (ti, b, c): . . (1, .L) < (2, .i..) = (1 < 2) y(1 ==2 A i < 1.)' = True
roots:: (Float, Float ,Float)- (Float,Float) On the other hand, the second computation fails to terminate,. so we' interrupt
roots (a. b. c) it.
a == 0 - error "not quadratic"
e<O - error "complex roots" Exercise's
otherwise - ((-b-r)/d,( - b+r)/d)
2.4.l P1:ov~ that ~ross ({,g) cross ( h, k) ; cross (f h, g k).
where r - sqrt e
d - 2x a 2.4.2 Give a datarype declaration of a type Triple that corresponds to triples.
e - bxb-4xaxc 2.4.3 Suppose a date is represented by a ~riple (d, m,y) of three integers,v.ihere
The local definition defines three values, whose scope is the whole equation for d is the day, m is the month, and y the year. Define a t'llllction age that takes
roots. two dates, the first being the current dare; and the second ~eing the birthdate
of some person P; and returns the age of P as a whole mm1bei of years. . .
2.4.4 Is it possible to declare ( ei, /3) as a member of the type class Enum, t,Tiven
that both tX and # are instances of Enum?
I '
46 . ' 47
2 I Simpla datalypes 2.5 I Other types
.
2.5 Other types The word plus comes from category theoty, where the notation f + g is used
instead of plus ({,g). . . .'
As well as declariT!g a tYPe by listing its ~onstants, we can also declare types The algebraic properti es of tase and plus are dual to those of pair and cross
whose val_ues depend on those 9f bther t)ip'es. For example, .
d escribed in the previous section:
data Either =: ~eft Boo[ I Right Char case (f, g) Left - f
case({, g) Right - g
This declares a type Either whose val~es ~re denoted by e xpressio ns of the form
Left b, where b is a b9olean, and Right c, where c is a characte r. There are three h case (f, g) - case ( h f, h g)

boolean values (inducting .l) and 257 characte rs (inducting .l), so there arc 261 case (f, g~ plus (h; k) - case ({ . h. g . k)
distinct values of the tYPe Either; these include Left .l, Right .l, and .l. When
The proof of the last equation is left as an exercise.
they are functions, the construc tors of a type are xionstrict, so Left .l '* .l and
Right .l '* .l. Assumin g that values of types ex and {3 can be compared, we can define
compari sons on the type Eitl!er ex /3. The instance d~clarations are
The type Either combine s boolean s and characte rs into a single type. We . !
can generali se the idea, and define instanc~ ( Eq ex, Eq {3) => Eq (Either ex /3) where
..
data Either ex 13 = Left ex I Right /3 Left x == Lefty ..... <x == y)
Left x == Right y = False
With this generali sation the previous. type is des~ribed by Either Boo/ Char. . Right x == Lefty = False
The naJJ:~.es te{t and Right introduc e two construc tors for building values of Right x == Right y = (x == y)
type Either; these construc
. . . ' -
tors are nonstlic t function s with types
Left .... ex - Either ex /3 instance ( Ord ex, Ord {3) '* Ord (Either ex {3) where
Rif1ht .... f3 - Either ex {3 . I,eft x < Lefty = (x < y)
1: Left x .< Right y = True
There are two key properti es that distingu ish construc tors such as Left and Right x < Lefty = False
Right from other function s. First of aU, t;here is no associat ed definition: con- Right x < Right y = (x < y )
structors just construc t. for example, Left 3 is an expressi on in. !ts simplest

possible fom1: w e c;Jid also have installed these instance s automat ically by writing
'? Left.3 data Either ex {3 = Left ex I Righi' 13
Left 3 ": deriving (Eq, Ord) .

The second property is that expressi ons involving Left anq Right can appear ~s Except for one importan t point we have now covex:ed the main details of how
patterns o~ the left-han d side of definitions. For exan1ple, new datazypes are declared. The remainin g point is the fact that data type de
claration s can be recursive. Recursive datatypes will be dealt with in the fol
case .. (<X - y, {3 - ;y) - Either ex {3- y lowing chapters .
case (f, g) (Left x) - fx
case({, g) (Right y) - gy
Exer4se s
Using case we ca.n, define plus b};. 2.5.1 .Oe,fu1e a function \vith source type Either Boo/ Char that behaves differ
. Plus - Either ex {3 - Ei.ther y ~ ently o~1 the three argumen ts Left .L, Right J., and .l .
.,. (<X- {3, y-o)
plus ({,g) == case (Left {,Right g) 2.5.2 Prove that case({, g) plus (h, k) = case ({ 11, g k).
48 2 I Simple datatypes 2.6/ Type synonyms 49

2.6 Type synonyms dedaratioris:


. .
'
- -(OI, ix.)'
. :

type Pairs 01
Before proceeding, it is convenient to introduce a simple notational device for . type Automorph cy - cy -01
giving alternative names for types. names that are more suggestive of the pur:
poses for which they are intended. The device is called a cype synonym dec-
type Flag 01 - ( e<, Boo_l)

laration. We will introduce the idea through a couple of-simple examples . . Two type synonyms cannot be declared in terms of each o~her sii_lc~ every syn
First, recall the function roots of Section 2.4 which was assigned the type onym must be expressible in terms of existing types. On the other hand, it is
legftimate to declare a Syt)Onym in terms of another synonym .. For ex,ample, .
roots :: (Float, Float, Float) - (Float, Float)
type Bools = Pairs Boo/
As an alternarive to this type description we can introduce two rype synonyms
There is no circularity here since Boals is a type synonym for PairsBool, which in
type Cdefl's - (Float, Float, Float) turn is a synonym for (Jloo/, Boo/). For the same reason, one can mix synonyms
type Roots = (Float, Float) and declarations; for example,

data. OneTw.o 01 = One 01 Two (Pairs c,~)


These d eclarations d o not inroduce new types but merely alternative riamcs .
for existing types. Th e type of roots can now be described in the equivalent
form 2.6.1 New types
It is important to 'emphasise that type synonyms, not being new types, inherit
roots :: Coef{s - Roots
whatever. class instp,nces are declared for the tmderlying rype: one cannot give
new instance dechirations. For example, (==) ~s defined on Boals because it is
The new type description is shorter and more informative.
defined on the tmderlying type (Boo/, Boo/). Similarly, the meaning of (==) on
As another example, suppose we want to define a function, move say, that
Angle is just the meaning of(==) on Float. ln practice, this m ay not be what we
takes a number, representing a distance, an angle and a pair consisting of a
wapt. For example, one might want to declare equality on Angle to be equality
coordinate position, and m oves to a new position as indicated by the angle and
modulo a mUltiple of 2rr. We can always use a specially defined function for
distance. We can introduce type synonyms for these values as follows:
this.purpose,t?ut if we want to u~e (==), then we have to declare Angle to be a
type Position = (Float, Float) new datatype and not a rype synonym:
type Angle - Float data Angle = MkAngle Float
type Distance = Float
instance Eq Angle where
Note that both A ngle and Distance are introduced as synonyms for Float. We MkAngle x == MkAngle y = normalise x == normalise y
can now define move by
normalise:: Float - Float
move .. Distance- Angle- Position - Position
normalisex
moveda (x,y) = (x+dxcos a,y+dxsina)
x<O = normalise ( x + rot)
The trigonomerric functions cos and sin are predefined. As with the type as- x ~ rot - normalise (x- rot)
SiJ:.'l1ment of roots, the type assigmnent of move is both short and helpful in otherwise = x
understan'd ing what move does. . where rot =2 x pi . .',

Type synonyms can be parameterised with one or more type variables, just
like datatype def'initions. For example, all of the following are valid synonym The flffiC[ion normalise returns an angle e in the range 0 < e < 2rr.
-so
I
2/ Simpic datal}pcs 2.7 I Strings 51 l

The prtce paid for using the above definition of equality on angles is that The datatype ( cx] of lists of type cx wiU be studied in Chapter 4. St.rings are Jr'
elements of Angle have to be 'wrapped' with a constructor MkAngle to give a new denoted with a special syntax: the characters comprising the string are enclosed I'.I
datatype. This has two disadvantages: One is that operations to construct and in double quotation marks. The difference between 'a' and "a" is that the former f.
examine angles have to be continually unwrapped and rewrapped. This adds is a character, while the latter is a list of characters that happens to contain only

'
to the running time of the operations. Secondly, in declaring a new datatype one element. For example,
we also declare possibly umyanted elements. For example, Mk.Angle .l.. is also
an element of Angle. ln other words, Angle,and Float are not isomorpltic; . .. ? "au
. Rccognismg this,' Haskell pio~.eies. an
alternaUvc mechanism for cr~<!ting uau

new types. The deciaration


? "Hello World"
newtype Angle = Mk.Angle Float "Hello World"
. . :
introduces Angle as a new type whose representatio n is exactly the same as ? "This sentence contains "tanewline."
Float. It differs from the type synonym in that a new tyi>e is constructed, one "This sentence contains -+a newline.'' .. ' . ,..,
that can have new class instances declared for it. It differs from a data.dec. .
laration in two ways. Firstly: wrapping and .unwrapping. with Mk.Angle does not .Sttings, being a rype synonym and not a sep'a rate clatatype, cannot be declared
add to the execution tirlle; although occurrences of Mk.Angle have to appear in separately as in~ta,hces of .Eq and Ord. They inherit whatever instances are
the text of a program, they can be eliminaEed before evaluation begins. The declared for general lists:
values of a new type are systematically replaced by the corresponding values_
of the underlying type. The second difference, necessary for thesafe elimin- instance Eq ex ~. Eq [ex] where
ation described above, is that MkAngle is a strict constructor, so MkAngle .l.
and .l. denote the same value. Hence the values of Angle and Float are_in exact instance Ord ex ~ Ord [ex] where
one-to-one correspondence. . ...
...---
. .
. . "" . . . ..
.
...
\
I
The missing instance definitions will be given in Chapter 4. Comparisons on '
Exercises strings follow the normal lexicographic ordering since that will be the ordering
2.6.1 Suppose you wanted to treat two distances as equal if th~y were less than defined for lists. For example,
10 miles apart. Can you define an equality test on Distance, when Distance is a :
\

? "hello" < "hallo"


type synonym? lf you pm, can you call it (::)?
False
2.6.2 Consider the declarations
'. ? "Jo" < "Joarma"
daia Jane = MkJane Int
True '.!,

ne~ty-pe Dick = Mk.Dick Int r


I
Most often, we want to print strings literally, which means that (i) the double
By defining appropriate functions, demonstrate that jane and Dick are different ,,I.
quotation marks do not appear in the output; and (li) special char~cters, such
from one another.
I
\

as ,-f', are printed as the actual character they represent. Other effects we
might want could be ptinting a string to a file, or Jeading a string from a fllc.
2.7 Strings The subject of input and output will be dealt >:ith in Chap.t er 10; for now it is
suffi.dent to observe that Haskell provides a primitive conunand for printing
A list of -c haracters is called a string. The type String is a synonym type: strings. The command is called putSir and its type is I
'\'
\
typeString = [Char] putStr :: String - IO () I.
I!
I
'!
.,, .
52 2 I Simple datacypes 2.7 I Srrings 53

Evaluating the command putStr causes the string to be printed literally. For PreVious -requests to evaluate and print v~ues of type a nave depended on a
example, declaration that ex is an instance of Show. The types Char and String are also
instances of Show and, for example,
? putStr "Hello World"
Hello World show 'a' = " 'a' "

? putStr "This sentence contains -~a newline." Applying putStr to the last expression on. the rigl~r r emoves tile outer parr of
This sentence contains m
double quot~ltion marks and results the tJuee character'~ ~a peiOg printed.
a newline. Some 'iiistances pfShow
. . -are. proVided as prinu'tive. For example, integers
are printable and the value shown Cor an element nof type Integer is the list
In fact, every request to show a value at the terminal involves an !!XJ)lidt or of characters that m ake up the decimal representation of rr. The same. is true
implicit applicaric:m of putStr as we will now see. of other numb er types. For example,
...

2.7.1 The type class SI1 ~>W


slu:iw 4 2 = "42" ..
show ~42. 73 ) =. "42.73"
Depending on the application, a programmer may want to produce tables of
numbers, pictures of various kinds, or formatted text. In order to achieve these Use of show ena.bles us to connol layout. In the following exa:inples, the oper-
etiects in a consis~ent fashion, Haskell provides a special type class Show, which *
ation concatena'te's two lists and is described in detail in Chapter 4.
is declared by
? putStr ("The year isu" *show (3 x 667))
class Show IX wher e The year is 2001 .
showsPrec :: Inc. - IX - String - String
. . . ? putStr (show 100 * ..-+"*show 101 * ..-1" *show 102)
The function slwwsPrec is proVided for displaying values of type ex: This fimc- 100
tion is designed for flexibility and efficiency, but it is a little complicated and we ~01
will not describe _the purpose of each ar~en t here (but see Sections 5.3 and 102
7.3 wliere more details are given). It is sufficient to say that, using showsPrec,
it is possible to define a simpler fwKtion If we do not declare, for example, Day to be a member of the type Show, then
the values of Day cannot be printed. Thus,
show :: Show IX ~ ex - String
?Mon
The function show takes a value and converts it to a string. For example, Boo/
Error: carmot find defini_tion of show for Day
is declared to be a m ember of Show and shovi is defmed for booleans
'
so that .. ~ ., - .. ' .

show False - "False" Fortunately, we do not have to proVide an eXplicit declaration of Day as a m em-
ber of Show. It is sufficient to declar e Day by
I
show True - "True"

A request to evaluate a boolean expression and display the result at the terminal dala Day = Sun I Mon I Tue I Wed I Thu I Fri Sat
involves a silent application of the function putStr show. The boolean value deriving ( Eq, Ord, Enum, Sh ow)
is convertt!d into a string via show and the result is printed Via purStr. We can
make this application explicit: The Show class can be derived automatically for datatypes.
On theother hand, the derived definHions may not be exactly what we want.
? putStr (show True) For example, in Section 5.3 we will want to install a certain data type as a member
True of Show, but do not want the visible appearance of elements to be that given
54 . 2 I Simple datatypes 2.8 I ChajJter notes 55

by the derived definition. 1-Ienc:e we ,.,.ill need to give an instance declaration 2.7.2 What are the values of the following expressions?
explicitly. . . . . . ., -
..
..
It is also useful to be able to introduce datat)rpes whose values should. not show (show 42}
be printed, even though they could be by including Sllow in a deriving clause show 42 -t+ show 42
for the datalype. We will explain this further in Chapter 8. show" t"
Finally, if we want to design a particular way of printing the elements of a
2.7.3 Suppose a date is represented by a triple (d, m,y) of tlu-ee Int integers,
datatype, then we 'can always do so by setting up a specific function for the
where d is. the day, m the month, and y the year. Define a function slwwDate
pmpose. We do not have to mi:tke use of the function show. To illustrate this_
that .takes a date and prints the corresponding date. For example,
point, let us.show how r9 customise the printingof elements of the datatype ,,
showDate (10; 12, 1997} prints as "10 December, 1997"
data Data = Pair Bool Int
.A$ a more complicated version, revise the definition so that
If we had asked for it, the del'ived instance of Show would lead to the following
way of printing elements of Data: showDate (10, 12, 1997) prints as "lOth Decemb~~. 1997"
. showDate(3l;12,1~97) .prints as "31st December, 1997"
? Pair True (3+ 4)
Pair True i .
' _; 2.8 Chapter notes
There is, however, nothing to prevent us defining
. Boole (184 7) introduced a calculus for reasoning about truth-valued expres-
showData :: Data - String sions, though he wrote x + y for x v y and xy for x A y. Modern accounts of
showData (Pair b n) boolean algebra and logic, suitable for computing scientists, include Ben-f\ri
- if b then"+"* shown else''-"* slww n . (1993), Burke and Foxley (1.996), Gries and Sclmeider (1995}.
Haskeil uses the syntax && for A, and l l for v. The Haskell syntax for ==
putDaca - putStr showData
and* is== and/=. The comparison qperators ~and:<: are written<= and>=.
Forexample, The Haskell character set is bas.ed on the ISO Unicode standard 8.859-1. In :'
. common with most other languages, Haskell uses escape s'equences for denot-
? putDilta (Pair Trl,le (3 + 4)) tng control characters. Fpr example, a newline character is denoted by \n, tab . '
+7 by \t, and backspace by \b. See the Haskell 1.3 report. or ISO (1.989), for
further details on the representation of control codes and other nonstandard
The definition of showData makes use of the furi.ction show for Int, b~t does. characters.
. notprovide
- a .function show
. for Data: In other words, Data is not made
. a fully The theoretical fmmdations of type classes are studied in Wadler and Blott
paid-up member of Show just because we have provided a way of prin.ting its . ..
(1989) and Jones (1992; 1995). The standard type classes of Haskell have
elements. Nor does'non-membership imply a second-class statusfor Data: .type . evolved through various versions of the language.
Classes are there simply for om convenience and to provide standard methods The notations f x g and f + g are used in a branch of mathematics called ..
in
for handling the predefined types Haskell. New data types do nothave to join category theory, which from one point ofyiew can be regarded as a foundation
''
,_'
,.
if we don't want them to. for functional programming. Suitable texts for computing scientists include ..
Barr and Wells (1995), Pierce (Hl91), Bird and de Moor (1997).
Exercises
... '.
2.7.1 Put the following strings .i11 ascending order' ."McMillan", ~'Macmillan",
I
i
!
and "Macl\ll.illaii". .. .
....
.. . .,

. .
: Chapter 3

Numbers
..

! " ..
..
,.

. . ..
. ...
. .
We have already mentioned three distinct types of number: arbitrary-precision
integers (elements of Integer), limited-precision integers (elements of lnt), and
single-precision floating-point n~mbers (elements of Float). Other types of
number one might wish to use include cl.ouble-precislon floating-point num-
bers, rational numbers, and complex numbers. The definitions of the arithmetic
operations are different for different kinds of number; for example, iriteger di-
vision is quite different from real division, and one caruiot compare complex
numbers by ( <:). Haskell provides
. a sophisticated hierarchy
. of type classes for
describing various ldnds of number, and we will give a simplified .accourH of
the system in Section 3.4.
Although (some) numbers are provided as primitive datatypes, it is theor-
"

etically possible to m:tt:~d{{ce 'tl~elilthrough suit"blc datatype declarations. We


will begin by seeing ho~ this is done. The discussion' serves to introduce three
important ideas: recursive datatypes, recursive definitions, and proof by in-
duction. These three ideas, which constitute the holy trinity of functional pro-
gr~ming, will be a major theme of the following three chapters as well.

.'
3.1 Natur<il numbers
. .
The natural numbers are the numbers 0, 1, 2, and so on, used for. counting. The
type Nat is introduced by 'the declaration
..., .. .
data Nat = Zero I Succ Nat

Nat is our first exampie of a recursive da't<llype declaration. The definition says
n
that Zero is a value of Nat, and that Succ is a value of Nat whenever 'n is. In
particular, the constructor Succ (short for 'successor') has type Nar :... Nat. For
.,.,
I.

58 3/ Numbers 3.1/ Nanzral nwnbers 59

example, each of Given +,we can define x by

Zero, Succ Zero, Succ (Succ Zero)


(X) .. Na( -Nat - Nat ..f
:.i~
m x Zero =! Zero :..

is an element of Nar. As an element of Nf:!l the number 7 would be represented m x Succ n - (m x n) + m


by
Given x, we can define exponentiation ( 1) by
Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) ( I) Nat -. Nat - Nat
m I Zero - Succ Zero ,,..
Every natural number is represented by a unique value of Nat. On the other
m I Succ n - (m I n) x m
hand, not every value of Nat represents a well-defined natural number. In fact,
Nat also contains the values .L, Succ .L, Succ (Succ .L), and so on. These addi- a
The definitions of+; X, and I follow similar pattern, nnd Section 3.3 contains
tional values will be dis.c ussed later. a discussion of how this common pattern can be exploited.
Let us see how to program the basic. aritlunetic and comparison operations We can define Nat to be a member of the type class Eq with the i.ostance
on Nat. Addition can be defined by . . ' cledara tion
.
instance Eq Nat where
' '

.( +) .... Nat - Nat - Nat .. '


I

m +Zero = m Zero == Zero - True '!


rn + Succ 11 =' Succ (m + Zero == Succ n - False '
'"
n) .. .. Succ rn =~ Zero = False f.
'I

!I
This 'is a recursive definition, defining + by 'p attern matching on the second Succ m == Succ n - (m == n)
ll f ;
argi.unent. Since every clement of Nat; apart from .L, is either Zero or of the .ft!;
This is nlso a recursive definition, using panern matching on both arguments. 'l
form Su~c n where n'is. an element of Nat, the two patterns in the equations for
' I
; '

+are disjoint and cover all n umbers apart from i. . $imilarly, we can define Nat to be a member of Ord with the declaration .
.;
is
Here how tero .t Succ (Succ Zero) would be evaluated: ;
instance Ord Nat where 't '.I
I

Zero< Zero - False


Zero+ Succ (Succ Zero) ,
Zero< Succ n - True !:

= {second equation for +} Succ m <Zero = F.alse ' '.


r
Succ (Zero+ Succ Zero) Succ m < Succ n - (m < n)

{second equation for+} . We can print elements of Nat by defining a function showNat:
Succ (Succ (Zero+ Zero))
slwwNat .... 'Nat - String
{first equation for +}
= showNat Zero - "Zero" ,

Succ (Succ Zero) showNat (Succ Zero) = "Succ Zero"

This calculation shows why it is not a practical propo~ition t~ inti~oduce natural


slwwNat (Succ (Succ n)) = *
"Succu(" showNat (Succ n) * ")"
numbers ttuough the datatype Nat: arithmetic would be just too inefficient. In The definition of showNat makes use of three patterns, namely Zero, SL1cc Zero,
' . . . . .. . ' .' . '
particular, calculating . m + n would require (n t 1) evaluation steps. On the, and Succ (Succ n). These patterns are different from one another and together ,.
other hand, countir!g on your fingers is a good way to tmderstand addition. cover all the elements of Nat, apart from .!.. There are tluee patterns in the
60 3 I Numbers. 3.1 /'Natural numbers 61

. . ..
definition of showNac because the first 1:\.YO na.tural numbers are shown ~thout The Fibonacci function is defined by .. . '

.
parentheses.
Alternatively, we could have introduced Nat with the declaration fib .... Nat - Nat
fib Zero - Zero .
data Nat = Zero I 'succ Nat fib (Succ Zero) - Succ Zero
deriving (Eq, Ord, Show) fib (Succ (S~cc n)) = fib (Succ n) + fib n
With this declaration, Nat is installed automatically as a member of each of
The definition of fib ~ses the same three patterns as in showNat.
the type classes Eq, Ord, and Show. In particular, the function show for Nat
gives the same func tion as sfwwNat. As we will see later, ail number types arc
equality types and are instances of Show. Hmvever, not all numbers can be 3.1.1 Partial numbers
compared by ( < ).
let us now return to the point about there being extra values in Nat. The values
The remaining arithmetic operation conunon to all numbers is subtraction . . .. ' '

. (- ). However, subtraction is a partial operation on natural numbers. The clef .L, Succ .L, Stice (Succ .L). ...
inition is
are all different and .each'iS 'also an element of Nat. That they exist is a con
..
(- ) Nat- Nat- Nat
sequence of three facts: (t) .L i:; an eJement of Nat because every datarype
m - Zero - m declaration introduces at least one extra value, the undefined value of the type;
Succ m - Succ n - m- n (ii) construct.or functions of a datatype arc assumed to benonstrict; and (iii)
This definition uses pattern matching on both argmnents; taken toge ther, th~ Succ n is an element of Nat whenever n is.
To appreciate why these extra values are different from one another, sup-
patterns
. . but not exhaustive. For example,
are disjoint
pose '!"e define undefined :: Nat by the equation undefined = undefined. Then
Succ Zero- Succ (Succ Zero)
{second equation for (-)) ? Zero < undefined
{Inrerrupte.d! }
Zero - Succ Zero I
? Zero < Succ undefined
. {case exhaustion}
True
.L
? Succ Zero < Succ undefined
The hint. 'case exhaustion' in the last step indicates that no equation for (- ).
. has a pattern that matches (Zero - Succ Zero). More generally, m .- n = .L if
[Interrupted!}

m < n. The partial nature of subtractiqn on the natural numbers is the prime ? Succ Zero< Succ (Succundefined)
motivation for introducing the integer numbers; over the integers (- )is a coca/ True
operation. On rhe other hand, we can always define a total operation e on
natural numbers so that men "' m- n if m ~ nand me n = Zerb if m < n. One can interpret the extra values in the follo\'.rJ.ng way: i corresponds to the
The definirion of e is left as an exercise. natwal number about which there is absolutely no information; Stice .L to the
Finally, here are rwo more examples of programming with Nat. The factorial natural hl..lmber about which the only informar~on is that tt is greater than Zero;
function is defined by Sue<: (Succ .L) to the 'natural number about which the only inf9~~ation i~ that
it is greater than Succ Zero; and so on.
fact .. Nat- Nat There is also one further value of Nat; namely the 'iniinite',number:
{act Zero = Succ Zero
{act (Succ n) = Succ n x fact n Succ (Succ (Succ (Succ .. .}))
62 3./Numbcrs 3.2 /Indui:riOII 63

This number can be defined by . . 3.2 Induction

infinily Nat In order to reason about the properties.of recursively defined functions over a
infinity = Succ infinity recursive data type, we can appeal to a priliciple of structural induction. In the
. . case of Nat the priricipie of structural induction can be stated as follows: in
It is different from all the other numbers because it is the only number x for order to show tha,t some property P(n) holds for each finite number n of Nat,
which Succ m < x returns True for all
finite numbers J!l. In.this sense, .infinity .it i.s sufficien,t to show:
of
. is the largest element . Nat.
. If we request the value of in(inily, then we ob~aj.~;~
Case (Zero). That P(Zero) hoids.
~

? infinity
Case (Succ n). That if P(n) holds, then P(Succ n) holds also. .
. Succ (Succ (Succ (Suce (Succ{Intemrpted!}
Induction is valid for the same reason that re.cursive definitions are valid: every
The number infinity satisfies other properties, in particular n+ infinity = infinity fuute nu'll1ber is eiti1er Z(}ro or of .th~ {onn Succ n where,n is a finite number. If
(or all numbers n. The dual equation infinity+ n = in/'inity hold~ on~y (oi' finite
we prove thefirst case, then we have shmvn that the property is tme for Zero;
numbers n. We will see how to prove assertions such as these in the next
if we also prove the second case, then we have s,hown that the property is tru.e
section. . . . ' .
for Succ Zero, since it is true for Zero. Bm now, by the same argument, itis true
. To sunirnarise this discussio~ .;,e ~an divide the values of Nat into three for Succ (Succ Zero),- and so on.
classes: .. -
The principle needs to be extended if we want to assert that some propos
ition is uue for ail elements of Nat, but we postpone discussion of this point
The finite nutnbers, those that corresponcLto well-defined natu.raJ num- I ~ '

to the following section. .


bers.
As an example; let us prove that zero + n = n for all tinite numbers n. In
The partial numbers, .l, suo:: i., and so on. words, Zero is a left unit of+. Recall that+ is defined by the two equations
The infinite nwnbers, Qf which there is just one, namely infinily. m+ Zero = m
m + Succ n. = Succ (m + n)
We will see that this dassification hold~ true of all tecursive types. There will be ;
the finite elements of the type, the partial elements, and the infinite eh~~1ehts. The first eq~ation asserts that Zero is a right unit of +. In.general, e is a left
Although the infinite natural number is not of ID!lCh use, the same is not tTue unit of Ell if e Ell (( x for all x, and a right unit if x Ell e = x for all x. If e is
of the infiriite ~alues of other datatypes. both a left unit and a right unit of an operator Ell, then it is called the unit of
Ell. The tenninology is appropriate since only one value. can be 'both a left and

Exercises right unit. So, by proving that Zero is a left wlit, we have I?roved that Zero is .
the unit o f
;: .. +. . . ..:... : . .
3..1.1 'construct the pcis~tive numbers as a recursive dat~type.
Proof. The proof is by induction on n. More precisely, we take for P(n) the
3.1.2 Define a fimction. convert :: Nat - Integer that
. converts a natural number
. assertion Zero+ n = ri. This equatiori is referred to as thei..riduciion h~potiJesis.
to an integer. .
x
3.1.3 Define versions of + and that use pattern ~arching on the first drgu
tncnt~ Cari the san1e be done foi ti . .. , Case (Zero). We have to show Zero+ Zero = Zero, which is immediate from the
first equation defi.ni..Iig +.
3.1.4 How _many. evaluation steps doe~ H take to evaluate m x n?
... .
3.1.5 Define a total version e of subtraction so that men :;o Zero if m < n. Case (Succ 11). We have to show that Zero + Succ n = SLICC n, which we do by
..

64 3 I Numbers 3.2 I Induction 65

For the right-hand side we reason .. ..


simplifying the left-hand expression:
Zero+ Succ n (x 1 m) x (x I Zero)

{second equation for +} = {first equation for I}


Succ (Zero+ n) (x I m) x Succ Zero .

{induction hypothesis} {secorid equation for x}


Succ n .. (x t m) + (x ! m) x Zero
D {first equation for x}
(x t m) + Zero .
This example sl)ows me format we will 1.,1se for inductive proofs, laying out each
case separately' and using a o to mru:k the end. The very last step made use of = {first equation for +l
the induction hypothesis, which is allowed by the way induction works. X I m
As a more complicated example, let us prove the well-known law that for all
finite natural nwnbers x, m, and n, The two sides simplify to the same result, so they are equal. The simplification
of the right-hand side is the more complicated of the two because it involves
x t (m + n) = (x 1 m) x (x t n)
proving that Succ Zero is a right unit of multiplication..
For the proof w~ will need the definitions of X and I fro~ the' previous section,
repeated here for easy reference: Case (SLzcc n). Again, the idea is to substitute Succ n for n in the hypothesis,
and to simplify both sides separately.
mx Zero = Zero
m x Succ n = (m x n) + m First, the left-hand side:

m 1 Zero = Succ Zero x 1 (m + Succ n)


m 1 Succ n - (mIn) x m {second equation for +}
Proof. The proof is by induction on n, taking the induction hypothesis to be x t Succ (m + n)
{second equation for 1}
x I ( m + n) = (x 1 m) x (x I n)
(x l (m+n))xx

It is important to state the variable we are doing the induction on, since there {induction hypothesis}
.

arc three possible choices, namely x, m, and n. ((X I m) X (x I n)) X X

Case (Zero). The idea is to substitute Zero for n in the hypothesis, and then to Now, the right-hand side:
simplify both sides independently. (x J m) x (x 1 Succ n)
For 'the left-hand side we reason {second equation for I}
x I (m +Zero) (x t m) x ( (x 1 n) x x )

{first equation for +) The two sides simplify to two different 'exilressions, which are equal under
X I m the assumption that x is associarive. The proof of this claim involves another
'.

66 3'/ Numbers 3.2 /Induction 67

induction argument and is left as an exercise. {inductiO'n hypothesis} . .


((xtm)x(xtn))xx
0

Apart fr~nn one decision, the proof follows a fairly automatic sequence of steps: For the right-hand side. we reason
in each ca.se there is a substitution into both sides of the equation, and each (x t Succ m) x (x I n)
side is then simplified;each simplification step is determined by the shape of
the current expression in a fairly obvious way. {second equation for I}
The one inventive part consists of decidiiig what choice of variable to do the ((X I rri) X X) X (X I n)
induction on. In this example, there were three possible choices, but only two
reasonable ones, namely m and n. What would happen if we did the induction Now we need an extra assumption, namely that x is commutative as well as
on nf? Let us sec by doing the proof again: ,. . associative; that is, x x y = y x x. The two sides are equal tinder these two
,' .. assuniptions.
Proof. The proof is by induction on m. - '~
'. ' t

case. (Zero). For the-left-hand side we reason


The second proof is more complicated t h an the first in that it involves no fewer
. . xI (Zero+ n) thati four additional assumptions, all of which themselves have to be proved
by induction. The lesson here is that the choice of variable .on which to do
{claim: Zero + n = n for all n} induction (if there is a choice, of course) can be crucial. It seemed sensible to
X in start out by doing an induction on .n because + is defined by r:ecursion on its' .
second argument; then at least tbe first step of.simplification on the left-hand
for the righthand side we reason side is known to be a simple one. Fortunately, the rest of the proof was simpler
too.
(x I Zero) X (X I n)
{first equation for t l.
.3.2.1 Full.induction
Succ Zero x (x I 11)
In the form given above, the induction principle for Nat suffices only to prove
(claim: Succ Zero x n = n for all n} proper*s of the finite members of Nat. If we want to sho":V that a property P
xtn also holds for every partial number,
..
then we have to prove three
. thlltgs:

The two claims are that Zero is a left


. unit of +, and Succ
. Zero is a left unit
. of Case (1.). That P(l.) holds.
x. The proofs of the claims are left as exercises. Case (Zero). That P(Zero) holds.

Case (Succ m). For the left-hand side we reason Case (Succ n~, That if P(n) holds, then P(Succ n) holds also. ,.

x I (Succ m + n) We .can omit the second case, but then we can conclude only that P(n) holds
for every partial number. The reason the principle is valid is that every partial
{claim: Succ m + n = Succ (m + n)j number is either l. or of the form Succ n for some partial number n.
x t Succ (m + n) To illustrate,
. let us prove the somewhat counterintuitive
. . m+n=
resultthat
n for all number~ m and all partial numbers n.
{second .equation for I}
(xI (m + n))' >< x Proof. The proof is by partial number induction on n.
68 _ 3 I Numbers . 3.2 I lnducrioiJ 69

Case (J.)_ The equarion m + J. = J. follows at on~;e by qts~ ~au~tion .in the Case (Zero). We reason ...
definition of+. That is, 1. does not match either of the pattern,s Zero or Succ n.
. . . ' (m +Zero) - Zero= m

Case (Succ n). For the left-hand side we reason {first equation for+}

.. m-Zero= m
m + Succ n
Hence we'can take m - Zero = m to satisfY. the sase, The symbol := is used
{second equation for +l
to separate steps of the ~alcuJation since we are calculating with mathematical
Succ (m + n) assertions. not with values of a datatype.
{induction hypothesis} ' .
Case (Succ n). Wneason
Succ n
(m + St!CC n)- Succ n = m
Sine~ ~he right-hand side is also Succ n, we are done: {second equation for+}
0 .. sw:c (in+ n) - Succ n. . ~
. . {hypothesis (m + n) - n = m}
The omitted. case, namely m + Zero = Zero, is false, which is why the assertion
does not hold for finite numbers.
Succ (m + n) - Succ n = (m + n) - n
.
So, it is easy to extend induction to apply to partial numbers. What we also Replacing m + n in the last equation by m, we can take SLice m - Succ n = m- n
obtain as a bonus is that, having proved that an equation holds 'for all partial to satisfy the case. Hence we have .derived
numbers, we can assert that it holds f9r the infinite miml:ier infinity too. See
Exercise 3.2.7 for elaboration on this poinr. In particular, we can now assert m- Zero - m
that m + inf'inity = infinity for all numbers m. Succ m - Succ n = m- n

This is the prograrri t'o~ (-) seen earlier.


3.2.2 Program synthesis

In the proofs above we defined some ftmctions artd then used induction to Exercises
prove a certain property. We can also view induction as a way to synthesise 3.2.1 Prove that Suet Zero is a left unit of x.
definitions of functions so that they satisfy the propt;rties we want.
Let us illustrate with a simple example. Suppose ~ve specif}' subtraction of 3.2.2 Prove that if ED has a left unit a and a right unit b, then a = b.
' .
natural numbers by' the co~dltion . . ~ 3.2.3 Does the law x 1 (m + n) = (x I m) x (x r n) hold for all natural numbers
x, m, and n?
+ n)- n = m
is
(m
3.2.4 Prove that + associative, that is, (m + n) + p = m + ( n + p) for all natural
for all m and n. The specification
. does. not give a constructive definition of, ..(- ), numbers m, n, and p.
merely a property that it has to satisfy. How.ever, we, can do an induction proof 3.2.5 Prove that x distributes over '+, that is,
on n of the equation above; but view. the calculation as.a way of generating a
suitable definition of (- ). Unlike previous proofs, we reason with the equation k x (m + n) = (k x m) + (k x n)
as a whole, since simplification of b'o th sides independemly is nor possible if
we do not know what all the rules of simplification are. for all natural numbers k, m, and n.
70 3/ Numbers 3.3'/ Til e fold fUJJction
71
3.2.6 Define n by
The two equations for f can be captured in terms of a single fnnctioq, (oldn,
called the foid function for Na c. The definition is
?era n n - Zero
Succ m n Zero = Zero foldn .... (C< - e<) - C< - Nat - C<
Succ m n Succ n = Succ (m n n) foldn h c Zero - c
(oldn h c (Succ n) = h (foldn h c n)
What operation on integers does n correspo~d to? P.rove that m n infinity = m
for all elemen.ts m of Nat, finite, partial, or ih.finite. . : . . In particular, we have

3.2.7 The claim made in the text is that if P(n) is an equaHon that holds for all . m + 11 = {oldn Succ m n
partial nwnbers n, tl1en P(infinity) holds as we.ll. Any free variables in P are m x 11 = {old11 ( +m) Zero 11
r~qulred to be universally quantified. For instance, we can take P ( n) to be any mIn - {oldn (xm) (Succ Zer o) n
of the propositions
It follows also that the identity function id on Nat satisfies id = {oldn :S'w:c Zero.
. = (X
(for aU. x and m) X I ('m + n) I m) X .(X I n) A suitable fold function can be.dctlned for every recursive.type, and we will see
(for all m)
'
(m+n) - .n=m
other fold filllctions in the following chapters.
' . '. . In the examples above, each instance of {oldn also returned an element. of
' .
How.ever, we crumot in generai take P( n) to be an equaHon that involves an Nat. In the following two examples, {o/dn retwns an dement of (Nat, NaC):
existentially quantified vruiable. Consider, for instance, the proposition P(n) fact ..
~m~ . . . . Nat- Nat
. face S"!d {oldn {(Zero, Succ Zero)
(for some ftnite number m)' ne m = .L where f (m, n) = '(Succ m, Sqcc m x n)

where e is the total version of subtraction, satisfying n em = Zero if n < m. fib .. Nat- Nat
Show by induction that P(n ) holds for all partial numbers n. Prove, also by fib = {sc {oldn g (Zero, Succ Zero)
induction,.that in(inity e m = infinity for all fini te numbers m. where g (m, n) = (n , m + n)

The fnnction.{act computes the fac torial function, and fib computes the Fibon-
3.3 Tb:e fold function acci function. Each program 1vorks by fi rst computing a more general result,
namely an element of (Nqt, Nat), and then exnacts the required result. .fn fact,
Many of, the r~c~rsive definitions. seel:). so far bav~ a cor;nmon pattern, cX~mpli
'fied by the follch-.:ing defini.tion of.a ftmction f:
foldn f (Zero, Succ Zero) n == (n, (act n)
.. foldn g (Zero, Succ Zero) n = (fib n, fib (Succ n))
I .... Nal'- A
These equations can be proved by induction. The program for fib is more ef-
f Zero . - c ficient than a direct recursive definilion. The recursive program requires an
f (Succ,n) - h ~{ n) exponential number of + operations, while the program above requires only a
linear number. We vvill discuss etTiciency in more detail in Chapter 7, where the
Here, A is some type, c is an element of A, and .h :: A - A. Observe that ( .''' .,
programming technique that led to the invention of the new program for fib
works by talctllg an clement of Nat and replacing Zero by c and Succ by h. For will be StUdied in a moi'e general setting.
example, r tak~s ' ' . '
There are two advantages of writing recursive definitions in terms of (oldn.
Firstly, the definition is shorter; rather than having to write down two equa-
Succ (Succ (Succ Zero)) to h (11 (h c))
tions, we have only to write dowri one. secondly, il is possible to prove general
' .
.. ' ... .
.' 72 3 I Numbers '3.3 /
,. J
The fold function 73
; .. . . .
properties of (oldn and use them to prove properties of specific instantiations. For the right-hand"sidc w'c reason
In other words, rather than having to write down many induction proofs, we
have only to write down one. fo/dn h b Zero
{first equation for foldnl
3.3.1 .Fusion
b
To illustrate, let us prove the following fusion law for Nat. It states that '.
These two results have to be the same, so we have our second assmnption,
f : foldn g a = {oldn 11 b namely that fa =b.
under certain assumptions on the variables involved. The law is ~alled a fusion
Case (Succ n). For the left-hand side we reason
law because the computation of (is fused with the computation.of foldn g a.
Fusion laws can le<!.d to a significant increase in efficiency; instead of processing f ({oldn g a (Succ n))
an elemen! of a ~~~acype and then processing the result, we can sometimes
comoine' the two im:icessillg s teps into one. ' {second equation for {oldn}
. ' .
. Rather than state at the outset what the assumptions are that make fusion . .: f (g ({o/clri g an))
work, let us usc the induction proof to bring them to' the surface. . '
For the right-hand side we reason
Ploot We prove that ( (foldnga n) = (6ldn h b n by full ind~ction on n, deriving
the required assumptions along rhe \vay. {oldn h b (Sur:c n)
,.
= {second equation for foldn}
Case (.L). For the left-hand side we reason h (foldn h b (SUcc n))

f ((oldn g a .L) {induction hypothesis}


= {case exhaustion in definition of (o/dn} h ({ (foldn g an))
f.L These two rcsclts h~we to be the same, which follows if f' g = h f.
For the right-hand side we reason 0

foldn h.b .L
Since an equation that holds for all partial numbers also holds for the infinite
~.
;,
= {case exhaustion in definition of {oldn} number, we have proved
,.r
. .L Fusio~ theo~em for foldn. Iff }s strict, fa = b, and f g = h f, then
t
<
These two resui'ts have to be the same, so we have our first assumption, n~ely f {oldn g a = foldn h b
that f is a strict function. ''
...,.,
~ 3.3.2 Examples
Case (Zero). For the left hand side we reason .
'
Let us now use the fusion theorem r~ pr~ve that Zero rs a left unit of +; in
f ({oldn g a Zer o) symbols, Zero + n = n for all numbers n. Since n = (oldn Succ Zero n, our
.
{first equation for {oldnl obligation is to prove that
fa
..'
(Zero+) . {oldn Succ Zero = foldn Succ Zero
74 3 I Numbers .. 3.4./ Haskell numbers 75

An appeal to the fusion law says that this equation holds provided 3.4 Haskell numbers
Zero+ .L = j_ There are three kinds of integer: positive integers, zero, and negative integers.
Z.ero +Zero == Zero Therefore we could declare Inreger by a datatype declaration
. .
Zero+ Succ n - Succ (Zero+ n)
data Integer - Neg Positive I Zero I Pas Positive
All three equations arc immediate from the definition of +. data Positive == One I Succ Ppsilive
As a second example, let us show that Succ Zero is a left unit of x. By an
appeal to fusiQn, exactly as in the previous case, we have three conditions 'to The type Positive deliver.s the positive .naturalnwnbers, and the type Integer
check: delivers a signed positive nwnber, or zero. Having constntcted the integers,
as
we could construct the rationals pairs of integers, and the complex rationals
Succ Zero x .L - .L as pairs of rationals. We could also construct suitable approximatioQs of the
Succ Zero x Zero - Zero real numbers as sequencesJ}f d.ec~al digits. The bottom line is that we can
Succ Zero x Succ n. = Su.cc (Succ Zero x n) recreate all of ari'thmetic from scratc)l without appealing to anything mor~ than
purely symbolic computation. . ' -
-The first two are immcdiat~ from the definition of x, and the third is proved as However, every computer possesses a buiitin aritluuetic unit, capaQle of
follows: performing limited-precision integer.arlttunetic at least. In many computers
there is also a floating-point unit, and for those computers that do not have
Succ Zerox Succ n
such a device, floating-point arithmetic is coded efficiently as low-level software
(definition of x ) .routines. lt is far more efficient to make use of these facilities than to rely on
(Succ Zero x n) + Succ Zero symbolic alt'ernatives.
Numbers are dealt with differently. in different languages. For example, in
- {~efinition of+) Miranda there is a single type nun1 that contains both the arbitrary-precision
Succ. ((Succ Zero xn)' + Zero)
. integers and limited-precision floating:point nwnbers. Haskell, o~ the other
hand, divides the numbers up into distinct types. ln this book we will follow
{de~tion of +l the Haskell naming conventions and .refer lO the following lypcs:
Succ (Succ Zero x n)
Int singleprecision integers
Neither of these two r esults was proved using induction explicitly. The single Integer arbitrary-precision integers
use.of induction was iJ?. the proof of the fusion law. Float singleprecision floating-poin.t nwnbers
. .. . Double doubleprecision floatingpoint numbers
Exercises . - . .
~

There are other Hask.ell number-types, including the lype Rational, but we will
3.3.1 Prove that /oldn Succ Ze'ro. n = nfor ali elements. n of' ;Vat, finite, partial, . '
not i:nake use of them (the following section shows one way of defining rational
or infinite. . . .
'
' J nwnbers). Nor >vill we say exactly what ;single-precision' and 'double-precision'
3;3.2 Use the fusion law to pro~e that+ is commutative. mean, because the meanings can differ depending on the available hardware,
. .
x although there is a standard to which rnost computers adhere. We will see one
' \ '
3.3.3 Division of:n!;ttural numbers can be specified by the condition that (n way of implementing' arbitnny-precision arilhmetic in Section 5.3. Aritlm1etic
m)! n = 1.11 for all posltive n and all rrz. ConslTuct a program for division and with Intis the fastest of all; arithmetic with Integer is appreciably slower. How-
prove that it meets the specification.
. . . ever, where Integer arithmetic is exact; Tnl arithmetic is not; beyond a certain
3.3.4 The function log can be specified by the condition that log (2 t m) = m range integer overflow occurs and the compt,llCr may either give an error mes-
for all m. Conslruct a program
. . and prove that .it n;eets thespecification.
for log sage or sin1ply return incorrecl results.
.76 3/ Numbers 3.4/ Haskell numbers 77

Note that there is no type Nac of natural numbers iQ Haskell. Nevenheless, 3or 65472233, represents the applicatiori'of (romlnteger to the appropriate
the ghost of natural numbers is presenr in the integers because we q:m still Integer value. Hence
make use of pattern matching. For example, we can define
654 72233 :: Num ex ~ ex
fact .. Integer - Integer
factO - 1 Integer numeric constants are defined i~ this indirect way ~o that they may be
fact(n+ l ) - (n+ l ) xfactn interpreted as values of any appropriate numeric type.
.- Not all nUmbers can be compared by ( <); for example, compiex n umbers
This mirrors the recursive definition seen earlier, when we wrote '?ero instead cannot be. The type c~ass Real captures those kinds of computable number for
of 0 and Succ n instead ot n + 1. Pattern matching with integers is r estricted v{hich < is a meaningful operation:
to the subclass of natural numbers. Thus, the pattern (n + 1} matches only a
positive integer. Even though we could avoid pattern nuHChing by ust~g a case class (Num ex,-(!)rd ex} Real 01 where
I
=>
analysis (or, berter, by using a new version of {oldn}, rh.ere are mm1y examples coRational ::, ex - Rational
where 'Pattetn matching is the clearest inetliod' of definition. Ftrrthermore, .the . ..
use of pattern matching parallels the cases in an induction proof. . The type Rationat'consists of pairs oUnJeger numbers.and is discussed further
: ( ' ' ,; ' ' + \' ~. -

There is one crucial diffet:ence between the constructor Succ of Nat and the in the followinK section. The new function toRa(ional captures the idea that
function ( +1) on integers: whereas Succ is a nonstrict function, ( + 1) is strict. every finite-precision real number can be expressed as the ratio of two arbitrary-
Hence there arc no partial ~umbers in built-in aritlunetic. precision integers. The remaining type classes we will mention are Integral and
Fractional. The type class lmegral is declared by
..
3.4.1 The numeric rype classes class (Real ex, Enum ex) '7' Integral ex where
(div), (mod) .. ex- ex- oc
The same synibols, +, x, and so on, are used fof' arithnietic on each numeric
tolnteger ex - Integer
type, even though these operators denote different operations on different
types. In other words, +, x, and so on, are overloaded functions like == and The members of Integral are the tw~ primitive t)rp'es andr;teger. For each In't
<. Haskell uses a sophisticated system of type classes for describing rhe vari- type, the operators div and mod are provided as primitive. If x and_y are
ous types of number and we will not give details in tllis book. Instead, ~ve will
integers, andy is not zero, then x div y = Lx/y J. where lxJ. pronounced the
desctibe a simplified scheme that is intended to caprure the essential ideas.
'floor' of x, is the largest integer n satisfying n ~ x. In particular, ll3 .8j = 13
All Haskell number types are i.llstances of the type class Num defined by . and l-l3.8j = -14. We will discuss how to compute lxJ in Section 3:6. The
value x mod y is defined by the equation ..
class (Eq ex, Show ex) ~ Num ex where
. . . . . .. . . ' :. ... ~

(+),(-),(x} .. ex-ex-ex
. x = (x div y,) x y + . .(x mod y)
',
negate ex-cx
{romlnteger .. Integer - ex The number y in (x mod y) is called the modulus. Inmost applications the
modulus is positive. For positive y we have 0 ~ x mody < y. In fact, for positive
= x + negatey . r,
y the values >! div y and x inod are l:he unique integc1;s q and ,.satisfying the
condition
The class Num provides a default definition of (-) in terms of negate. All
numbers can be compared for equality and have printable representations. All x = q x y + r and 0 ~ r < y ..
numbers can be added, subtracted, and multiplied. Finally, there is a conversion
function {romfnteger for dealing wirh constants. An integer constant, such as When y is negative, we have y < x mod y ~ 0.

.,,..
'
..
"' l
..
'
78 3 I Nurnbers 3.5 I Example: rhe ralion_
als 79

The type class Fraclional captures those kinds of numbers for which division The function mkRat takes a P.air of integers and returns au element of Rational
is meaningful and contains the floaring-point number types Float and Do~:~ble: in canonical form: '

class (Num oc) Fractional oc where .. (Tnteger, Integer) - Rational


- -
~ mkRat
(/) .. ()( ()( ()( mkRat (x, y) = Rat (u div d) (v divdj
fromRationa/ Rational - ec where u = (signum y} x x
v = abs y
The conversion function fromRaeional is used for floating-point constants. A ) -d = gcd(u,v)
constant, such as 2. 1414, stands for an application of {romRational to the ap- . .
propriate value of type Rational. Thus, - We will build ration~ numbers only through the use of mkRat, thereby guar-
anteeing all rational numbers are in canonical form.
2.1414 :: .Fractional C< ~ ex The.type Rational is declared as a new type rather than simply a type syn
onym for ([nteger,Integer) because the .equality and comparison operations
Floating-point cons tants are defined in this indirect way so that they can be on Rational are different from the corresponding operations on paiJ;s. Foi ex
interpreted as values of the appropriate munetic types. an1ple, (2, 1) < (3,2) o~ pairs, ~ut'as niti~nals we want 2 > 3{2. Accordingly,
... we define

Exercises

instance Eq Rational where


3.4.1 What iS the value of 3 ttiod ( -4)?
. Rat. x y ==Rat u v = . (x x v) == (v x y)

3.4.2 Show that when y is negative, y < x mod y ~ 0. instance Ord Rational where
3.4.3 Is it the case th~lt LLxJJ = LxJ? Rat x y < Rat u v = (x X v) < (y x u)

. if both Rat x y and Rat u v are in canonical


The. definition of ( <) is correct only
3.5 Example: the rationals form.
- We can show a rational number by defining a special function showRat:
- . y) of integers that represents the number. xfy.
A rational number is a pair (x,
For ~xamp le, (l, 7), (3, 21}, and (168, 1176) all de.note tlie fraction 1/7, and showRat (Rat x y)
( -1, 3), (1, -3 ) 'both denote the fraction -(1/3). However, only fractions (x, y} = if y == 1 then show x else show x * -"1" ft. showy
with y * 0 represent well-defined V(ll~,Les.
Since. there is. an infinite nwnber of \~ays to represent one and the same This del.'iilition makes use.of the primitive show function for the trlJe Integer,
rational,
. it is sensible
. to choose a caJJOnical represemation. . . can
A fraction and also the operator* for concatenating two strings (cliscuss~d in the follow-
always be represented uniquely by a pair (x, y) in whi.ch y > 0 and gcd (x, y) = 1, ing chapter). Provided its argwnent is a rational in cruwnical form, sfwwRat
where gccl (x, y), the greatest common divisor of x a11dy, is ddined below. In . prints a sensible result. .
partiCular, the unique r'epresentation of 0 satisfying these conditions is (0, 1).. The problem with s~owRat is that it does not declare Rational as a mem
.
Our aim in t\1is
. section is to install. the rationals as a Haskell number type. ber of the type class Show; Such a de~laration is needed i.f we want to install
First, we introduce Rational as a datatype: Rational as a proper number type. One can use the default definition by includ-
ing a deriving clause in the de~laration of Rational, but the result is a function
newtype I~alional = Rat l~?teger Inrege~ . ... show that is different from showRat. This point aside, we can declare Rational
. 81
80 ... 3 I Numbers 3.6 I Example: linear and binary search
..... :: ~
. .~
to be a member of Nlim by declaring (x,y) ~-vith y > 0 and gcd (x,y) = 1'. - . ' . .

instance Num Rat'ional where 3.5.2 An integer x can be represented by a pair of integers (y: z) with x =
10 x y + z. For example, 27 can be represented by (2, 7), (3, - 3), and (1, 17),
Rarx y+ Ratuv- mkRat(xxv+uxy, y xv)
among others. Among possible representations we can choose one in which
Rae x y- Rat u v = mkRat (x x v - u x y,y x v ).
abs z < 5 and abs y is as small as possible (subject to abs z < 5). Show that
Rae x y x Rat u v - mk.Rat (x x u, y x v ) each integer has a unique representation of rhis form, and define a function
negate (Rat x y) - mk.Rat ( -x, y ) repint so that repin' x returns this ~anonical _representation. .
{romfnteger x = mk.Rat (x, l )

It remains to define gcd. There are two slightly different ways that the function 3.6 Example: linear and binary search
gcd can be specifie d. One is to say that gcd (x.
y) isthe hrrges t positive 'integer
d that divides both x and y. The other way is to say that gcd' (x, y) = d if The function L- J. raking an arbitrary real number and returning an integer, is
and only if (i) d diVides both x and y; and (ii) for. all e, if e diVides both x more primjtive than d~v. but it cannot be implemented in Haskell which can
and y,''then e diVides d. Under the first specification we have gcd (0, 0) = J. represent only limited-precision real numbers. Nevertheless, it is instructive
because every positive integer diVides 0, so :there is rio largest one; under the to see how floor :: Float - Integer can be programmed. The problem isn't
second specification we have gcd (0, 0) = 0. Apart 'from this one case, the tw~ . as' simple as one' inight thirik, so we will develop a program ill a systematic
definitions aie equivalent. With the second specification, gcd can be computed manner. In fact, we wm develo'p two programs, one much more 'effident than
recursively by Euclid's algorithm: the oth~r. The two strategies behind the two programs are called linear and
binary search: The section ends with a second application of searching to the
gcd :: (lnteger,Integer) -Integer
problem of computing square roots.
gcd (x, y ) = if y = 0 then x else gcd (y, x mod y)
' ..,.., ' e

let us begin ~-vith the specil'ication:


For example, since Omod 3 = 0, (- 6)mod4 = 2, and (-3)mod l = 0, we obtain
floor Float - Integer
gcd (0, 3) = gcd (3 , 0) = 3 floor ~ .= n - n ~ x < n+ l
gcd ( - 6, 4 ) = gcd (4 , 2 ) = gcd (2, 0) = 2 ..
Thinking ahout.\vhat shap e the program for floor might take, it Is tempting ~o
gcd ( - 3, 1) = gcd (l , o ) = 1
. I
plunge immediately 'into a case analysis, considering what to do if x is positive,
Finally, we can declare Rational as an instance of the type class Fractional by what to do if it is negative, and, possibly, what to do if it is zero. But the spe
cification does not men tion cases and, since programs th at avoid case analyses
instance Fractional Rational where .-. .. ..
.:-- ~
are clearer and simpler than those that do, we should try n ot to mention cases
{romRationa/ = id either.
wewm have to search for n, and the specifi.cation suggests at least orie way
Rae x ytRat Ll v that the' search might be conducted: we can search for an n satisfying ~ .s x
u<O = mkRat (-X X Y, - y XU) and then increase n until the condition x < n + 1 also holds. Dually, of course,
1.1 :: 0 = error "division by 0" we could first Search for an n SUCh that X < n + l and then decrease n until the
u >O = mkRat (x x v,y xu ) condition n ~ x hoJd as well. The idea of searching until some condition holds
can be encapsUlated in a function until, .clefmed by

Exercises until (IX -Boo!) - (IX - IX) - IX - IX


until p f x - if p x then x else Lmti/ p t' (f x)
3.5.1 Using the fact that for positive integers x andy, if x diVides y andy divides
x, then x = y, prove that each rational number has a unique representation To search for an n satisfying n .s X., where x is some fixed number, we can
-
82 3/ Numbers 3.6 t Example: linear and bin.! lry searcll 83
-
begin With any int_eger we like, and then decreaseit until "thecondition holds. m ~ X < n, and then tO bring 111 and n closer together, SO that eventually the
For example, the search condition m + 1 = n also holds. The advantage of decoupling the two searches
is that we can make use of larger steps. More precisely, consider the pair of
lower Integer - Integer searches
lower - until (.S x ) decrease, wheredecrease n = n - 1
lower = until ( :::; x) double
applied to any starting value will do the job. The search will terminate because upper - until(> x) double
for every ref\1 number x there is an integer n with n :::; x. .
The integer n found by the first search may be far too small, so we need a where double n = 2 X n. ,Provided lower iS applied tO a negative ntimber, and
to
second search i.ncrease n until the condition x < n + l.is satisfied as well.. We upper is applied to a positive one, the two searches are guaranteed to find .a
pair (m, n) ~vith nt .S X< nina number Of Step's proportional to log2 (abs 'x).
need to increase h insteps of 1 to ensure that the condition' n:::; :(.is maintained.
The second search can be written in two ways, either as These two searches have to be Stlpplemented with a third search that brings the
pair (m, n>' closer together uhtil m+ 1 =- 11. We can chqose either to Increment
until(.> (x -' 1)) fi1crease where increase n = n + 1 m in steps of 1, or similarly decrement n in steps of 1.. But .we .can do better.
Consider the integer p = (m + n) div 2 that is halfway between m and n. ~lore
precisely, if m + 1 < 11, then ii-1 < p < n. If p .s x, ~hen. we e<in increase m to
qr as decrease :upper, where. .

upper ;= !Jntil ( > x) increase where increase n = n + 1 the value p; dually, if x < P; th'en we can decrease n to p. The result is the new -.
program
In the second solution, upper is dual to lower. The function decrease upper ' .
will be applied to the result of the .first search."The compl~te program can now floor x
be expressed as - : -searchfrom (-1, 1)
where searchfrom = fst middle cross (lower, upper)
'lower = until (.s x) double
upper = until (> x) double
middle - until done i'!'prove
done (m, n) = (m + 1 = n)
improve (m, n ) = if p s x then (p, n) else (m, p )
where p = (m + n) div 2

The function cross was defined in Section 2.4. The new program takes anum-
An attempt .has be'el} made to make this program as clear as possible.:- The ber of steps proportional to log 2 (abs x). For example, with x = 17.3, we get
names searchFrom, increase (rather than the equivalent succ), and d.ecrease
' ' '

lower ( ..:.1) = -1 and upper 1 == 32. The third search prod\lces the intermediate
I

(rather than ~red) have been chosen to b.~;ing out the contributions of the as- values
. sociated pa~is of .the definition, and the functions lower and 'upper liavc'been
as
defined to be as dual to each'other possible: ~inally,' the various subsidiary (-1, 32)- (15, 32)- (15, 23)- (15,19)- (17,19) .... (17, 18)
fun~tions hav~ q~en made local to .the main definition. The program is Sl..\.r
prisingly short, ~wing mainly to the absence of a case analysis on tll.e sign of and returns 17. With x = -17:3, we get lower ( -1) = -32 and upper 1 = 1. The
third search produces the intermectiate values
x. It is easy to see how the two cases are ti:eatect: if 0 :::; x, then the first loop
terminates at once, and the second loop does th.c real work; while if x. < o it is (-32, 1), (-32', -16), (-24, - 16), ( - 20, -16), (- 18, - 16), (-18, -17)
the other i.vay arow1d. .
The above progra'm is not very efficient, since it takes about abs steps tox and returns -18. The strategy behind thls program is called bi.IJary search.
find the answer. A better method is first to find two integers m and n such that Rather than bring two integers together in steps of 1, while maintaining a certain
,3 I 3.6 I Example: linear and binary search 85
84 ..
Numbers

relations hip between them, it is sometim es possible to cut the gap to half the the case of square roots, Newton' s method says that if y;; is 'an approxim ation
size. w ../X, then
Yrr+l = (y, + X/Yn)/2
3.6.1 Example: computm g square roots
is a better approximation. For example, taking x = 2 and Yo. = x, we have
Let us give a second example of searching. Our aim is to construc t a definition of
.
the function sqrt for computi ng the (noJmegative) square root of a nonnegative Yo - 2
number. The mathema tical specifica tion of sqrt is that ('J- (2 + 2/2) /2 - 1.5
Yi - '(l.S + 2/1.5)/2 - 1.4167
and square (sqrt x ) = x,
sqrc x 2:: 0
Y3 = (1.4 167 + 2/1.4 167) - 1.41421 57
wheneve r x o.
The specification is rather strong in that it does not make
and so on. By iterating this process we can cleterrni.rle J2 to any required degree
2::.
allm~ances for the lin:llted preCision of aritlm1etic operatio ns ori. acrual com-
of accuracy, subject r? the limitations of compute r arithmetic.
puters. For example, it requires that
Usirig the search function until introduced above, we can. implement sqrt
\vith the program
sqrc 2 = 1.4142135623 ...

be compute d exactly. As we will see in Chapters 4 and 9, it 'is quite possible .to sqrt .. Float - Float
design a function that returns an infinite lis t of digits, though the process of sqrc x = unci/ done improve x
printing this list will never terminate. The programmer can then show that sqrt where doney = abs (y x y- x) < eps
meets its specification by proVing that the list of cligits, iftOrnil'rued for long improve y - (y + X/Y)/2
enough, will approxim ate the answer to any required degree of accuracy. How-
ever,.for the purpose s of the present example we will weaken the specification
Exercise s
to require only that sqrt :: Float - Float should satisfy
3.6.1 Justif); the claim that the second program for floor x takes 2log2 (abs x)
sqrt X 2:: 0 and abs (square (Sqrl' X) - X) < epS steps.
for a suitably small number eps > 0. 3.6.2 Let p = (m + n) div 2. Sl}ow that m < p < n provided m + 1 < n. What
To Hlustrate the revised specifica tion, suppose we take eps = 0.0001 and happens if m + 1 = n?
x = 2. We require: 3.6.3 In Newton's method, the test for determini.Og whether an approxim ation
abs (square (sqrt 2) - 2) < 0.0001
y to ../X is good enough was taken to be abs (y x y - x) < eps. Another test is

and since
abs (Y, x y- x) < eps x x
1.414 1 X 1.4141 - 1.999678 8 1 Rewrite the sqtt function to use this test.
1 .4142 X 1.4142 - 1.99996 164 3.6.4. Yet another test for con vergence is to stop when two successi ve approx-
l.414J X 1.4143 = 2.000244 49 ' imations y and y' are sufficiently close:

the value sqrt 2 = 1.4142 is an acceptab le answer. abs (y - y') < eps x abs y
In order to construc t sqrt we will use Newron's method for finding the roars
of a given function. This is an iterative method that repeatedly .improve s ap- Rewrite the definition of sqrt to use this new test. Give reasons why these new
proxima tions to the answer until the required degree of accuracy is achieved. In tes ts arc likely to be superior in practice.
86 3./ Numbers .3.7 I Churcl1numbe~s 87

3.7 ..Chmch numbers ., In a similar spirit, one can ask the question: what are the natural numbers
actually(or? The answer! one might say, is for counting tllings, for cmmolling
We .end tllis chapter on numbers with an exercis~ in theoretical fancy; the ma- the number of times that something is don.e. Again, we can capture this im~
terial is not used anywhere else and can safely be omitted by those wislling to pression by defuling the natural numbers as functions:
pursue more practical programming topics. ' . '
1

We have seen that it is not necessary to asswne that numbers are built-in, zero, one, two (oc- oc) - oc- oc
because we can always introduce them through datatype declarations. Now we zero r. - id
will see that dalatypes are not necessary either: everything can be done with one f - .(
functions alone! In fact, one cati get away with functions as the sole primitive two{ - ff
rnathematical entity; once we -Understand functions, we understand everything.
Thls was part of the programme that Alonzo Church set llirnself in the 1940s and so on. .The fwKtion zero{. applies f no times to its argument, the ftmction
when he was working on the ,\calculus, the formal mathematical system that one f applies f once, and so on. Thus, Church numbers are a synonym type
underpins much of to4ay's research on functional progt:amming. too:
Let us begin, not with numbers, but \'\'ith Boo/. What are the truth values
actually for? Basically, one nlight answer, they are there to make deCisions; to type Cnum ex - (oc- oc~ - (oc- oc)
help us cboose between two alternatives. We can captui-e tllis imp~ession by
defining them as functions: . lnstea,cl of having to write down each nim1ber explicitly, we can t:nake use of the
~ successor function, defined by
. true, false .... oc-oc- .oc
l'tuexy - X
suce ., Cnum oc - Cnum ex
fa/sexy ;= y suee en r - f . en f
The function true chooses the first alternative; the fw1ction false chooses the In words, suee en f applies f first en times, and then once more.
second. Thus, Church booleans are a synonym for a certain kindof function Here is a program that turns nall.l!al numbers into Church numbers and
type: . . .. .
. '
back ~gain:
type Cboof cc - q - ex - oc church .... Inc - Cnum Int
..
The definition
. . of negation \vi.th Church booleans is church - foldn succ zero

not Cboo/ ( Cbool oc) - Cbool oc


natural .... Cnum Int'- lnt
not x - x false true natural en = cn(+l)O

Similarly, conjunction and disjuilction '-vith Church booleans are defined by The furi.ction (oldn was defined for Nat in Section 3.3. The value natural en is
computed by using en to apply the function (+ l) exactly err times to the number
and, or .... Cbool ( Cbool oc) - Cbool cx - Cbool oc 0. Note the types of church and natural. The source type of natural is required
' '
andxy - xy false to be Cnum lnt because its argument is applied to an Int - Jnt function on the
righthand side. The target type of church is chosen to be the sarr)e to ensme
orxy = x true y
that clwrcfl and natural are each other's inverse.
Ih each case, the Church boolean x selects appropriate alternatives. This func- We can also do arithmetic \.vi.th Church numbers. In fact, there is ni.ore than
q.on takes Church booleans as arguments, which explains the type signanires one way toiriiplemeiit the basic arithmetic operations, though not all of them
of nol, and, and or. can be assigned the cype Cnum oc - Cnum oc - Cnum oc.
.

.! .. ..: . ...

88 3 I Numbers 3.8 I Chapter notes 89

One legirimate definition of plus is .'


3.7.2 Consider.rh~ d~fiillt~on curow2 m n = m n. Why does this give the Church
number for nm? What is the type of arrow2?
plusl Cnum a- Cnum a- Cnum a
3.7.3 Use a computer to discover the rype of arrowl.
plus! en dn f = en f dn'{
.,
~
3.7.4 Define a Church version of Either a /3.
This defines plusl en dn to be the result of doing f firs t dn times, and then .
doing it en times more. An even briefer definition of plus is to write
3.8 Chapter notes
plus2 .. Cnum ( Cnum a ) - Cnum a - Cnum a
plus2 en - en suec A full discus.sion of cqmputer arithmetic can be found in Knuth (19Bl). Linear
and binary search are fundamental programming techniques and are covered
The function p lus2 en dn applies SLtee exactly en rimes to dn. The first argument in Morgan (1996) and Kaldewaij (1990). The properties of floors, as well as
of plus2ls a Church number that takes suee :: Cnum a - Cnum a as argument. many other useful numerical functions, are given in Graham, Knuth, and Pata
This explains the change in rype. shnik (1990). Church numerals are presented in Church (1941) and discussed
Multiplication can also be given a brief definition:
in Gordon (1994).
' .'
Cnum cc - Cnum cc -: Cnum a . ..' . .
,.~. ~
timesl ,, ~

times.l en dn = en dn
The fimc.tion 'ames.l en dn f applies dn (exactly en thnes. An alternative 'def
inition is
cimes2 Cnum (Cnum a) - Cnwn ex- Cnum(iX - et)
times2 en - en plusl .

The funcrion times2endn applies plusldn exactly en times. We can replace p/usl
'by plus2 in the definition of cimes2 ro obtain a third version of multiplication.
The rype signatures of these functions are getting complicated, and we will not ' .
attempt to justify them. In fact, they were deduced with the help of the Haskell
rype inference system. -,.,~
.,
Finally, one version of exponentiation is
~
arrowl en = en timesl .~ . \,

t..
':v~
There is a switch of arguments here: the expression arrow! m n means nrn. ...... .. .. ...

1
~ .-,: -:
'~1 ,
:'" :.
The function arrow] en dn applies timesl dn exactly cr1 times. An even briefer
;

r
definition is ,:,~

arrow2 en dn = en dn
We leave it as an exercise to explain why tllis version works.

Exercises
l
.,
'
\ '

ll
'~

3. 7.1 Write a definition of isZero :: Cnum cc - CBool ex that determines whether
irs argument is zero or not. ..:~
~
J
~
..
i
'l
;I
'!
Chapter 4

Lists .'

.
' .

' '

The datatype of lists is the workhorse of functional programming. Lists can


be. used to fetch and carry datafrom one function to another; they can be
taken apart, rearranged , and combined with other lists; lists of immbers can be
:
summed and multiplied; lists of characters can be read and printed; and so on.
The list of useful operations on lists is a long one. The purpose of thls chapter
is to introduce the more important functions on lists, giVing their names and
definitions , simple examples of how they are used, and the properties they
satisfy. We also describe the prindple of induction over lists for proving such
properlies. More extended programm ing examples in the use of lists are given
inChapter S; this material is arranged so that it can be studied in parallel with
the present chapter.

.
4.1 List notation

A finite list is denoted using square brackets and commas. For example, [ 1, 2, 3]
is a list of three numbers and ("hallo", "goodb~c"] is a list'of two strings. AUthe
elcnients of a list must have the same type. The empty list. is wr itten as [] and
a single~on list, containing just one element x, is written as [x ]. In particular,
[[]] is a singleton list, con taining the empty List as its only member.
. . If the elements of a list all have type e<, then the list itself will be assigned
the type [ e<) (pronounce d 'l~st of e<'), For example, all of the following aJ:e valid
type assignrnen ~s: . '''

[1 ,2, 3] .... [Inc]


{'h\ 'a\ '1', 'l', 'o'J .... [Char]
' [[1 , 2], (3]] .... [ [In l]]
((+ ),(X)) .." [Inc - Int - Int ]
.
' ...
f
.. - '. )
+ ......... '' , .

93
92 4 I Lists 4.1 f LiSt notatio n
+

( ==) over lists: .


' .. ' ' t :.
..
'

On .t he qther hand, [1,,"fine day"] is not 4 well-formed list because its e!ep1ents
have differenr .ryp~s. Strings, introduced in Chapter 2, are simply lists of charac- . instance (Eq <X) "". Eq [<X] where
ters writte n with' a special syntax. Thus, "hallo" is just a convenient additional [ ] == [ 1 - Tn1e
syntax for the particular list ['h', 'a', 'l', '!', 'o'). Every generi c operation on lists [] == (y : ys) - False
is therefore also applicable to snings .
(x : xs) == [ ] = False
Unlike a set, a list may contain the same value more than once. For example,
[1,1] is a list of two elements, both of which happe n to be 1, and is distin ct
. .. ., 'ex : xs) == (y: ys) - (x == y) A (xs == ys)
,
--..z...:-"' . .
from the list [1), which contains only one element. Two lists are equal if and Notice the names given co lis t vanables. By convention, we will use the letters
ZS, and
only if they contain the same values in the same order. X, y, z, and SO on,'to de~D-te ~~~hJC ntS Of listS, an~ the nameS XS, ys,
so on, to denote the lists thi!mselves. The convention can be extended~ writ
ing xss, yss, zss, and so on, to describe lists whose elements are themselves
4.1.1 Usts "s a dataty lists. Tllis convention is not enforced by Haskell, but is simply a useful aid to
. . pe
comprehension. .
A list can be constr ucted from scratch by startin g with the empty list and suc- .. It seems obvious that if one wants to test elements of [<X] for equality, then
cessively adding elements one by one. One can add elements lO the front of the , .. one needs ai1 equality te.st ori <X. But there is one case where this is not true:
list, or to the rear, or to somewhere in the middle. In the following dataty pe testing equality with the empty list. The function null, define d by
declaration, nonempty Usts are constr ucted by adding eleme nts ro the f r ont of

..
null
.... {<X] - BooI
a list:
null [ ] - True

" data Lisr <X - Nil 1 Cons <X (Lisr <X) .. - - . mill (x: xs) - False
. .
I
does not require <X to be an equality type; 's ee Exercise 4.1.3.
For anoth er view of lists, see Exercise 4.1.4. The constr uctor Cons (short for
'const ruct' - the name goes back to the programming langtfage LISP) adds an
4.1.2 Induc tion.o.ver F~ts
'. . . . ,
eleme nt to the front of a list. For example, the list [ 1, 2, 3] would be repres ented . . . '

as the following eleme nt of List lnt: Recall from Section 3.2 that, for the datarype Nat of natural numbers, structural
induction is based on tluee cases: every eleme nt of Nat is either .L, or Zero,
Cons 1 (Cons 2 (Cons 3 Nil)) or else has the form Succ n for some element n of Nat. Similarly, structural
induction on lists is also based on three cases: every list is either the undefined
In functional programming, lists are defined as elements of List <X. The syntax list ..L, the empty list [ ], or else has the form (x : xs) for some x and list xs.
[a] is used instea d of List <X, the constr uctor Nil is writte n as [ ], and the con- To show by thfit ..q,..prQpo sition P(xs) holds .for all lists xs it suffices
to
indu~t10!l...........
. . ' . . .. . ..

struct or Cons is written as an infix operator (:). Moreover, (:) associates the
~

therefore to establish three cases:


right, so
Case (..!.). That P( ..L) holds.
[1,2,3 ] = 1:(2 : (3:[]) ) = 1:2:3 :[ ) Case ({ }). That P([ ]) holds.
' Case (x: xs). That if P(xs) holds, then P(x: xs) also holds for every x.
ln other words, the special syntax on the left can be regard ed as an ahlkeviation
for the syntax on the right, which is also special but only by virtue of the fact If we prove only the secon d two cases, then we can conclude only that P(xs)
that the constr uctors are given nonsta ndard names. holds for every finite list; if we prove only the first and third cases, then we
can conclude only that P( xs) holds for every partial list. Jl' P takes the form
Like functions over other daratypcs, functions over lists can be defined by
of an equation, as all of our laws do, then proving the firstand third cases is
patter n matching. For examp_lc, the following class instance declaration defines
94 4 I Lists 4.2 1 List operations 95

sufficient to show that P(xs) holds for every infinite list. Partiallists and infinite a nonemply list, ~s easy to define with the,datatype [e<], but more complicated
lists are described in the follo~ng section. Examples of induction proofs are wit)l Liste e<. Give the definitions of head for the two types. Give a function
given tluoughout ~e.remainder of the chapter.
convert :: Liste ex - [a]
Exercises '
for converti.qg
. from one
. datatype,. to the other.
4.1.1. Give an example of an expression that contains two occurrences of the
emptY list, the first occ.urrence having type [BooiJ and the second having type
0 0
[Char]. 4.2 List operations
4.1.2 Complete
. . . the following irtstance declaration:
.
This section'introduces some of the most commonly used functions and oper
instance ( Ord c:x) => Ord [ c:x] where . ations on lists. For eaci1 function we will give the del~ition, illustrate its use, '
... . and state some of its properties. We \\'ill also appeal to structural induction
. over Lists to prove these properties .
. Recall from Chapter 2 tl~at, for the particular lype [Char], the ordering on
strings is lexicographic, The ge.neral definition of :;; 011 lists should.be lexico-
graphic too. . 4.2.1 Concatenation
0 0

4.1.3 Consider the following two definitions cif the function last that retums
0 0

Two lists caJ1.be concatenated to form one longe1; list. This function is denoted
.the last element of a nonempty list by the binary operator * (pronoLmced 'concatenate'). 1\s two simple examples,
we have
'' ,

. last
. (x:.xs) . - if nul/.xs then x else last xs
0

last' (x : xs) - if xs == [ ) then x else last' xs 0 ?[1,2,3] *


[4,5]
..
[1,2,3,4,5)
The 'differ~nce between last and last' is that they have slightly different types:
last .. [e<] - e<
? [1, 2] * [] * [l]
last' (Eq <x)' => [ <x 1 ~ cx
0

. .[l,
. . 2,1]
.. ' .

Since the definition of lasti involves an explicit equality test, its type is restricted The formal defWtion of * is
.tq lists whose elements are drawn from an equality type. Give an expression e (*) [cx]- ted ..- [a] .
such that the evaluator iesponds' cliffe'reJitly to last e and last' e. [ ] * ys I ' I ~;

' 4:t::r The. dual Vie.~v of li;ts is r.o co~stn~~t them by.~dding el~~er{ts tb the end
y~' ., .,
*
=
(x: xs) * ys = x: (xs ys)
of the lis,t: , .. .: :
+

, 0

Concatenation takes two lists, both of the same type, and produces a third Jist,
data Lisle e< = Nil I Snoc (Lis.te e<) e< , again of the same type. Hence the type assigrunent. The definition of is by *
pattern matching on the left-hand argument; the two patterns are disjoint and
Snoc, of course, is just Cons backwards. With this view of lists,.[ 1, 2, 3] woUld
cover all cases, apart from the undefined list .l. It follows by case exhaustion
be represented as .an element of Liste Int by
that' .L * ys = ..l.
snoc (Snoc <.S:noc Nil I) 2) 3 However; it is.not the case that xs * .l = L For example,

E.'<actly tlie same information is providgd by the two views, but it is organised ?[1,2,3] *
UI'Jdefined
differently. f;9r example, the function head, which returns the first element .of [1, 2, 3 [Interrupted!}
t i
!. . ' . -. ., .:.
'
I .

96 4/ Uses 4.2 I List operil!ions 97


....
The list [1, 2, 3] ..t .l is a partial list; in full form it is the list 1 : 2 : 3 : .l. .TI1e right-hand side si~plifi~s to j_ as well, establishing the case.
The evaluator can compute the first three elements, but thereafter it goes into
a nonterminating computation, so we interrupt it. case ([ ]). For the left-hand side we reason
The second equation for* is very succinct and reqUires some thought. Once
one has come to grips with the definition of* one has understood a good deal (()#ys)it-ZS
about how lists work in functional programming. Note that the number of steps {first equation for#}
required to compute xs * ys is proportio.naf to tl1e number of elements in xs.
yS#ZS
For example,
.
[1,2] * [3,4,5]
'
The right-hand side smiplifies toys * zs as well; establishing the case.
{notation) . case (x : xs). For the left-hand side we reason
(l : ( 2 : ( )) ) * (3 : (4 : (5.: [ ] ) ) ) ((x.: xs) * ys) * zs
{second equation for *) ,<''

- .{second equation for #}


1: ((2: [ ]) * (3: (4: (5: [ ])})) ., . .
'(x' : '(x'.f# ys)).
.
*.
.:: , (

zs ::-' . .o
.

"' .' ..
' '

- {second equation for#) = {second equation for #}


1 : (2 : ( [ ] * (3 : (4 : ( 5 ; [ ]).) ) ) ) x: ( (xs * ys) * zs)
ifirst equation for * l {induction hypothesis}
- . '
1: (2: (3: (4: (!i: [. ]))))
-~.\. .. ...
.. .. .
..
x : (xs * (ys * zs))
{notation) ... For the right-hand side we reason
(1,2,3,4,5]
. . ..: ."... . ,L'!;.;,N).;;~ J,~;0.1:: ~f~<i;,., ~-~' ,,: . . 'I , . , ., .

Concatenation is an associative operation with unit [ ]:


{second equation for#}
(xs * ys) * zs *
= xs (ys +r zs) x : (xs * (ys -tl- zs))
XS#() = (}#XS = XS
The n.vo sides are equal, establishing the case.
Let us now use induction over lists to prove that * is associative.
0
PrOQf. The proof is by inductio~ on xs. .. .... The reader should consider why the inductimi' in this proof is on xs rather
than on ys or zs. Note that associativity is proved for all lists, finite, partial,
Case (.l). For the lef-hand side we reason
or infinite . . Hence we can assert that is associa.tive without qualification. *
(.l * ys) +r zs The reader should com1>are the proof above with a similar proM that + is an
associative operation on the i'ype Nat of the previous chapter.
{case exhaustion}'
Let us now prove a result that is true for partial and infinite lists, but not for
.l it-ZS *
finite lists. The clainl is that xs ys = xs for all partial lists xs. The assertion
[case exhaustion) is an equation, so it also holds for all infinite lists xs.

.l Proof. The proof of the claim xs * ys =.xs is by partial induction ,on xs.
98 4 I Lists 4.2 I List operations 99

Case (.1). Immediate by case exhaustion with* For example:

Case (x : xs). We reason ? concat {[1, 2], [ ], {3, 2, 1])


.. ' .
{1,2,3,2,1)
(X: XS) * YS.
? putSt.r {concat ["We", "u", "like", "u'', "lists."])
- {second equation for *I
We like lists.
x: (xs *YS) .. A basic property of concat is that
{induction hypothesis}
X: XS concat (xss * yss) = concat xss * concat yss
. . .
D for all lists xss and yss. This property can be proved by induction on xss and is
left as an exercis!:'!.
The reader should compare this claim with a similar one in,the previous chapter
that rn + n = n for all partial elements n of Nat.
4.2.3 Reverse
To illustrate
. . that returns an infinite
the result, .consider the function {rom
list oLintegers: Anotlier basic functi9n on lists is reverse, the function that reverses the order
. .
from (Integral ex)=> ex- [ex] . of elements in. a finite list. For' e~ample:
(rorn.n - n: from
.- .
(n + 1) , . ?_reverse '~Madam, l'm Adam."
.. . ' ..
:

Evaluati()n Of {rom n.will not terminate, so ".madA m'I ,madaM-"

? {romO The definition is


{0, 1, 2, 3, 4, 5, 6, 7, {Interrupted!) reverse .... [C<] - [ex]
Now consider reverse [] - []
reverse (x: xs) reverse xs -ti [ xl
? {romO [0] *
[0, l, 2, 3,4, 5, 6, 7, (Inten'upted!) In words , to reverse
. . a list (x : xs) one
. reverses xs and then adds x to the end.
:.. As a program, the above definition is not very efficient on a list of length n it
- Both evaluations, if continued for long enough, '1-\>ill produce only the.elements
oLt~.e ~te li'st [O; l, ... ], which is -exactly wba.r tl)e,"result predicts: _ __
to
'will need a number ofreduction steps proportional n2 to deliver the reversed
' ' ' : list.: The first element willbeappended to the end of.a list of'length (n-1),
whlch will take about ( n - 1) steps, the second element will be appended to a
4.2.2 Concat list ofiength (n- 2), taking (n - .2) st_eps, and so on. The total time is therefore
Concatenation performs much the same function for lists as the union operator about
.
u does {or sets. A companion function is coricat, which concatenates a list of
(n - 1) + (n- 2) + 1 = n(n -1)/2 steps
lists into one long list This function, which roughly corresponds-to the big-
. ' .
union operator U for sets of sets, i~ defined by . _:
' ,' ' '

A more pre~ise analysis is given in Chapter 7., and a more efficie.ilt progrrun for
concat [[C<J] - [C<) ' . reverse is given in Section 4.5.
... Let us.now prove by incluctlon that
concat [] - []
co neat (xs : xss) - xs I+ concat xss reverse (reverse xs) = xs
'~!ci
'
100 I 4 I Usrs 4.2 I Ust operations 101
'
. .
for all finite lists xs. The proof is instructiv~ because it requiTes an auxiliary for: all finite lists ys. = reverse xs, and making use
By taking the special case ys
res.ult. Rather than give the auxiliary result first, we will start.the indUction of the fact that reverse xs is a finite list if xs Is, we can complete the proof of
proof and see what is needed ro complete it. rhe main result.
-
Proof. The proof is by induction on xs. To prove rhe auxiliary r esult we need a second induction arl,'lunent. Here is the
induction step:
Case ([ )). For the left-hand side we reason
I '
.Case
.
(y : ys). For the left-hand side we .reason.
..
reverse (reverse [ ]) . .
- {first equation for reverse}
'
1:everse ((y : ys)" * [x] )
= [definition of * }
reverse [] .. reverse (y: (ys * [x]))
{firs~ e9uation for reverse)
' . {second equation
.' ,,.,for reverse}
[l - ~ ...
; . ,..:.,. <. ..reverse (ys -t+~(x.]) fl. [y) ,.
' . " ' I '

...~ ~ :' I~<. ,' :;., . ~.;,~-/' :.).: . ..


The result is the i:'ight-hand side.
., ~ . 'i'' . .... :>;., # : , ' '

- . !induc.~ion.hypothesisJ ..
.. .. . _. ~ ,, ...
Case (x: xs). For the left-hand side ~ve reason (x: reverseys) -If [y] ..
. .,
{definition of -it l
reverse (reverse (x : xs))
' .... -.
.~ ...:.
=

x : (reverse ys * [y] ).
- {secpnd equation for reverse}
(reverse xs * [ x]) = {second equation for re)lerse}
re~erse
x : reverse (y : ys)
There is nothfug more we can do to the left-hand side, so we n.irn to. the tight-
hand side: . . . .;o, ... The result is the t:fgl-it-hm1cl'sidc, establishing the case and rhe p~oof.
,.
X: XS 0
.... {induction hypothesis}
Since similar situations arise in many induction proofs, it is worth reit~rating
x :.. re~erse (reverse xs) how the proof of the main result was achiev.ed. First we simplified__borh sides
The two sides have sim1_>lified ro two different expressions. We are left with the of the equation in the inductive case, arriving at two different elqlressions. To
task of showing that pro've that these two expressions were equal, we needed to resort to a second
induction proof. However , before doing SO, it was necessary to generalise the
auxiliary result to som~tlling more manageable. One. might 'expect that this
reverse (reverse xs * [x]) "' x : reverse (reverse xs) would make tl1e proof harder, but the reverse is the case. The induction hypo
thesis of rhe generalised equarion, being stronger, can carry more we~ght from
for all finite lists xs. Trying to prove this result directly by induction does not one side of'the equation to the other.
work, as the reader may verify. Ins read, we have ro generalise the equation to
.. .
read

reverse (ys * (x)) - x : reverse ys


102 4 I Lists 4:2 1 List operations 103

.4.2.4 Lengtl1 ......... H~weiter, the analogous deFinition of inif, namely


. ..
. TI1e.length of a list .is the number-of elements it CO.QJains: -- iniC :: [X]- [X)
leng01 [X] - Int init = reverse . tail . reverse
lengtf1 [ ) - 0
defines init xs = l. for all partial and infinite lists xs (see Exercise 4.2.6). A
length (x : xs) ~ 1 + length xs superior defulition of these two ftmctions is
The na~e of the lis~ -ele~ents is irrelevant when computing the length,~f a last (x : xs} - if null xs then x else last xs
list, whence the type ~ssignme~1t. For example,
~ +,' ... init (X: xs) = if nullxs then []else x: initxs
7 length [undefined, undefined]
2 With this definition, in it :-.:s = xs for all infinite lists xs.
Since [x] is an abbreviation for X : [ ], and can be used as a pattern on the
Hm.Vever, not every list has a well-defined length. In particular, the partial lists left of definitions, one might be tempted to write the defiriirtons of last and i11it
l., x : l., x : y : l., and so on, have an undefined length. Orlly finite lists have in the form
well-defined lengths. The list [l., l.] is a finite list, JJOt a partial list because it
last [x] = X
is th.~ list l. : l. : [ ), w!lich ends in [] not l.: The computet cmmot produce the
elements,
last (x: xs) - last xs
- but it can produce the length . of the list: .
Like contat, the function length satisfies a d~stribution ptoperty:
.
inic [x) - X
'' . length (xs * ys) = length xs + length ys. init (x: xs), - x: initxs
' _l

the proof is left as an exercise. However, there is a serious danger of confusion with these.particular defini-
. ' tions. The patterns [x] and (x: xs) are nor disjo.int because the secondincludt:s
the' first as a special case. Although ~he definitions me valid in many languages,
4.2.5 Head and tail, iitit and_ last inciucling Haskell, they depend oil an understanding that patterns are matched
The function head selects the first element of a nonempty list, and tail selects 'top to' bottom', that is, from the first equation downwards. If we had reversed
~e rest: the 'orde.r of the equations, writing, say;

head :: -_[oi] - X last! (x ; xs) = last' xs


.' '
..
. ~
..
.
head (x: xs) = ,. X ' .
., last' [x) = X
.. . . .. . . , ..
:~
.. . ....
: .- tail
+ :, . \ _ _: - ..

r<>:'J - rXf then-the defulition of last' would sin1ply be incorrect: In fact, 1ast' xs = 'l. for
. :z: .
tail (x: xs) - xs ,. xs.
ail it is not good practice to w:i-ite definitions that depend critically. on the
order-in wllich we put the equations.
These. me constant-time. operations~ since they delive'r .their results ill one re The difficulties cm1 be resolved with yet a third definition:
duction step. .
The companion functio~s. last and . init, which select the last element of last [x) - x
a nonempty list and
\Vhat remains after the last element has been remo~ed, last (x: y: ys) - las! (y: ys)
cannot be iinplementecl so efficiently. ori'eshort definition of last is
The. first pattern [x] matches only singleton lists, and the pattern x : y : ys
last :: [ex]- X matches only lists that have at least two el~ments. Hence the two pattems
last = head reverse :.. . cover disjoint cases and everything in the garden is fine.
i
104 4 I Uses 4.2 I List opera tions . lOS
l
4.2.6 Take and drop
. ' .-
matching with the second' ~quatton gives take' 0 .L = l.. .
The definition of take' is less satisfactory than that of take because the order
The flll1ctions take. and drop each take a nonnegative integer n and a .list xs
in wruch the equations ai:e written is significant. Suppose take" is defined by
as arguments. The value rake n xs consists of ~he first n elements of xs, and
switching the first two equatio ns for take':
drop n xs is what remains. .For example,
take" 0 (x: xs) - [)
? take 3 ''functional"
take" n [] - []
"fun"
take" (n + 1) (x : xs) - x : take" nxs
7 take 3 [1, 2]
We have take" il] ,;, .L beca~se of the numeric pattern ih the first equation.
[ 1, 2]
*
Hence take" take'. But also take" "= take becal.lse take" 0 .L = l..
The definitions are The functions take and 'drop satisfy a nwnber of useful laws, including the
basic relationship
take ..
.. Tnt - [ lX-] - [ iX]
takeOxs - [] take n Xs * drop n xs ,;, xs
take(n+ l )[ ] - [] for all (finite) natural numbers nand all iists xs. The proof is.instructive because
take (n +l) (x: xs) = x : taken xs it uses a combination of induction on the natural numbers and case analysis.
. .
drop .... Tnt - [lX] - [lX) Proof. The proof is an induction on n >vith a case analysis on xs.
drppOxs - xs w ' ~ .. - ) :-.. ..
drop (n..+ .n.[.) = (] ,J- ,
case (0, xs).. For the. left-hand
. .. . . side
. . ...we
.. .reason
drop ( n + 1) (x : xs) - drop nxs .
take 0 xs * drop 0 xs
.

These definitions use a <;ombination of pattern matching with natural numbers = {first equations for take and drop}
and lists. Note that the patterns are disjoint and cover all possible cases: every . . '
natural number is either zero (first equa(ion).or the successor a natural num of
;: ber; in the latter case we distinguish between an empty list (second equation) {rnst equation for -ttl
...' and a nonempty list (third equation). . xs '

Since there are two argun1ents on which pattern matching is performed, it is


important ro ~ow which argument gets matched .fu:st. As we have said, pattern
Case (n + 1, .L). For the left~hand _side \ve reason .
matching is pe.iformed on the clauses of a definition in Older from fu:~t ro last. .

Within each clause, panern matching is performed from left to right. Hence in take (n + l ). .L :it drop (n +1) .L
take and drop the.nuineric pattern is matched first. In particular, rakeO .L = [ ] = {case exhaustion with take and drop}
and take l. [ ] = .L.
We could have written the definition of cake in the form l.-ttl.
{CaSe exhauStiOn.With -tt}
take' n [ 1 - [] .. ""
.
.. take' 0 (x: xs) - [] ..

take' (n +1) (x: xs) == x : cake' nxs


Case (n + 1, [ ]).. For the left-hand side we reason.
However, the definition of take' is subtly different from that of rake. This time, ' '

pattern matching with the first equation gives take' .L [ ] = [ J. an.d pattern take <n + 1) ( 1* drop <n + n [I

...
LOG 4 I Lisrs 4.2 I List operations 107

= {definition of take and drop} specified by


[]-ttlJ splitAt " I ht - (!X] - (( e<], ( IX])
= {definition of *I spliiAt n xs - (taken xs, drop n x.s)
[] However, spliiAt is implemented by the equations

splitAt 0 xs = ([ ], x.s)
Case (n + 1, x : xs). For the left-hand side we reason
splitAt (n + 1) [] '= ( [ ), ( ] )

take (n + 1) (x: x.s) -1+: drop (n + 1) (x: xs) splitAt (n + 1) (x: xs) - (x: ys, zs)

= (dc.t'initionof take'and drop} where (ys, zs) = splitAt n xs


(x: taken xs) * drop n xs It is easy to derive the second version, and we leave details as an exercise.. As
we will see in Chapter 7, the alternative program is more efficient in the use of
= {definHion of t!}
space because the argument list is tr aversed only once. The dilference in time
x: (take n xs *drop n A's) between the two versions is marginal.
= {induction hypothesis}
x : xs 4.2.7 List index

A list xs can be indexed by a natural number n to f'ind the element appearing


0
at position n. This operati(m is denoted by x.s!! n. For example, . .-.
The proof is straightforward-but 'tliere are two poi.J{ts of interest. .First, ..the . ?[1,2,3,4)!!2
proof can be vie_wed as an induction argument on n with a case analysis on 3
x,s. The various cases match thepatterns in rpe defini~iqn of take and drop;
indeed, that is precise~y why the patterns wer e chosen in the way they were. ?. [1,2, 3,4]!!0
The proof of the <iddit1onal case ( n + 1, 1..) is necessary if we want to assert th at 1
the equation holds without restriction on xs. .
The second point w note is th at the equation fails.to hold in the case r:1 = 1.. Indexing begins at 0, which for most purposes is a better choice,than beginning
becau&e at l.
.. The operator (!!) is defined by
take l.. x.s* drop 1.. xs -=. 1.. .* 1.. .= 1.., .QOt x.S
. . (!!) .... (!X] - fnt -' IX
In a similar fashion, c>ne can prove a number of additional laws about take and (x : xs) !! 0 X
drop, including (x: xs)!! (n + 1) - xs !! n
take m taken - take (m min n) Indexing a list corresponds to the mathematical device of using subscripts and
. drop m drop n - drop (m + n) so seems a very naturai and useful operation. However, indexing is a fairly
take m d~op n = drop n take (m + n) ex-Pensive operation in functional progrruruning, since xs !! n takes a number of
redu ction steps proportional to n, and should be avoided whenever there is a
The expression ( m min n) denotes the Sti:~aller of m and n. suitable alternative. On the o'ther hand, there are situations when indexing a list
. In a number of situations the value (taken xs, drop n x..~) Is required, and is appropriate and Section 5.1, which d~J?ends. Ol~ly on the material presented
Haskell provides. a standard
. . computing it. .The function splitAt
. for
function . is so far, contains one such example.
.,
..
108 4 I Lists 4.3 I Map and (ilter 109
, .
Exerdses 42.12 Prove that

4.2.1 Mlich of the following equations are tr ue for all xs and ~hich are false? (xs * ys) !! k - if k < n then xs.!! k else ys !! {k - n)
where n = length xs
[] : xs - xs
[] : xs - (( j, xs] 4.2.13 Since concatenation seems such a basic operation on lists, we can try to
xs: [] - xs . construct a datatype that captures concatenation as primitive. For example,
xs: [] = [xs] data .CatListrx . = Nil I Wrap IX I Cat.( CatUsc rx) ( CatList rx)
xs:xs = [xs,xs]
The intention is that Nil represents [],' and Wrap x represents [x ], and Cat xs ys
4.2.2 Which of the following equations are true for all xs and which are false? * *
represents xs ys. However, since is an _associative operation, the expres
sions
([ )] * xs = xs
[())*XS = [xs] Car xs (Cat ys zs) and Cat (Cat xs ys) zs
[[J]*XS ([],xs]
"' should be regarded as equal. Define appropriate instances of Eq and Ord .for
[(]] * (xs] - [[ ],xs]
- . . . CatList. '
[Xs) *[] = [xs]
(xs] * [xs] = [xs,xs)
4.3 Map and fllter
..
4.2.3 Prove by induction that xs * [] =; xs for all lists xs.
. . ,, . . ' . r . w . _ Twb useful 'filllctions on lists are map and filter. The filllction map applies a
4.2.4 Prove that concat (xss * yss) = concat xss * concat yss.
;. ; . ~ .

function to each element of a list. for example,


4.2.5 Prove that length (xs * ys) = length xs + length ys.
? map square [9, 3]
4.2.6 Prove that re verse xs = .1 for all infinite lists xs, and show that in it xs = .1 [81, 9]
for all infinite lists xs, where init = reverse tail reverse.
? map(< 3) [1, 2,3]
4.2.7 Consider again the assertion revers~ (reversexs) = xs. Since :
j' ' . .' [:true, True, False]
reverse (reverse .l) = reverse L = ..L ..
? map nextLetter "HAL"
it seems that the asserUon is proved for allli.!ltS, not just the f~te one~:,.~But "lBM"
one cannot reverse an infinite list (see the previous exercise), so what has gqne
wrong? The defiriition is

4.2.8 Using pattern matching with (:), define a funclion rev? that reverses all map .. (IX - Jn - [IX] - [p]
lists of length 2, but leaves others unchanged. Ensmc that the patterns are map f[] = []
exhaustive and disjoint. map f (x: xs) = f' x : map f xs
. .
4.2.9 Give an informal characterisatio~ of those finite lists 'xs and ys which As another ex<imple, suppose we want to computt! the sum of the squares of
. " *
satisfy xs ys = ys xs. * ' the integers from lup to i OO. The functions sum and upto can be defined by
4.2.10 What is the value of [head xs] *tail xs when xs = [ ]? sum .. (Num IX) ~ [IX] - IX
4.2.11 Is it the case that (drop m xs) !! n = xs!! (m + n) for all finite lists xs a_ng sum [ ] - 0
all natuial numbers m an'ct n? . . .
sum (x: xs) - x + sumxs
110 4 I Lists 4.3 I Map and fil!er 111

upto (Integral LX) ~ ex - ex - [ex]' The first equation holds only if f is a strict function, but .the other three hold
upto m n - if m).. n th~n [)else m : upto (m + 1) n for arbitrary f . If we apply both sides of the first equation to [],then

Now 'we have r (head []) = head (map f [ J) = head []


? sum (map square.(upto 1100)) Hence, since head [ ] = l., we require { to be strict.
.338700 Each equation has a simple interpretation. For example, the last equation
says tha,t one can either concatenate a list of lists and apply ( to each element
. The us_e of map isheatly illustrated by the previous example: the English phrase of thc.result, or apply map f to every component list and then conc~tenate the
'the sum of the squar.es of the integers from 1 up to 100' can be translated result.
virtually word for word into a simple formal expression. *
Since con cat (xs, ys] = xs ys, a special case of t.he last result is that
The functio.n upto, and the related function (rom, crop up frequently in
computations, and Haskell provided a special and more convenient syntax. The map'{ (xs -1+ ys) = map f xs *map f ys
forms [m .. n] and [m .. ] are defined by
*
for all lists xs and ys. In words map f distributes ov.er for all (. In fact, the
[m ., n) - upto m n special case is .needed as an au;xiliary result in the proof by induction of the
[m .. ] - (romm more general one.
The common theme behind each of these equations, and m.any others like
The special forms can be used with enumerapon typ~s other than Int or Integer, thein; concerns the types of the functions involved:
though we will not do so in this book.
. There are a ni.unber of u:;:e_fu.l algebraic iclenti.~ies concerning m(!p. Two basic head .... {(XJ - ()(
facts are that ' tail .... [iXi -r~J
reverse .... [ex] - [(X)
map id = id .
concar .... [[ex]]- (ex]
. map ({. g) "" map f . nwp.g
The firsteqwltion says tha~ applying the identity function 1:0 every elemeJlt of The point about these ftmctions is that they do not depend in any way on the
a list leaves the list und1anged. The two occurrences of id in the fust equation nature of thelist elements; they are simply combinators that stnimc, rearrange,
. have different types; on the left id :: ex - lX, and on the right id :: [ex] _; [ex]. or .extract elem~nts from lists, That is why they have polymorphic types. It
foll~?ws that we can .either 'rename' the list elements (via map f) and then do
The second equation Says that applying g to every eleinent of a list, and then
applying f to each element' ofJ he resu~t, give~ the same result as applying f . g the operation, or do tl,le operation and then rename the elements. this is exactly
what each equation above says. In categ01y theory, such equations are called
to [he original list. Read from dght.to lCft, 'the equation says that two t~aversals
of a, list can be r~placed by one, witJl a correspondlng,galh in efficjency. The naturality conditions,.. ~d we
will use this ternunology in calculation hints . .
'
. proofs of both laws use induction over lists and are left as exercises. In category
theory, functions like map that satisfy the two basic properties above are .called 4.3.1 Filter
fWictor9, and we will use the word fUnctor when referring to the two properties
The second function, filter, takes a boolean function p and a list xs and returns
in calculations.
that sublist of xs whose elements satisfy p . For example,
Here is a list of additional laws, all of which have a common theme:
.
'Ifill>' ) [12 , ::., -3"]
, ' , 4-
f head - head. 'map r et even ."
[~. 4, 32]
map { tail - tail map f
map r . reverse - reverse . map r ... '., ' ? (sum map square filler even) [1 .. 10)
map f concat - concat. map (map n 220
112 .4 I Lists 1 Map and filrer 113
:

The last example asks for the sum of the squares of the even integers in the {generator rule}
range 1 to 10. concat (map( [1 .. 5]) where f x = [x x xI odd x)
The definition of filter is
{guard rule}
'
filter (a - Bool) - [a] - [a]
I
concat (map f [1 .. 5]) where f x = if odd x then [x x x ] else [ ]
!

I
filter p [] = [) .
filter p (x : xs) = if p x then x : filter p xs else filter p xs {map)
,, concac [[1 ], [ ], [9], [], [25]]
,i Like map, there are a n umber of useful identities concerning filter, fncluding
I
'i the basic fac t that {concat)
[ 1,9,25 ]
filter p filter q == filter (p and q )
Here are some more examples:
where (p and q ) x "' p x " q x. This equation is valid only if p and q are strict
fu nctions. Another law is ? [(a, b) I a- [1:. 3], b - {1.. 2])
[(1,1), (l, 2 ), (2, 1), (2)), (3,1), (3, 2) ]
filter p concat "' comat map (filter p)
?{(a,b) lb -- [ 1.. 2], a - [1.. 3]]
which is valid for any p.
[(1, 1) , (2, 1), (3, i) , (1, 2), (2, 2) , (3, 2) ]

4 .3.2 Li~ t comprehensions Later generators can depend on the variables introduced by earlier ones:
. ~ " "'-' ~ "
.,
,.
Haskell, in common with some other functional languages, provides an alternat ? [(i,J) I i - [1..4]. J- [i + 1..4]]
ive notation, called a list comprebension, for describing computations involving [ (1, 2), (1, 3), (l , 4), (2, 3), (2, 4), (3, 4))
map and filter. Here is an example:
We can freely in tersperse generators with guards:
?[xxxlx-[1..5], oddx]
[1,9,25) ?[(i:j) li-[1 .. 4], eveni,j- [i+ 1 .. 4), oddj]
.
[(2,3)]
This reads: the list of squares of odd numbers in the r ange 1 to 5.
Formally, a list comprehension takes the form[e I Q] where e is anexpres- Here is an example where the generator takes the form (x, y) - xs. First, define
sion and Q is a qualifier. A qualifier is a possibly empty sequenc~ of generators pairs = [(i,j) I i - [1 .. 2], j - [1 .. 3])
and guards, separated by commas. A generator takes the form x - xs, where x
is a variable or tuple of variables, and xs is a list-valued expression. A guard is nien we have
a boolean-valued expression. The qualifier Q may be empty, in which case we
j ust write [e). Otherwise we define ? ( i + j I (i,j) - pa irs ]
[2, 3, 4, 3, 4, 5]
[e I x- xs, Q] = concat (map f xs) where f x ;o [e I Q]
As a more iilteresting example, here is a program to list all pythagorean triads
[e l p, Q] = ifp thcn [e i Q]else[] 2 2 2
in a given range. These are triples of numbers (x, y , z) such that x f y = z .
.,
The first equation is called the generator 111le, and the second is called the guard We define triads by
' ' '
m l e. Using these rules, we can calculate
triads .. Inc - [(Int,Jnt, Jnt)]
[x x x I x - {1 .. 5], odd x ] triads n - [ (x,y, z) 1 (x, y, z) - triples n, pyt!J (x, y, z))
tl4 ' 4 I Lists 1 Map and filter 115

triples lnt - [ (lnt, Int, Int)]


triples n - [(x,y,z) I x- [1 .. n]~ y- ["1 .. n], z- [1 .. n]J
~.3.1 Evaluate map (map square) [[1, 2). [3,4, 5]].
pyth .. (Inc ,Inc ,lnt) - Boo/ 4.3.2 What is the value of map f .L? What is the value of map .L [ )?
pyth (x, y, z) = (x x x + y x y = z x z) 4.3.3 What is the type of map map?

For (!xample: 4.3.4 Prove that inap f (xs * ys) = map f xs * map f ys. IIence prove that
map f concat = concat map (map f).
? triads 5 4.3_'5 The function inits computes the list of initial segments of a list; its type
[(3,4,5),(4,3, 5)) is inits ::[ex]- [[ex]]. What is the appropriate naturality condition for lnits?
Since triads generates essentially the same triad in two different wa}IS, the fol- 4.3.6 The function filter can be defined in terms of concat and map:
lowing definition of lrip/es is a better one:
filter p = concat map box
triples n = [(x,y,z) I x- p .. n], y- [x .. n}. z- [y : n]] where box x = ...
. '.
In the new definition, the value of y is restricted to the range x < y :;; n, and Give the definition of box.
the value of z to the range y :;; z :;; n. Since .z must be at least as big as the 4.3.7. The .useful functions take While and drop While are similar to . ta~e and
larger of x andy, all triads will still be found, but no triad will be found more drop except that they .both mke a boolean function as first argument \nstcad of
than once. For example, . a n_atural number. In this respect, they are both similar to niter too.~The value
- .. take While p xs is the longest initial segment of xs all of whose elements satisfy
? triads 5 .. . p. For example
[(3, 4, 5)]
takeW11iie ~ven [2, 4, 6, 1, S, 61 = [2, 4, 6]
4.3.3 Reasoning about list comprehensio ns
The value dropWhi/e p xs gives what remains; for example,
List comprehensions provide an a\tractive alternative to a combinatorial style
; dropW11ileeven{2,4,6, 1, 5, 6) = [1,5,6]
based on map, filter, anci concat. 'J.1teb~ are also a number of derived rules for
reasoning about list comprehensions, including the fol19wing: Give recursive def'itions of takeW11ile and drop While.
. .
. 4.3.8 Under what conditions on xs and ys does the following equation hold?
.. .{f xI. x- xs] - map f ?IS :.
. [x I ?' - xs, p x] = filter p xs . .. = {xI y- ys, xsr
-- ... [e I Q,P] .. [x l.x- XS, y- ysJ .,
X- . ...
= concac [(e IP] j Qj :

- .:
[e IQ, x - [dIP]] = ie(x := .ciJ I Q, Pl 4.3.9 Define a function_pairs so at pairs n is a list of all distinct pairs of
integerS 1' $; X, y :;; 11.
In the last equation c[x := dJ denotes the expression that results when occur- 4.3.10 Write a program to find all essentially distinct quadruples (a, b, c, d) in
rences of x in_the expression ~are replaced by the expression d; The last two the range 0 < a! b, c, d:;; 11 such that a-? + b2 = c? + d 2. .
rules can be proved by inducti.on on the'structure of the qualifier Q. .
4.3.ll Convert the following list
'.... comprehensio ns
On the other hand, the combinatory stylc has some advantages too. 6ite is . . ' .. to combinatory
. style:
that the algebraic properties of map and . filter 'are easier to state and . use. tq I x- {1.. nJ, odd x, y - [1 .. n]]
[ (x, y)
The fair conclusion is that the choice as to whether to use list comprehensio ns [(x,y) I x- (1.. n], y- (1 .. n], odd x]
or a combinatory style is mostly a matter of.personal preference. The same is
tT.U~ about a point-wise style ver.sus a point-free styie. . .. Are they equal? Compare the costs of evaluating the two expressions.
' -
. . .. ., '

116 '
4 I Usrs 117
.-
a of boofeans and returnsTrueif all the elements
. :
.. . . ..
.... ft.mction.an(i'takes llst.
' ''
4.4 Zip
are True, and False otherwise:
The function zip t~kes two list!; and returns a list of pairs of corresponding
elements. For example, . and .. [Boof] - Bool
and [] - True
? zip [O .. 4) "hallo" and (x : xs) - x A and xs
[(0, 'h'), (1, 'a'), (2, n. (3, 'l'), (4, 'o'))
The expression tip xs (tail xs) returns the list of adjacent pairs of elements in
( ? zip [0, 1) "hallo" xs. in .particular,
!; ' . ' .. , :' ~... ...
' [(0, 'h'), (1, 'a')] ,. ,' .... ' ~.-:!' ' ,,- :. .:

zip [ ](tail (]) - zip [ ] ..L = (]


As the second example shows, if the two lists do not have the same'length, then .zip [x](rail [x]) = zip [x][] - []
the length of the zipped list is the shorter of the lengths cif the twoarguments.
The'fuU definition of zipis Note also that leq = uncurry (:::;).
. As a third example, consider ~he problem of building a function position
.... [01]- [/3)- ((tx,p)]
zip 'with tb~:prop~J~Y ,rhp,r.,vosjtjpnx xsde~ote;'; the position ofthe first occurrence
zip ( J ys - .'
. of
. X in .XS (COtllltiDg from. _()); and -'1 if X does not.appear in Xs. ThUS pOSition
()
zip (x : xs) ( ] - (] - has type
zip (x : xs) (y: ys) - (x, y) :zip (X.S, ys)
position :: (Eq .~) ;;> C< - [a) - Int
The pattern matching in tllis definition parallels that of..fak-6m~d dr.op. Matching
. .
on the left-hand argument is performed first, so zip ..L [) = 1.. and zip ( ].!:. = [ ]. . . This is an instructive problem be'caus~ the best way to tackle it is to soive a more
;
The function zip has many uses. For example, the scalar product of two general problem first, namely to compute all positions at which x appears in .
I .
t .', : vectors xand y is defined by 2:?a1 x; x Yi- The function sp~ for computing scalar xs. The definition, which uses a list comprehension, is
' ' ..
products, dm be dd'ined by
. PQSifi.O,~. ;,"':;.:::;~. :: ,. ,_(E,'fl..lX).,.~~,cx,, ~,J.ql - {Int L .
sp .. (Num lX) ;;> [lX) ... (lX] - lX . positions xxs . '= [i I (i,y)...: zip [0 .. ] xs, x == y]
. . ..
sp xs ys sum (map times (zip xs ys))
~

;. -
I~ ~ The expression zip (O .. ] xs pairs each element of xs with its position in xs.
'
where times (x,y) = x x y Although (0 .. ] is an infinite list, zip [O .. ] xs willrerurn a finite list whenever
The function times is tlie uncurried version of x; in ri~'r:~-times = unc~rry ('X). _xs is.a finite list. We can now define position by
. ' ;. - - - . .
As a second exampte, suppose we want to define_a-funttion nondec for
,..
. . . position X X$ .. ;= . head (positions x XS +H =:-1]} -~ . '
determining whether a sequence [Xo, .. . , Xn-1] Is nondecreasing. Thus, we want
to determine whether Xk !> )hl for all kin.the range 0";;
k ~ n- 2.' Tlietype of It turns our that the simplicity of this definition is. adrteved at no increase in
nondec is the cost of evaluation. In order to calculate the head of alist, it is not netessaxy
to determine the value of every element of the list.
nondec :: (Ord a) ;;> [lX] - Bool .
These examples illustrate that combinations of map, filter, and zip can be
It is easy to give a direct recursive definition of nondec, bur the following def- put to a variety of uses. In order to ma~e the definitions shorter, we can intro-
inition also works: duce the function zip~Vieh, defined by

nondec xs = and (map leq ( zip xs (tail xs))) . ~ zipWil'h .. (e<- /3.- ;y)- ([lXj - [#]- [;y])
where /eq (x, y) = (x !> y) . With f
... .zip xs ys - map (tmnmy f) (zip xs ys)
. 118 4./ 119
:
For example, n,,:,lu lists xys of well-defined pairs (see E-xercise 4.4.1 for the l,'eason for the
estrlCtion to well-defined pairs).
- sum (zipW~th (X) XS}'S)
Since zip and unzip have polymorphic types, we might expect that they sat
SPXS}'S
nondec xs - and (zipWiih (.s) xs (tail xs))
appropriate naturality conditions of the kind described in the previous
For greater brevity we can introduce non curried versions of zip and zipWith: For instance, to rename elements of the target type of unzip we need
functions, a [unction map f to rename the fil'st component, and a fwlc-
zipp ([ex], (13])- [(ex,/3)] map g to rename the second. The function that does both renamlngs is
zipp = uncuny zip .,.,_,.(map{, map g)1 where cross is given by

' . zippWilh (ex- {3 - y) - ((ex]. [.8]) - (y]


cross({, g) = pair (f {st, g snd)

zippWith { _ = . map (l,lncuny f) zipp This ftmction was also .introcl.uced in Sect\on 2-4. To rename elem~nts of the
' .
source type of unzip we need to map with a sii1gle function, and it is not h<ird
For example, with spp denoting the uncurried ~ersion of sp, we have . to see that the function map(cross ({,g)) does the job. Hence we should expect
' .
spp - sum zippWith (x) that
. '

.. ' nondec = at'd zibtMiih (:5) pair (id, tail) I

....' cross (map{, map g) unzip = urizip map (cross({, g))


The new
'
tlefinitio~of. nondec
. uses the function Indeed, this equation does hold. The proof is left as Exercise 4.4.3. The dual
.result
pa{r ({,g) X = ({X, g X)
.... .. ma.p (cross((,
defined in Section 2.4. It~ be seen from .the ne>v defuuti~ns that a point-free
zipp q:asHmap(,. map g). . =
. . g)) zipp
'
. .' . . ' .

, '
-stY,le of definiti?n.is possible only if some' functions are given ~n noncurried also holds.
form. Haskell, in coltlplon with 1v~iranda and some other functionallal!guages, A more extended programming exercise in the use of zip is given in Sec-
defines all binar}r operators as curried functions, and also zip a's a curried ftmc- tion 5.2. This ex~rdse also uses material frOril the. follo'.vi.ng section. .
tion; consequently, the conversion to noncurried forms has to be made explicit.
Exercises
'. 4.4.1 What is unzip [ .l]? U~~~~g die
. [act that (.l, .l) *' .l, consuuct a llst x.ys
4.4.1 Vnzip '

such that zipp (unzipxys) * xys .


. Tp.e functio.n unzip takes a list of pairs art.d unzips it into two lists: 4.4.2 Does the converse equation unzip zipp = id hold?
unzip' :: . [ (ex, lnl - ((ex]', (13]) 4A.3 Provided certain other laws are assumed, the eq\,lation
- ynzip . pair (map {st, map snd) . ct:oss (map{, map g) . unzip = unzip map (cro;s (f, g))
For example,
~ ; ,. ,I ' ' '

. '-; . can be proved by simple calculation with functions. The necessary additional
? unzip [(1, True), (2, True) , (3, False)] laws are '..
([1, 2, 3]. [True, Ji'ue, False))
.,
map (f g) - m~pf mapg
cross({, g) pair (h, k) - pair (( h, g k)
Thefunctions zipp (the noncurried version of zip) and unzip are related. by the
equation pair ((,g) h - pair (f h, g h)
..: {st cross((, g) - f {st
zipp (unzip xys) = x.ys ,' .. ': snd cross (f,g) - g snd
.
.rr:l'
:r.
...,
.,.
'
'

::.
.

:!
''
"' 120 4 I Lists 5 I The fold functions 121
.; ...
.-. ' . '.

Usc the~e laws, together with the definition of unzip , to prove the required . reverse :: [ex]- [ex]
result reverse = folclr snoc ( )
where snoc x xs = xs * (x]
.
4.5 The fold functions ..
length :: [ex] - Int
. .
We have seen in the case of the datatffie Nat that many_re<;:ursive ~efini tions length = foldr oneplus 0
can be expressed very succinctly using a suitable fold operator. Exactly the where oneplus x n = l +n
same is true of lists. Consider the following
. .-. definition
. of.a function h: .
sum .. Num ex ;) [ex] - ex
h [) - e sum - foldr (+) 0 .
h (X : XS) - X Ill h XS

The function h works by taking a list, replacing [ 1by e and (:) by ID, and eval- and .. . [Boo~]~ Boo/
uating the result. For example, 11 converts the list and = foldr (A) True

Xt : (X2: ~X3 : .(N,j: ( ])))


. map :: . (ex - {3) - [ex] - (/3]
n []
'

map{ - {oldr (cons .


to the value
where cons x xs = x : xs
'' . ' .. ..
unzip .. [ {ex, ,8)) - ( [ex), (/3])
'' . Since (:) associates to the right, there is no need to pur in parentheses in the unzip = foldr conss ([ ], [])
first expression. However, we do have to put in parentheses in the second where conss (x, y) (xs, ys) = (x: xs, y: ys)
... expression because we do not assume that Ill associates ro the right.
The pattern of definition given by h is captured in a function {oldr (pro- In some of i:li~se 'definitions the operator.e that replaces (:) is ass~ctative, and
nounced 'fold right') defined as follows: the constant c that replaces [ ] is the unit of ED. For example, ( * [ ]), (+, 0),
,.:. . . . . ..:.. --
(A, True), and so on. In other definition s, Ill is not associative; indeed, e may nor
{oldr .. (ex-13-tn - {3 -[ exJ-13 even have a type appropriate for an associative operator, namely ex - ex - ex.
..
foldr f e [ ] = e - Not every function on lists can be defined as an instance of {oldr: For ex-
{oldr f e (x: xs) - f x ({oldr f e xs) ample, zip cannot be so defined. Even for those that can, an alternative defini
.... . ..,. - -~-

tion may be I'(lore effh:i_ent. To illustrate, suppose we want a function decimal


We can now write h = foldr(e)e .. The first argum_eQt of {oldr is a binary operator that takes a list of digits and returns the corresponding decimal number; thus
that takes an De-value on its left and a f3-value on its right; and delivers a 13-vallte.
The second argument of {oldr is a ,8-value. The third argument is of type [Ci], II

and the result is a value of type {3. In many cases, ex and {3 will be instantiated
' .. I [ Xo, Xt, ... .. , Xn
L~eClma . ] = "L Xk 10
<n- kl
ro the same type, for instance when m denotes an associative operation. k O
The single function {oldr can be used to define almost every function on It is assumed that the most signil'icant digit comes first in the list. One way to
lists that we have met so far. Here are just some examples: compute decimal efficiently is by a process of multiplying each digH by ten and
adding in the following cli!,'it. For example,
concat .. [(ex)) - [ex]
con cat - {olclr (*) [ ] decimal [xo, x1, x2] "" 10 x (10 x (10 x 0 + xo) + xtl + xz
122 .. .. 4I Lists 4.5 I The fold functions 123

This decomposition of a sum of powers is knm\ln as Horner's rule. 'suppose we One can prove _that reverse' =- reverse by induction, or as an instance of a more
define e by n e x = 10 x n + x. Then we can rephrase the above equation as general result to be described in the following section. Of greater importance
than the mere fact that reverse can be defined in a different way, is that reverse'
decimal [xo,XJ,X2] = ({0 e Xo) e xd ED X2
gives a much more cffid~nt program: reverse' tak<;s time proportional to n on
This iS almost like an instance of foldr, e.'<c~;p t that the grouping is tl~e olher way a list of length n, while reverse takes time proportional to n2.
roWld, and the slarting value appears on the left, not on the rigl?-t. Ln fact, the There are a nturer of important laws concerning {oldr and its relationship
computation is dual: instead of processing from right to left, the computation to fold/; but we will postpone discussion to the following section.
processes from left to right. .
This example motivates the introduction ot a second fold operator, called 4.5.1 Fold over nonempty lists ,
fold/ (pronOtmced 'fold left'). informally,
Say wewish to find the ma'<imum element in a finite list of elements d.raVv11
fold/(e)e[Xo,XJ, ... ,xn- d = (-((emxo)mxrl)EBxn-1 from an ordere!=l type. We wottld li.l~eto . do this by defining
The parentheses group from the left, which is the reason for the name. The full maxlist :: (Ord ex) => [ex) - ex
definition of fold/ is max/is~ = {oldr (max) e .
{old/ (/3 - {X - /3) - {3 - [{X] - {3 where (x max y) returns the greater of x and y. But what should we choose as
fold/ { e [] = . e the value of e? In other words, what is maxlisl [}? The choice is nor arbitrary
fold/ ..f e (x: xs) = {old/ { {(ex) xs because we naturally want maxlisc [x] = x, and the definition gives (x max e)
instead. So e has to be smaller than any other value in the type ex. Such a \ah.ie
For examp~e. .. may not exist. h1 Haskell there is a ty.pe class Bounded whose instances are
{oldl (e) e [xo; x1. x2) .. types possessing maximum and minimum clements:
- fold/ (EB) (e e xo) [x1. X2] class. Bounded ex where
- {old/'(6J) ( (em Xo) ext) [Xz ] minBound, maXBound :: ex .
- fold/ {e) (((e e Xo) e xd e Xz) []
- .((e6JX())EBXt)EBXz Hcnce' one solution is to redefine inaxiist to
(Ord ix, Bounded ex) => [ex] - ex
If e is associativ~ with unit e, then foldr ( $) e and f~ldl (e) e define the same maxlist -::
function on finite lists, as we will see fn the follm-viDg-'section. max/ist = {oldr (max) minBound

-. . . example
As an;ther. ... . . .. .'definition:
.. .oJ.fqldl, consider the followirig
of the use .
,. ,. . , , ..... . An alternative sQlution that does not make use of Bounded is to introduce a
....
~

reverse~ . :;' [ C<J - [ex] < new.fold t'Wlction, one that works on rJ,onempty lists. [n fact, there are two
,-teverse' . fold/ cons [] where cons xs x = ?< :~ . such functions, {oldrl and {o/d/1. The defi nitions are
.. .
. . .
Note the order of the ar1-,ruments to cons; we have cons = flip (;), where the
{oldrl (C<- ex- ex)- [ex]- ex
standard function flip is defined by .flip f.' x y ~ f y x. The function rever:sil {oldrl f (x: ;ey) - if null xs then x else f x (foldrl f xs)
reverses a finite list. For example,
{old/1 .. (ex- ex- ex)- [ex] ..:. ex
reverse' [xo, .><t. x2) f (x: xs) f x xs'
. -
. {old/1 - fold/
- cons (cons (cons [ JXo) xd x2
For example,
- cons (cons [xo] xt> xz
= . cons [x1, xu] x2 fo/drl (Ell) [.\U,XI.Xz,X3] - Xo Ill (X1 Ell (Xz Ell XJ))
. - (xz, x Xo) fo/d/1 (ffi) [xo. ><t, xz, x3j = ( (xo Gl xd e xz} e x3
124
. .. ' 11 Usts j Tile fold functions 125

Now we can solve the problem by defining Let us now synthesise a.. more efficient progtam. The synthes is is by an
. ,l

maxlist = foldrl (m ax)


,m,cm<:uo'n argument on xs s~ we lay out.t}le calculation in the same way.

Of course, since max is associative, we could equaily wellliave defined maxlist case
,.
([]).He re we get scan/ f e [] = [e). The details are routine and are left as
in terms of foldll. in exercise. .. '
... ..~

case (x : xs). We calculate .

4.5.2 Scan left


scan! f e(x : xs)
Sometimes it is convenient to apply a foldI' operati on to every initial se~:,rrnent ..
of a list. This is done by a function scan/, pronou nced 'scan left'. For example, (definition of scan/)
map (fold/ f e) (inits (x: xs)}

= {definition of inits}
In particular, scan/ ( +) 0 computes the. list of accuiriulated sums of a list of
map (fold/ f e) ([ l: ma'p (x :) (in its xs)}
numbers, and scan/ (x) 1 [ 1 .. n) computes a list of th e first n factorial numbers.
. More substan tial examples of the use of scan/ are given in Secti9~S 5.2 and 5.3. = {sec<;md equation for map}
We will give two programs for scan/;. the first is the dearest , whJle the second . fold/ f e [ l: map.(fo/dl f. e). (map (x :) (inits xs))
is more cff'ictent.
For the first program we. will need. the function in irs that returns the list of {first equation for (oldH
.
all initial segmen ts of a list. For example,
.
e.: map (fold/ f e) (~nap (x :.) (in its xs))
.' - '
..
;,-. . . . '

{since map is a funcror)


<
::.

The empry list has only one segment, namely the empty list itself; a list (x: xs) e: map (fold/ f e (x :) ) (in its xs)
has the empty list as its shortes t initial segmen t, and all the other initial seg- {claim: {old/ f e (x :) =fold/ f (f ex)}
ments begin with x and are followed by an initial segmen t of xs. Hence
e: map (fold/ f (f ex)) (inils xs)
t
i
' in its .... [ex) - [[a]) ... ... . = (definition of scanl}
-
+

;' I' inics [] [[ ])


e: scan/ f (f ex) xs
- -
\
inits (x: xs)
- ......
[]:map (x :) (inirs xs)
.. ......
,.'The claim is left as a short exercise. In sununary, w.e have derived
;

The function inics can be defined more succinctly as an instance of foldr:


....' ..
scan/ f ![] - [e)
inits = (oldr f [[]) where f x xss;,. [ ) :.map (x) ~s
SCan/ { e (X : XS) = e : Scan/ f (f eX) XS
Now we define
This program is more efficiem in that the function f is applied exactly n times
scan/ .. (ex - f3- t3l- f3- [a) - [a] on a list of length n.
scan/ f e - map (fold/ r e) . inits
This is the clearest definition of scan/ but it leads to an inefficient p~;ogram. The 4.5.3 Scan ri.ght
function f is applied k times in the evaluation of fold/ f eon a list of length k and,
The dual compu tation is given by scanr, defined by
since the initial segmen ts of a li~t of length n are lists with lengths 0, 1, ... , n,
the function {is applied about n2 J2 times in to.tal. scanr ra = map ({oldr fa). tails
126
4 I Lists 1.5 I TlJe fold functions 127
. ..,
The functi<:m .t~ils returns the tail Se,g:r:tlents ,of a list.. F6r example, ' .
4.5.3 Which, if either, of the following equations is true?
<.
<

tails[.\'o,Xr , Y2] = [( XQ,xi ,x2]. [ x1 , X;!], [x2 ] , [)] '


fold/ (- ) x xs - x - sum xs
'

No_te that _while inils produces a list of initial segments in increasing order of {oldr (- ) x xs = x - sum xs
length, tatls produces the tail segments in decreasing order of length. we can
define tails by 4.5.4 Co:qsider tlle follmving definition of a function insert:

tails [ ] = [()) insert x xs = take While( ~ x) xs * [x] * dropWhi/e (5 x) xs


tails (x : xs) = (x : xs) : tails x.s Show that if xs is in noridccrcasing or~er, then so is insert x xs for all x. Use
insert to acfine a function isort for sorting a list into nondecreasing order. Use
The corresponding efflcicnr program for scanr is given by
{oldr.
scanr{a[] - [a] 4.5.5 The function ren1dups. removes adjacent clupHcates from a list. For ex-
scanr {a (X: XS) , .= f X (head ys) : ys ample, remdups [1, 2, 2,3, 3, 3,.1, 1] = [1, 2, 3,1]. Define remdups using eithet:
where ys = scanr f a xs fold/ or {oldr.
'
We ~yiU leave the synthesis of the more..efficient version as an e;xercise. 4.5.6 Given a list xs = [xl. X2,. 'Xn] of numbers, the sequence of successive
0.

maxima. ssm xs is the Io!)gest subsequence [~II XJ.: , .. . , x.;~ l such that J1 = 1
and Xj < x;~ for j < }k- For example, the ~cqu ence of st.icc.essive maxima of
4.5.4 Squ:is over nonempty lists
[3, 1, 3,4, 9; 2, 10, 7] is (3,4,9,10]. Define ssm in terms of f'o/dl.
We can also define two further scan.funclions, scanll and scanrl. We have 4.5.7 Prove that scanlf e[] =[e).
scanll ( . = ,;.,ap ({oldfl f) . inftsl 4.5.8 Justify the efficient program for scanr.
scanrJ f . = map ({oldrl f) . taiisl 4.5.9 \Vhat list does scan/ (I) [1 .. n] produce?
Wbe.(e initsl and tailsl return fue n~~empty initial m d final segments of a 4.5.10 The mathematical constant e is defined by e = 2::~. 0 1/ n!. Write down
nonempty list. For example, an expression that can be used to evaluate e to some reasonable measure of
accuracy.
initsl (x : xs)
... . . = map (x :) (inics xs) .' 4.5.11 Consider the datatype Liseeex defined in Exercise 4. 1.4. The fold function
Using fold/1 f (x :) = {old/ f x, \ve.obtain ,. for this datatypeis.pefined by
. .. . .
.. . ({3 - ex - {3) - /3 - Lisee ex - {3
sl.:anl! . - ==. . ' (ex :.,. ex ~ ex) - [ex] - [ex] ' ...,. . f'olde --
~ scanll.f <:x.: xs) "= Can/ f x,_xs .- .._ . ' , folde f e Nil"-_ = e
" '
folde f e (Snoc xs x) - f (folde f' e xs) x .
The eff:~cient versionof :scanr1 is left as an exercise.
' . The lype assi~:,'11ed to {aide is very nearly the same type as that assigned to f'oldl,
Exercises :., the only difference beingthat [ex] is replaced by Lisle ex. In fact,
' -
4.5~1 Define {ilte~ pas an .instance.~f foldr. ' .' {olde f e = _ (oldlf ~convert
.. , ., . . . . \ ; .
4.5.2' Cohsid~r the tv.io fw1ctions take While and dropwhii~. which w;re dis .where convert :: [ex].- Liste ex. Define the function convert and prove by induc-
c~sse~l in Exercise 4.3.7. Define takeWhil~ as:an instance of {oldr. Can dropWf;il~ : tion that the above....equ(\tion holds.
be defined as an instance of a fold function? ..
' ~ '

' ' 4.5.~2 Derive an efficient program foi scanrl.


128 4.6 I Laws of fold 129
4 I Lisrs
..... :- .
.,.
4.6 l-aws of fold Case (x: x:s). For the left-hand side we reason
-----
. . .... .... -....... .. .
. .....
... ','- -~ -
{oldr (E!>) e (x: ~)
There arc a number of important laws concerning {oldr and its relationship
with {old/. As we saw in Section 3.3, instead of having to provea prOtJCrty' of {definition of {oldr}
a recursively defined function over a recursive datatype by writing down an
x e foldr (Ell) exs
explidt induction proof, one can often phrase the property a~ an instance.of
one of the laws of the fold operator for the datatype. = {induction hypothesis)
' i.
....~ . x mfold/() ~xs
f
1:.
. I' . 4.6.1 Duality theorems
..
. '
For the right-hand side we reason
The first three laws are called duality theorems and concern the relationship
between {oldr and fold/. The first dualiry theorem is as follows: fold/() e (x: xs)
First duality theorem. Suppose ED is assodative with unit e. Then {definition of fold/}
(old/() (e x) xs
{o/dr (ED) e xs = {old/ (ED) e xs ' . ..
..;,. . ... {assumption}
for .all. finite lists xs. . .. . .,
fold/'() (x Ill e) xs
For example, we could have defined ..
". The two sides have simplified to two different expressions. To show that they
. .

sum = fold! (+) 0 . are equal we have to resort to a second induction proof. However, if one takes
and <" > True .: _... ~ -

fold/ as the second induction h)tpothesis the obvious assertion that,'


concac - fold/(+~) [ ]
. '
However, as we will elaborate in Chap ter 7, it is sometimes more ef'ficicnt to xED{old/()exs' - ' )xs
fold/()(xa>e
. . implement a function using fo/d/, .and sometimes more efficiem to use foldr .
The second duality theorem is a generalh;ation of the first. .
for all x and finite lists xs, then the induction doesn't work. The only way to
Second duality theorem. Suppose e, , and e are such that-for all ,~. y, and z appreciate this fact.is to try it, a task we leave as an exercise. What is needed
we have is a scronger hypothesis, namely
,.
x ED (y z) = (x Ell y) z
' ..
''.!
...... ....... . .
.-..~-:..
-- -:,: '

- .. x e foldq)
~

xEDe - ex . ' ,:,.. :.''"' y xs = fold/ ()(x e y) xs


. .. -~ ...-:... tl.,.

ln:other W~rds, ED
.~ , '

and aSSOCiate.with each Other, and ~ Ol:\. ~right Of Ea . iS


' I
,. '

equivalent toe on the left of. Then for all x, y, apd fuyte lists xs. As we ~ aw in Section 4.2 in the. discussion of .
-::: :
reverse. making an induction hypothesis stronger can often si.inplify a proof.
foldr (e) exs - {old!() exs . ..
.. Case ([ J). Both sides simplify ro x Ell a.
for aU J'i.nite lists xs.
" .
.. .....
Case (z : xs). (Note the use of z to avoid confusion with the' variable x already
Proof. The proof of the second duality theorem is by induction 'on xs.
present in the 'assertion.) For the left-hand side we reason

Case.((]). Both sides simplify to e. )f. e fold/ ( ) y (.z; xs)


- ". '- . .
::

:.o ... ...


'

"'. ' .- . -. ,._. . .


' 41 Usts
'
'

4.6 I Laws of fold


: 1' ' -
. .- ' ' '
l ... . . .
. . . 131
.
_. ., '
..
----- . ".
. ..

. .' . ' . ... ' '- " - ' " -
.: '
.. '
- '

-
< . '
'
-
'
. ; ,-_~ ..-- . '

- . {definition} ,._' , '_,


Since foldr (:) [] . id and {6/dl(flip (:)) [] - reverse, we obtain
. . . .. -~ - ' , _., .

.-
X ffi fold}() (y Z) ..
-'" '
.L I . .
~
' : ' .

- ,. ,_, . .
. . .
. xs . -:- .. reverse (reverse xs) .
- -- . - {induction hypothesis}

for all finite lists Xs, a resUit\ve have already proved directly.
': ...
fold/() (xffi (y z)) xs ,. .. - ._.

{assumption} 4.6.2 Fusion . - . .

. .
.. . . -_. . ,


. fold/() ((x ffiy) z) xs The duality theorems deal 1-Yith the relationship between the two kinds of fold
' r: -'" _, '
For theright-hand side we reason ' ' .- . . operator on lists; .the fusign theorems deaL with one.kind of fold operator only ... -
. .. ' '

The fusion theorems for foldr and fold/ are as follows .


'

'
.. - '

--" ' -
fold/(} (x ffi y) (z: xs)
Fusion theorem for foldr. Iff is stri~=t, fa = b, and f (g x y) = h x (f y) for all
,' -- . ' ,; ''
, : I
{definition} x and y, then
.. . '
'
.'. -- '' ' . fold/ ( ) ( (x. ffi y) z) xs f foldr g a - foldr h b

., ,- ' . . ...
:- .
" .
.. ' . ' D
: '.' ..,- . -

Fusion theoreniforfo/dl.Iffisstrict, fa b, and f (g xy) h (f x) y for all


' '
',

. f '' ' =

_: [
\ .
'- -. : '
.-' '

..
.
Tlie second duaD.ty theqrerri has the fust duality theorem as a special case, .

xandy, theri ,,
n<iinely when ( ffi) = ( ).
- ~c -


' '
:' ,! '
': '
' " .. ' .. To ill~strate the second duality theorem, consider the following definitions. f fold/ g a - fold/ h b
'
- J _., ~ :: ' : '
; ;
_._)..'
';
of1engthand reverse: . "' ' ,. '
"-'...
'

. ' . ''
.
. .'
' :" :
--'-'-:~ / '
. ' .' ' - . . : .. . .. . . . ' ' ,. .' .
'
'
.. ,
'. . .The proof of the fusion ,theorem for fOldr is very similar to the one in the
.. length
'

foldr oneplus 0, . where oneplus x n. = _1 + n


'
1- . "'
previous chapter for foldn, and is left as an exercise. The ptoof of the fusion ....
., . ..
(I'
. 'I. . ., .. .
.:; .
'

.. . . =
. .. .
'.,-'. ,.I, I ' ' :.... ~ - ' '

.. . . .le'l'lgth fold/ plusoneO, where p/usont:! n ~ . = n + 1 theorem for fold/ is trickier, a,nd is explored in Exercise 4.6.3.
'


'

.'. ; :: :.,.i ~'' .


= .
.
'-. .
.. The fusion law is verygenerar, ..and- there are useful special cases. Four Of
., ;,
. ,; : ~;, .
)

,:

*
'
...
reverse - . foldr shoe t ], .where snoc x xs .. ;.(S [x]
'
'

these are considered next. .


,- ,' / '' !
' '

"-'-"---'
:~ '' .,' ., ..
..' ." .I .' . .
..
I , . ''.. , -
.
reverse - fold/cons[], where cons xs x x; x.S
-~

- ----
. .. ' .
'1 "~:'' :-lr:.
:
-. ,e'. ~ '." '

,- , ..... .., .. . .. .
4.6.3 Fold-map fusimi
, ' '


':.:-
' \
:;
' ' .,
' , .. ''
.
-
The JnnctiC)ns oneplus, plusone, and 0 meet the conditipns of the second dual-

ity theorem, as do snoc, cons, and [ ]. We leave thev.erification as an exerCise .


Recall that map g foldr '(cims g) [],where cons x xs = x: xs. Consider what .
Hence the two definitions of1ength and reverse are eqUivalent on all finite lists.
conditions ensure that
' . )tis Iibtobvious whetherthere is aiJ.y practichl difference between the twb defin: .. .. :,

of
' '

itions length, butthesecond prog:ramfor reverse is 'the more efficientoffhe


.
. ' ' '

.,: ' . .. . .. .. . ' .- .


f
foldr a map g . . foldr h b .
. ... ..
.
"
'. . . .
. . tlNO, . .. .
' ,.'- .
.

art exe~cise.
' . '' '

.. Looking at the conditions<.of~hef;sion theorem for foldr, we have that (oldr


,. ' '
'
' . ';_ ':_j ' :,
.- . . The proof ofthe third duality theorem is left as (h
.TJtird ct1lality theorem. For all finite lists xs, .
'
i :).: . . ' . is a strict function, and the second condition is satisfied by taking a = b..The
. :.>
' . ' ;
',',...:.:..... ..
.. third condition expands to : .
.
. .
~

. .. '; :.. . ,., .-:. ' ' ," '

..
. folqr f e xs
I -

= .. fold/ (.flip f) e (reverse x.s) ' . ' .. . ' . ,

.,, . .
: ';':
'
-' . .
' foldr fa ((cons g) x xs) = h x .(foldr fa xs)
' . -'
'

!"<:; . .. . ~ - -- .. .
.. .
Where flip {X Y = { Y
'

.
'. ' '
X. . . . .. {definition of col1s) . ' . '

..
\_'c::J.
. ,___

..
To illustr~t~ the thlrd duality theorem, consider
'

. .
foldr . fa (g. x: xs) . . h x (foldr fa xs)
' - ..;
. __ , . .; .- _..:,- ' , - .
.
.- . . .. ..
- . .. ....
' ' .. . . . -
' . '

- ..
- ._:_- ..
I: :r'
.. foldr (:) [] xs -
__ ,.

{definition of foldr}
"

fold/ (flip(:)) [) (reversex5 ) . ', .


,. - -
.. .' .

-.: .. ..' .. ...

!.,

' ' ...
- .' "
'

- -.-..

' ' : --_;_


' ' '
. .-.
.;.
.
' '
'
~ '-'--'-''
132 . ., ... :

.... .;~.'~ "";"-~ 4/ Lists :J.6/


. . Ltws of fold . 133

#~ ~~~~~.: ;~.-~
.
_. . .......

. ,.. . ...~ P .,. .


f (g x) ({oldr fa xs) = h x (foldr fa Xs) : ,.:.: '-.:. - . We ~an use the rold-concar ancj. fqld-m ap
.. .', ..-" . fu~ion laws tb rewri.te ~he book-
{generalisation}
\
:
~ ---
.'
-> .-.-.;..- . keeping law in the form
f = hxy
(gx) y
{oldr (flip (foldr f)) a = {o/dr ({ foldr fa) a
The symbol : is prono unced 'fi>llows from'. Since h -~ y = f. ('g ~ y if and only
This equati on hoids if flip ({oldr f) == f fo/dr f a. Applying both sides to xs
if h x -= f (g x) if and only if h = f g, we get the result .that . - and then y, we get
. . :.
{oldr fa map g = f'oldr (f g) a . foldr f y xs .= { (foldr fa xs) y
In words, a fold after a map can always be eli.1Jresse d as a singte fold. \Ve will This equation hoi~f~ ir f is associative with lmit a proof we will leave as an. , a,
call this law the fold-m ap fusion law.
exercise.
'
I ' '

. .
In summary, the bookkeeping law iS valid whenever the argum ents to {oldr
4.6.4 fold-c oncat fusion me an associative operation and its unit. For example, since strm = foldr ( +) 0,
As a second example, recall that con car = foldr ( *) [ ]. Consid er what concli- the bookkeeper's accounting metho d is justifi ed. As anothe r examp le,
rions ensure that ..
. ,
....
, l
.. conca t conca
. .t .= conca r map conca t .' .
{oldr f a concac = foldrh b ~ . . . :
This equation says that flattening a ll~t of lists of lists into 'one long list .can be
Again, looking at the condit ions for fusion, we huve that foldr fa is strict, and done by concarenatin'g outside-in or inside-out.
the ~econd condit ion is satisfi ed bY.t<lkiP:g .a = b.' The .hir.d. ro,n~tion eli.1Jan ds
to 4.6.6 Fold-s can fusion

{oldr fa
. (xs * .ys) = h xs ({oldr fays)
.
Consider the equati on
(claim: {oldr {a (XS * ys) = {o/dr { ({o/dr?.a.ys-~ xsr + X0 + X0 x X1 + Xo X x1 X X2 = 1 + Xo X (l + XJ X (l + X2 )).
l
. .. .
. .....
.
= h xs ({olclr {a ys) .:
' . .
foldr f ({oldr fays) xs , ~ .. :
' . . . .
':
~

. .. '

... The equation generalises ro an arllitra ty Jist of numbe rs and can be expre ssed
. Hence we can lake h xs y = {oldr f y xsor, more shortly,"fj";; :~ip(foldr {).-Th e in ijle form
proof of the claim is left as an exercise. IIence we hav~ shoWn tWit
.. : . f'oldr l(+)s canl( x)l - {olclr (0)l
. . . .: ~ ... ;. ~ . -.
t. .. .:;. -

~.:
. ~::. .~ .:; ;:~
. \ .! ' ,.:,
{oldr ({lip ({oldr f ))
= 1 + x x y. This leads to a more.general ques tion:. ~hen does the
. foldr fa q>ncat ' .
I
= a '1he~e x0 y
1I. t
.. We will call this the J'old-concat fusion law. .
"~
law . . .
. ~ . ..: .~::\;~; :-:~~-- {
' ; . .\ : . . -:.:::;... . 0

. ...
. . .. '
.. #
._.

. .. .. ~.
;

. . .... . i, ~

. {oldrl (ED) scan/( )


-; .. e foldr (0)
4.6.5 Boo~eeping law . . ... . :- ~
= e
hold, where x 0 y = e ED (x y)?
As a third ex{l1Ilple, consid er what conditions on f' and a.ensur e:itiar
Under the assum ption that is ossociative arid e is the unit of , we can

express scan/ as an instan ce of foldr:


<l o ,

foldr fa conca t =
foldr fa . map ({oldr fa) :~ ::;~. : ..
.... .::. . . .
We will call this particular equation the bookk eeping ,law. Tbc.sp e.cial instan ce scan/ () e = {oldr g [e} where g x xs = e: map (x ) xs
su m concac =sum map sum is exploited by every beokkee,Q.e;.wlw sums each
Th<z proof is left as an exercise. Having rewrit ten scan/ as an instance of {oldr,
. indivi dual day's accounts, and then gers the year's total by sti.rfunirig the sums:
we ~'an see rhal the requir ed law is yet anothe r instanc~ .o f:the fusion law for
:"' ' ... - ...

.. . . ...
~"- .. 4 '. ~--
., l
134 4/.Lists 4.6 I Lai-vs of fold 135
.. ' .... ' .
. . . , . ' ' ' ' ' ,. : .... - t~ ' ' r' 1 '

.. . foldr. The first two conditions are inunediate, and the third expands to .: where segs retums q lisfof qll segments'of a list. Tllis. fw1ction can be defined ..
in a number of ways, inclu~g_
{oldrl ( ~) (g x.~) = x 0 (foldri { ffi) xs)
- segs = concat map inits tails
. = {definition of g}
foldrl (ffi)(e :map (X) xs) =X 0 ({ofdrl (Ell) xs) This definition corresponds to the process of taking all the initial segme'nts of
all the tail segments. For example,
.
{definition of foldrl an.d 0}
e wfoldrl (Ell) (map (x) xs) = e Ell (x foldrl {fll) xs)
'

..
The empty sequence appears four times in this list, once for every tail segment
: {substitution} of "abc". . . ' .
foldrl (m) map (x) = (x) foldrl (fll) . Direct evaluation of mss will take a number of steps proportional to n 3 on
. ' .
a list of length n. There are about n 2 segmems, and summing thein all t<1kes
The last equation holds if distrtbutesover Ell, that is, if
about n3 steps: It is not obvious that we can do better than Cttbic time for tllis
X (y.ffi Z) = . (X y) E9 (X Z) problem.
However, let us see what we can achieve with some calculation. Installing
y,
for all x, and z. The prOof is left as an exercise. . . . _' .: . ' " ,,,. the definition of segs' in iiiss, we have' to compute
' ..
. .
In si.urimai-y, if i~ associative 'with unit e, arid 0 distributes over m; th~n . '

maxlist map sum concat map inits tails


..
foldrl (fll) stan/() e ,; {oldr (0) e where x 0 = e e (x y). We ~111 call this y , ' I ' - " ' .... '

the fold-scan fusion law. The only thing we can do with this exp~essiQn (apart from going backwards) is .'
In the ieirimnder 61' this section w~ will give an example of" hOw the$e iaws to use the law rhap f :co neat = concat<map (map f) to rep)ace the second and
can be used in the synthesis of efficient programs. . . . third terms, obtaining
T ~ '

.
. . ma.xlist coneat map Jmap sym) map inits _tails
.
' I
4.6.7 EXa~ple: the maximwn segment sum . '
. . . . !
There are two things we can do now: we can either apply the bool<keeping law
The maximum segment sum probiem is a famous one and .its. history is de- ... .. z;<:~.--t9 the first two .t erms, or apply the law map (f' g) = map f map g to the tllird
scribed in J. Bentley's Programming Pearls (1987). Given a seqi.1ertce ofmim- and fourth terms.. Of cowsc, . ..we can also . do both these steps .a.t once,
. ht wbich
.
bers it is required to compute the maximum of the sums of all segments in the
~

. case the result will be ., ..


sequenc~~ For exanipi~; the sequence . . .:. . . . . : . .. . : - ... . . . .:.. ... '

'' ... maxlist . map mdxlist . map (map sum . in its) . tails
, . ' I'
[ .:.::1, 2, '-3; 5, -2;.1, 3, ~.2 .:.:z, :.3, 6] .. .' :.:
.~ : .."~:.:.;. ':'

..'For
. th.e next step we can apply the map law once more .and obtain
- ~~ "!. :-. ..
,,
h~s rriaxirrilim .sum 7 ;:the swn of.the ~egmeilt [5, -2, 1, 3]. 'a~ the other l:i.and, maxlist map ( maxlist :: rt!.ilP sum inits) tails
.... , the sequenc~ [-1 : -:-z, -3 ] has a ma:dmum Sei,'l):J.ent sum ofzero, Sin<;:(!-the . ~ ' . ; ~
'
."'
~mpty s~ctitence [ ].is a segment of every list and its sum lS zero. It follows ' 'the trm map sum . inils can be ~epla~ed by a sca~l. a substitution tha.t could
that ~he ma..ctrrm:m segment suin is always no~megative. (The exerCises deal have been done one step earlier:_..
.. ~vith a variant p roblem in which the empty sequence is exch~ded, so the max- . ..
imum segment sum. be negative.) can .. maxlist
.. map (maxlisr scan!
. . (' +)' 0) tails
- . . ' . - ' . .. .' .
The pr?blcm can b'e specified formally by .
'

.. '~ .
. Since _maxlist = {oldrl (max) and ( +) distributes over '(max), the ~old-scan
fusion law now gives
mss - ..
i
[Int] ~ Int .. ' '
mss - maxlisl map sum : segs. maxli.~t. map ((oldr (0) 0) . taiis

~ . . ' I ...

''
rr!" : ~ : t. , ;...... . . . . ;:, ~ ..... .
~I
j . 136 4 I Uses 4.7 I Chapter notes 137
. .. .' .... . .
. . -::-
""
. --
~I where x 0 y = 0 max (x + y). Finally, the last two' terms can bereplaced by a - f~r f~ldrl ~rtd t;se it to give conchtions on-,: g, ana h
o ' 0 r ;' o ;
' .'
' o

. ~ . 4.6.8 Givea fusion law


scanr, and we obtain .. --: . _ so that the law

mss = max/ist scanr (0) 0 foldrl f scan/1 g - (oldrl h

The result is a linear-time program for the maximum segment sum. is.valid.
4.6.9 Define segsl by segsl = concat map inifsl . tailsl, where initsl returns
Exercises the nonempty initial .segrnents of a list, and tailsl the nonempty tail segments.
.Use this _version to. stare . <)ncJ. solv~ a version of the maximum segment sum
4.6.1 .Prove the third duality theorem. problem that leaves out empty segments.

4.6.2 Prove the fusion theorem for foldr. 4.6.10 Tliere is a version of the fold-scan fusion law that does not depend on
any properties of the operators involved. The law is
4.6.3 The fusion theorem for fold/ states thqt f fold/ g a = fold/ h b provid ed
f is Strict, fa = b, and f (g X y) = h (f X) Y for all X andy. fold/1 (!B) scan/()~ = fst fold/ (0) (a, a)

In the induction proof the case (x : xs) requir es us to show: \ that z. =.?(~'J/Uf~4 . '-r' = y
Ilef:~ ;, Prove tills ~ersion of fold-sca:n
.: wirh.. (x,. .y) .0
. 1 ..'' . .
. : . ... , ~
.
.
\

fusion.

- .
f (fold/ g (g ax) XS) = fold/~ ( h(f a) X) XS - -
' '
.
To do this we need asecond induction hypothesis, namely that 4.7 Chap ter notes
.' ..
f' (fold/ g (g x y) zs) = fold/ h' (h (f x) y) zs Haskell provides many more standarcHunctions on lists than we have described
.L
L
; 'I

.
) 1'1 .. . in this chapte l'. For full details, consult the Haskell standard prelude and the
for all x and y and for all lists. z.s. Prove this equation and. comple_te the proof
.~

-1
library of list functions. '
w
1o ;' of the fusion law. - -
A great deal o~ workha.s_,))e~n do:11e on automatic or machine-aided gener-
.'~ !! . . . . atiOt1 oT induc tion pfobfs:::se(' for exah1ple, Boyer and Moore (1979), Goidon,
,.. . 4.6.4 Prove the equati ons
-
..\ '
Milner, and Wadsworth (1979), Paulson (1983), Martin and Nipkow (1990).
:) :. .... ... - Tlie relationship between polymorphic functions and naturality conditions
j .I
:!,.~~ foldr f a (xs * y.s) = {oldr f ({oidr rays) xs
: 1 ot l

r * ys) {old/ ( (fol_dl (a XS) YS ;- ~;; ;,: :. .. is explored in Wadle r (1989); see aiso Bird and de Moor (1997):
'' (old/ a (xs =
were systematised in ;Malcolm (1990),
~~- .
'f.lie f~ion . operators
laws for fold
: ... t . . ... ~

.

o ~

. :, .
-wh.a t restrictions on xs and ys are ne~essa.y; if any? ... . ~ :. _- . .. Fokkinga (1992), jeuring (1993), and Meijer (1992).
I

' ;
~!
. .. . Th~ Il!a~mwn seg~~%..S1Jlp, .p,r.~bl~m is described Bentley (198 7). The in
written
.. \ ~~ '"J . -

ns a f~ldr if~ is"as.so~l~iivc With miir.


:1'
J, ! 4.6.5 Prove thar scan/ c) e can be deri.vation recorded in this chapter was first given in Bird (1989}.
e.. Can scan/ ( ) e be written as a fold/ withou t anyassil.inP,tiojrs _on ' and e? -
q , .. ....~...:..
4.6.6 Prove that if dist-ributes over IB, then

. foldrl (!B). map (x) = (x) {o ldrl (!B) . . : : -

' . . .. -. . .
4.6.7 It is tempting to rry to push the calculation of the maximwn segment sum
' -~

one step further and use tl)e fold-scan fusion law to replace' maxiist. scanr (0) 0 .
by a fold/. Why doesn' t this work? (See E{cercise 4 .6.~0.f.or,~v~~sion of fold-scan
fusion that docs work.) ":. :.:
. . ., .
...... -
... ':.

. ' . .
. . . . ...
..,...,
!
.. ; . .. . ..
.
~

Chapter 5
,o'


' . ' .
.-' ' . ... ..

Examples

The examples of list processin g dealt with


. in the present
. chapter come from .
a variety of sources and cover both numeric and sym)Jollc applications. In
.

'
particular, we will build a simple package for doing aritlunetic With arbitrary
pr'ecision integers, design some useful functions for himdJing text, and.show
:
how to print a calendar. We begin with a simple problem in whlch list ind~xing
plays a central role:
..... , . . . .' '
. . -. 5 .~ Converting number s to words
..
' .. Sometimes we need to write numbers In words, For instance, to fill out a cheque
. "
... .. or c~s~ transfer correctly, not only must the amount appear in figures, it must
,. also be written in words. Suppose, for simplicity, that the given number'.is an
' .,,,
.. integer greater than zero but less than one million. We want to design a function
convert so that, provided n is..m the stated range, the value of convert n i:;.thc
. .. . -. list of characters correspon ding to the usual English formulation of the w,l:t<:>le ,

. " . : number n. ; -...;,~': ~, l
...... .. -- . . \: ..
.- . . '
'
' The iriformal specificat ion above asstupes'we know exac.tly what 'the ~sua!
"

,., . ..... . .- ." ~~ '


:'.
.I
. . .. . .. English formulation' of a nwi1per is. ~ fact, different rules and converi~ions .!
' '
. . are adopted in ditiereJtt PJ!\Cf;!S; The ntles we shall f~llow are illustrated by the '
'

.. follq:Wing exarnpl~s: , ,.
....
? convert 308000
,.

- ..
I ,, '

.... '
"thr~e hundred and eight thousand"
.. . :
. '
..- . ? _convert 3~902 7
.
.
.. . "three hundred and sixty-nlrie 'thousand and twenty~seven"
,'

? convert 369401 .....,..


..
.. "(luee hlmdrcd and sixty-nine thousand fow hundred and one"'

. .
.. ,..
..:,'
140 "~ -u 5/ Ex~mples
.. :j,l./ _Converti11g numbers to words 141
. - :::.. :.
. . ,.....,. ~
. .., . . ',

Notjce 'the .dash in the phrases "twenty-seven"ri:n'd "sixty-nine", <q1d the ton- . disjtil.n t, $0 the ord~f of the equations is' not i~poriant. Ho~everi rio value is
necting.word."and" which appears: .(i) after the.word<"hvndre<f~~i the tens pqrt - specified for the panern (0, 0). . . .. .,
is 'n onzero; and (i.i} after. the word "thousand" if the hundreds part is zero but . The. case 0 <' n < 100 yielded easily enough, so now let us investigate the
the tens part is not. range 0 < n < 1000 when n can have up to three digits. We would like to make
A good way to tackle such problems is ro consider a: simpler problem first. use of convert2, as well as to exploit the simple structure of definition, so its
There is, of course, no guarantee that solutions obtained for simpler problems we define
can be used directly in the problem that inspired them; they may only serv-e
to familiarise the solver with some of
the features and difficulties involved.
convert3 .. Int _. String

Even so, the work is. not wasted; familiarity with a proplem is one of our inost (:Onverc3 . - combine3 - digils3
important tools for solving it. And often we will be able to use the solution digits3 .. Int- (Int, Int)
directly or by adapting it. .. digits3 n - (ndivlOO,nmodlOO)
An obvious place to begin is to suppbse that the number r .belpngs to a ' .
smaller interval, say 0 < n < 100. In this case n has one or two digits. Thes!! combine3 . (Int, Inr) - Siring
digits are going to be needed, so we start with the definition C<?mbiY!e$ (0, t + 1) - converl2 (t + 1)
.. comb(ne3 (h + 1,0) - units!! h * "uhtmdred"
convert2 .... Inr- String ' ..;..._ .... .... . combine3 (h + l, t + l) = units!! h * "uhundre~ andu"
.-
convert2 - combine2 digit-s2
: 'J '
*convert2 (t + 1) .

is of
digics2 .... Inc - (Inc, Int)
. 'This st.e p the crucial one as far as .the design the ovet:all algoritl1m is
- (n div 10, n mod 10)
digics2 n
....... ... -
~~ ~
concernecl. We split n int~ digits in t\VO stages: first in(o a hundreds part h ~nd
In order to define combine2, we 'will needthe English names for the simplest a parr r less than a hundred; and then, in the definition of corrveri2, split t into
nt1mbers. These can be given as lists of strings: -' a tens part and a part less than ten.
Now we are ready to tackle the next and final step in which n m~s in the range
unics;Yeens, tens::
. [String]
. :
' .-. - i' 0 < n < 1000000 and 's o can have up to 6 digits. In a similar spirlt to befor.e, we.
units - ["one", ''two~. "three", "four'', "five'\ - . split n int6'h-\>6 nu:m hers m and h, where m is the thousands part and his the
. part less than a thousand. There vvill be a connecting "and" beaveen the words
"six", "seven" .."eight", "nine"]
teen.~ .,-:- . ["ten", "eleven'', "tweive", "thir(een''., "four'te-~1?,'. for m and h only in. the case that m > 0 and 0 <_ h < 100. Hen~e we have ..
"fifteen", "sixteen", "seventeen", "eighteen'::;~pil}.eteen"]
#

..;convert6 .. Int - String


tens . - ("twemy", "thirty", "forty", "fifty'~. ~ ' .. .

"sixty", "seventy", "eighty", "n!necy"J : . .' --::


convert6 - combine6. digits6
. . :: ,." ,._- ~
cligits6 .. Inc :.... (Int,,Jnc) ..
The definition of combineiuses these lists by extraQtltig.ap]JI;qpdate elements .., digiCs6 n - (ndiviOOO,nmod1000)
depending on the digits: ;.. ~ : :.,.~,>1;: .:~.: .
combine6 . . .. . (Int, Int) - String

..-- ....
combine2 .... (Jnt, Inc) - Siring '. combine6 (0, h + I) - conv.erc3 ( h + 1')
- ~
~

., . .. (0,. u + 1)
combine2 units!! u
.. ...
combine6 (m + 1, 0) - convert3 (m+ 1) -tt "uthousancl"
..., -
.-. .
- .
combine2 (l, u) = teens!! u -
combine6 (m + .1, h + 1) - convert3 (m :t-0 * "uth9usand"
combine2 (I'+ 2, 0) = ... . - * convertJ(h + 1)
- .
tens!! t
.... *link (h + 1)
combine2 (t + 2, u + 1) = tens!! t * "-" * units i!u: ....
.: link Tnt - .String
Recallthat list-indexing begins at 0, not 1. The p_a tterns ~n theteft are mutually link h . - if h < 100 then "ua'ndu" else "u"
.. . ' ~

' '
.,

142 5 I Examples 5.2 j Producil!g ~ class list 143


' .
-
. .. . . . . .
-: .
.
... .. .. . . .. . .
.. ~

.- .The -required function c-onvert is just the-function convert6, so weart( done. _.- . The task of the ex'aminer is to .use these two lis.tsto produce an alphabetical .
As w~ll .a~ being a good illustr~tion
. of the use of fl- a,nd'!!, this example also :. clas"s list of candidates, tMiqnc;uks, and thelr final. ranking. It is also required
. demo1J:;trates the advantages of pattern matching over a definition using condi-
'

. to"pr'int the result.in a suitably attractive form. For example,


. tional cX]),ressions. Each case is expressed clearly and concisely, and it is easier . .... ~ ...
;>
~:.

. :~ .-

. . to check that all cases are covered. ' - Name Mark-- :Rank
, ,
AN.DERSON 30.. ~5 . . .
62 .. 2' .: ;
' . Exercises BAYLIS " .

CARTER 1
5.1.1 Moqify the solution so that a full-stop character is printed after a number. DENNIS 2
EDWARDS 4 ,
. 5.1.2 Generalise the solution.to handle positive numbers up to one billion.
. . ' .
5.1.3 Show how tlie solution can be adapted to handle negative numbers and ,B~fore starting to think about the problc'!l, we introduce some appropriate type
zero. synonyms:
5.1.4 W:rite. a similar program to convert a whole ni.unber of pence into words.
' I ,

type Name = String .


For ~xample, t~e numbe~ 3649 shoul9, convert to "thirty-six pound~ a)ld forty- . type lden = Integer
nine pence". . . .: : ' type Mark - Int '' ..
.. ..
.. s.LsAsa much more 'difficult e~ercise, wrtte a p rogram which will do the type Rarik. = Int '.
'. inverse of: convert. 41' other words, t)ie input .is. the Engli~h forrnulatio'n of a ''

-. . .!)umber. and the output is tbe corresponding decimal representation: For brevity, we a:iso introduce .
#
; .
. -. . ~ .. .... . ~. .: type Codes_ -: [ (Name,
. . Iden)] .
.. - , .
~

.. . ~
type Marks . = [([den,..
Mark)] '
' ' .
I : . . ,, t , , ,. ' , , type Ran.ks . = [(Name,
. Mark,
.. Rank)]
Consicl~rthe.problem of p ro_!:es~ing examinatiort marks.to procluc~ a final class . .
The (wo functions we have tQ implement me

. list. There are two inputs to the problem, both of them nonempcy lists. One.
~ :, o ' ~ ' , ' I '

lis.t, known only .to the examiner, co;1sists ~fan c}iphabeticalli~t of.<:andidate
.'
riames together wl.th cah~idate.idcntiflcati or1 ntimbers. For example, : .:
class/ist .. (Codes,.Marks)
.. - Ranks .;
.: : '

. : .
.. ' "
.. '
display :: Ra nks - String
.. . .. .
. - . . .... . .
ANDE~SON.
'
:,
....... pefining ciasslisi as a nonc.urrie.d fuqc tion me~s that we can exploit a c6~pos: _. - .
._~ , ~ .. BAYLIS 101'369 ' ........ .
.- . . . ..
' . t
- . -.
- itiorial style. ._:: . . _._ . .- . :: ,... -. . -_.<..
-~- ' I \ ~

'. _.-. .. CARTER .Ioi3io .


- :. - 0 - : ...

.. . . . .. ...
:!

.. . .... -. ... . . : . :t:'et us conc~li. tra.te first


--.- .:\ _' : DEN~ is"'. - on:ciasslist..It is sensible to construct this func'tion in :
. . ~ ':' , ;:
. 1~1371 : . .
- .. . .... . .... tr'C?. phases: collating marks vyith candidate names, a,nd producing the ranking. ..
~

-. . .' . EDWARDS ' . 1013B . ,.


. ..;,. . . ': : -:: ...
~ . . .:,,...Hence
. . .
. .... . :: ' ," .. " "'; . ~ .' -: ' .: ,
, . ' . .' .' ... +. ,, : :!' --: . .. . : .. ' '\::~: ;.,.: ~- ... . . \ve define' .. : . ..
' . The .second list, produced by .the marker for th~ examination, consists of an "'
.
classlist . =
:

ordered llst of candidate identificati.on numben; at14 the inarks. For exan)ple, rank collate
'. . ' ..
.. ... . ..
'
~
'Fhetypes ofth~ subsidiarY 1\ih~tions arc
-: ' '

' .
0 ., ' ' '.

. ., . . J: .." . .
101369 . 62~ ' . .., ....
.-
'
...- ' ... ..
'!' 101370 .: ' _75 . . .: : . .
.-. '. collate .:: ' 'i Code.s,lvrdrld)
,.. .... [(Name, Mark)]. . . ".
. 101371 ,, ,. 62 . " . ' . . .. ; .: ~-
... ...... '.
. . [( Name;Ma~~)] - Ranks
. : .. - 1013'72 :
,
. 30. .. . ...
.;. "
rank ::
. . . ~ .. ;
'
.' . 101373 . . 50 We will deal with eac}jof thes.e functions separately.
- .:

:
. '
.
.. .. .
. .' ' ' \ '
""!.
'
.. .5.2 I Producing a class list
'
...:. ,:,. . .s.j Examples 14S
. . 144 ;- ~,._.

.. . ... ._...-..,.._ . ..
... . . . ... ... : .. =.
'
.. . . ..Now r~c<YI the law.- . .
: 5.2.1 - Collating
. : .. : '
.: .:. . - . ." r. ...- . . ... .' .
.
In the construction of collate we can assllille that the list of codes is in al-' ..c~oss ({,g)
..
: cro.ss ( h; k) . ~. . c;oss
.
<'r .. h; g . k) .
pl:iabetical order of Name.and the list of marks is in nume(ica]:'gr.der of Iden.
. proved;.in Section 2.4. 'Using this law, we obtain
Furthermore, nq two ~anclidates have rhe same name or th.~~ s~me identifica- ' ' . . ' '
,

tion .number, arid the two lists have equal length. Theresult: hasto be a list in cross (map {st, map snd ) cross (sortby iden, id)
alphabetical order of Name. -~ = cross (map {st sortby iden, map snd)
'! ; There is one fairly obvious way to construct coliate: sorr the first list by iden- ..
: . Putting these two fac~s together, we obtain
j I tification numbers, zip with the second list, remove the identification nunibers,
H and sort the result by candidate name. Here is the definirion:tvh.ich is a faithful


4'
col/are .;... sortby name. zipp : cross (map {st . sortby iden, map snd)
\ transcription of the previous sentence:
r-
.. collate - sorcby name remove zipp cross (sortby iden, id) 5.2.2 Computing rank
!.
where name (xn, xm) = xn
..f Now let us mrn to the second problem, that of compt1ting rank. What, precisely,
. ..
.... ..
iden (xn, xi) - .. - xi .. ' 1

does it mean to say ~hat <r cand.idate .A has ~<mk n? We might ans\vcr that it
'

Recall from Section 4.4 that zipp is the noni:urr ied version of'zip'. The func ti.Of! .m<;ans that A comes "irl position n (counting frorn l ) in the list .of candidates
remove is defined by . . . ' . in descending order of mark, but that is not quite co~-rect. ~wo can~dates .can
. . :have the 'same marks, and therefore the saine r'ank, but they cannot both be in

-
remove [((ex.$), (/3, y))) - [(ex, ;y)) ~he same position. The right answer is that A has rank n if and only if there .
.
... iire exactly (n - 1) candidates wit)l higher marks. pne way of defining r~nk is
~-
;.
~;remove = map (cross (fsc 0 snd )) . .
. .. . . 'ihere'fore to. count, for each candidate, the m1rhbcr 'of candidates with better
.. .. . ...... .. ..
The function sortby has type ; ,.
marks:
. .. ..
.. . .-

'' sortby :: Orcl {5 => (ex- /3) - [ex] - (ex]. . . .. . ..


rank .. [(Name, Ma rk)] :- RankS ,

= .map (s~ore xs) xs . :


' '
ran~xs
Th~ specification -of sortby fxs is that it remrns a permutati6n ~s ~fxs satisfying score xs (xn, xm) = (xn. xm,l .+ leng'th (filter (beats xm) .xs))
.
' . ... . .
.~
,.
beats xm <Y.~. ym) = xm < ym ...
. . . and[{x~{yl (x,y)--zipys(r(lilys ).] ....:(;, -' ,: .. . ... . . rr.ovided.the class.list is reasonably small, exf)miners .d.o tend to use exactly this
-. ... . . .. '. ~-::,.; )i~ .:.. -
1
.. . J: :~-:>:- .. .
I

-. .. . - .m ethod for compuring rank. It is easy tosee that computing score takes about
r- ,.
:- :m
.. . _pli,rtitular, the
funcrion sortby'
. . id
. . . ... ,, .......... .We will
sor~s a list into asccnd'i(l'g'"Qtder.
givea defi.riition of sorrby at the 'end of the section. For nm:v:~ve:3lnention only
- . ;t.steps on a list of size n, so computing the ranks of all candidates takes about
. n'2 steps. Ttiis is fine for small n, but' class~s are getting bigger these days; in
m.
I

that, assuming f takes constan~t tirrie, sort bY. f can be i:inp_line1l:l:ed to run. ~Y case,.mosr examln!!rS can.use cmnputers to hdp them, so we should not
'.
time p'roportional to n log n steps on aH!it iength"n: . : :~. of .z::. be restricted. to a method that is easy to perform only by hand.
The program for collate can be written in an alternati~~~to.r:~n. Recall the . The problem of computing rank would be a lor easier if the marks were in
n'aturality condition . ..
... . . descending order. We ~o uld then assign ranks in a single paS1i. through t.he list.
This suggests redefining rank by
map. (cross({~ g)) . zipp -. zipp . cross(map ma}.ffJ) .... ,
..
, '

r. I '" .-r

.
'

.. .' :.
.. . . ":.. .. rank = . sortby na'me . assign . reverse' .' sortby mark
' .
discussed in Section 4.4. Using.' this lav.i, we obtain
, .
.
~-

. ,
.. where mark (xn, xm) . -== xm
.. ~ .:remove zipp = zipp . cross (map {st. map snd) name (xn, xm,-xr) = xn

.. . ,:-

I '
.,..
~ 't + '

. . : 146
. " .. ~~: ..
.. ..') / Examples 5.2 I Producing a clas_s. li$t ::-::- ..
:: ~~... .
.. -.. .
.. :: .,
- ' I "' , ' . , "~ : .::: ..::...... : ;..... ...: . ...::~:. . .....
To define assign we can attach an inltial.rank of n to.the .~:lthc~did~te (c~unting. . 5.2.3 Prip.ting. the d~.ss list .... ....
from 1), and then reduce itif a candidate has the same mark as the immedi'a~ely
preceding candidate. The rank is reduced to that of the preceding candidate. The implementation of display :: Ranks - String is straightforward as we are
This method requires us to. trayerse the li~t from left to right. The follovving not 'required to do anything sophisticated. The simplest method is to build a
implementation of assign uses the function scanl.l. Recall from Section 4,5 that list ofthe lines of the output ~md then .flatten the result to a single string:

scqnll (Gl) [xl,x2:, x3] - [xl,xl m x2, (xl Gl x2) m x3] display [(Name, lvfark, R_ank)] - String
display = unlines (heading:) map line
The definition of assign is
The definition of unlines is similar to concar except that newline characters are
' '

assign . .:: [(Name, J'vlark)] - ~anks "' inserted before concatenating:


assign xs - scanll reduce initialise
unlines [String] -String
( (Name, 1'-'Iark)] - Ranks
initialise .. unlines - (oTdrl join where join xs ys = xs * . -... * ys
initialise xs zipWith mklriple xs [ 1 .. ]
The Wing heading and the'function lin.e depend on how many columns should
. .. . .' .
. .. :
wh'e re mktriple ( (xn, ~m), xr) .= (xn, xm, xr)
. be allocat~d tb thenames ofcand.iclates; the length of the identification num-
bel:S, and thesize Pf the' marks in decimal notation. For concretehes~fwe take
' . ' . . ,. . ','
' . . ~-

The fw1ction reduceis defined by .'


. . . : . . . . .
heading . ., '.. "
..,... ,, /justify 12 ."Name" * rjusti(y 4 "Mark" H: rjus!ify .6 "Rank" ;
line (xn, xm, xr) .
#:. 1justi{},' \v ;xr) .
' :. .. .. . .
4 (shoiv xni) * rjustify 6 (sho.
' ' .
. Ea<;h,qmdidate th_e~e[ore gets th~ ;>arne rank as atiy previous candidate.,vith the . '= i}ustify 12 xn
. . .. . .. .
same .inark, or the rank initi<,llly assigned if there is no such previous candidate . . ' ' ' ' I ' '
. . ... .~

The functions .lJJ.l~ti(y and "rjust_i(y are defined as follows:


. It 'is .cle<,lr..that, on an }nput 9f fengtli ~. th~ ri.mctio~ assign takes' time propor7
tional to n..T~1e result is a program for rank that take~ about the t~ne requi+ed . :. ljustify;rjusli{y ..;; ; Ini - S!ring - String .. ' .
.. .to carry oU.t two sorting procedures. As we mer.lt;oned aboye, the implem~nt-. ' 'ljusriiJiri Xs.. .. == x.S' ; :sp~ces n - iength xs) (
. . ; ation of Sqrtby. takes time proportional to n log n on .a list oflength n, so the
. '. reVised definition of rank can to a big saving. . . . '. . . ieaci rjJ1S(i{y 1;1 ?.<S . -. spaces (n- length xs) * xs . ., .-
At this point, ,.;e have 'bbtairied,the folloWing det'iriition of class list;:
' ' . . .. ' '

In. particular, ijustify n Xs 1s thestring xs padded with extra spaces on the right
. to make_a string C?f total length n..The definition of spaces',is lefras:a41exercise.
'soriby name . as~ign .'reverse . :{ .. . ..
..
.. : . cltissli~t
' . ..,._ . :. .
=
....
. ..
.~ ' : ~, . . .. .' ..
,, '

. , .. ... : . .
o; ' ! ' ' , . , ,_,.,

sortby_rrlark sortby 11ame' zipp


' . . ." ' . I : . ' ~ .. ' ' .
, ' ', , .,. : ' ' o \ ' ' ' ' ' ' H ' o, ''
. '
. . ... ..:; , . ..
.. .:. ,.
s.2.4
'" ~ .. '
t' ' .. . . - . ' ' . .. . . . . !-
' . cross (niap {sr sor.tby iden, map snii) . .
.. '. ' ,. . '
sorting
.. 0 -

> : t : ':

'
. ..
. ' . .. ' ( ' ' ' ' ) ' '
.. . '.
...
'~ ' I '

It remairis to~plement.ri1e f~eti.oii sortby..We \vill give two linpie111eutatio~s


'
. The two deJinitions of nam~ are 'slightly diff~rent (~e~ above), which is wi1y the
...

second o~~urrence is decorated~th a prime: But Jt is.ea~y to.see.that . one is.simple and the oth~r is effiCient.
. ..
Thesiffiple rneWoq_Is.t<;> ,in~erF.~l~!~ents th~ list o ne by one in,the co~T~ct of
Sot:tby { ~O,rtby g =.. sortby { .. ...
-' . . .. order:. '. -.:; . .. .
>'
..
_;. ' I ' ' ..
I ' '' ' I '
.
., ;.. .'.In bthe~ ~orcis; there is' no point.i~ sorting the same.lis{ tWice: Hen~~ the term sortby , :: ( Ord ~r e< :.... {3) - [ex] - [ e< J
.
:;(
sorlby ,name' in the above expression for classlist is rcdwJdant. sorlby I - {oldr {irisercby f) [ ]
. .
' . ... M
.. . .
' ,,

.' ... ..
.. .
~ . . .. ,;,. . . .
. .
,,
~. . -
o..~ ~ -~
:.52} Producing aclass list
l " . - ...

148 . .. ... , . , >; 4-=~-- -~ .: 5-/ ExCl!llpies 149


. . ~.' ~;~_:.;:;: ~~-;1..~~: ..;. < .: .. ~: .:. . . .
. .. .
. . . . . . ..... J. '

.Ai'weil as being a good illustration of a ~orripositional style of programming,


'

insercby . (Ord /3) "'> (a -: /3) -:- a -: . l.0l:;J~J,..,.... :. . ~.. '


insertby { x - insert. span.test ,.. :. ,__ .....~~.:::.- ' _.. ' - the problem of producing a class list also demonstrates the importance of being
i
I:
r. where insert (xs, ys) - xs * [x 1 # ys able m sort a list efficiently. The complete programis dominated by the time to
'i '
testy - ({ y < f x) sort various lists. If there are n candidates; then the class list can be produced
I .. '
in time proportional to n log n steps. The naive method 'that examiners do by
The function span can be defined by hand can take time proportional to n2 'steps.
.
span .. (IX- Boo/)- [a]- ([IX]. [a])
Exerdses .
.~I I .
span p xs - ( takeWilile p xs,.drop
. . While
. . p xs) .. . '
.
'." .. '
.
"' .

'
I' :.I The functions take While and drop While were considered in Exercise 4.3.7. The 5.2.1 In the list of candidate-identification pairs where was the assumption
l,. . way to write a more efficient program for span is discussed In Chapter 7. used .that the list was sorted 'in alphabetical order?
The problem \yith the above mer hod of sorting is that it can take r.ime propor-
jl
!
i 5.2.2 Assume that sortby f takes at most en log n steps on a list of length n,
r. tional to n2 srep~ on a list of length n. A more efl'icien method for computing
sortby is to use a divide and conquer str:ategy: if the list has length at most one, and that mergeby f takes at niost en steps when the result-is a listoflength n.
.. Prove that sortby f' takes at most 2cn log(2n) on a list of length 2 n.
-th.e n it.is already.sorted; otherwise, divide it iitto two equal h~lves, recursively
sort each lialf, a~d then merge the two sorted halves 'iogethei~ -This idea leads
I
It'
,,I' . 5.2.3 ..Give an alternative (~hough not equivalent) definition of divide that makes
to the following algorithm: -' ' use of thestandard functiop splitAr defined iri.Section 4.2. The dehnitiqn of
-- ..
. .
.... . . divide given in the re;xt makes one traversal of the list. Does yours? ..
sortby f [] = (] .. .'
;>~ sort by f[x] - [ X] . ..
_ .:, '
4_. : . . , . 5.2:4 The equ[uion reverse. zipp'= ZiPP :.cross (reverse, reverse) holds on pairs
sortby f (x: y: xs) = . mergebyf(divid~ (X: Y: XS)) of lis'ts of equal length. Use tllis fac t, together wi~h
. . ~ ......
.The function divide allocates each element of the list to one-..of.......
two lists in strict reverse ..map f . = map t' : reverse
alternation: - ..
'to re\vr)te the defl.nltioi1 of d~sslist. : .
divide [X]~ ([IX], [IX))

.
divide "" {oldr allocate([],.[]) where aJioca(e X .(ys, z) = (zs, X:. ys) 5.2.5 It could fairly be argued that the function sortby is not as use.t'ti.l as a
more general function sortwichwith tyPe. .'.
For an alternative definition of divide, see Exercise 5.2.3. . ...
the f~nction mergeby is 'ctefined as foilows: .. .. . . - . ..... ..
...... . . : .\ . . . sortwith .. (IX- iX- Boo/) - [IX] .:..[a)
. . . .
' "'
... ~ -,

, . me:.gepy ...... ,. .. .Ord f3


The.~pecification of somvith'comppre x.s is ..thai: it remrns a per'rimtation ys of
'
::;. (IX - /3) - .([a], (a] ) :-:: ['IX] : .: :.:
merg_ebyf([],y~) - .ys . . .-,.,<:~;~--.: ~ ?._
. ::,.~.: .-~ :
.. r~ergeby f (;c Xs, [}) =
..... xs satisfying ..
. I!'
'
X: XS. ... . -~-. ~ !::.....
. \
-.
: ~ j

and [compar-exy

(x,y) .::. zip ys(tail ys)]


: '
mergeby f (x : xs, y: ys) ... -~ :::,:.--:.~. '
i : 1 (xsf'y: = x:mergeby{(xs,y:ys) ~ ~~write the class list algorithm using sortwiih. Show why there is no need to
-- - . . .
reverse
r otherwise = y: mergeby f (x: xs,ysr ;;; . . .lists \Vith the
. new algorithm.'
- l- ' "' .~
..

Assun1ing / takes ~onstatn time, this program for sortby {;takes rirhe propor- 5.2.6 The examination might have been for ah optional cow-sc, so some can-
,.
I n
.tiom~l to log n .steps on a list of length 11. We will prove-thts fa.ct in Chapter 7. diclares.\.'ill
. . not appear on the marks list. How would you tackle th.is.rcfinement
.
... . of the problem?
.. -, .
I '

'
'

,,

150 .
.
..
:-
- . : . 5/ Examples .' 5.3 / Arbitrary-pr
.
ecision
.. arithmetic , ;
-
' .
151
' ... ...
. ' . .'
- .- .-. . .
. -
' . '

'
. ' . , ' ': ' > ,. ; " ._. - ' . -
_
., " , ' . . . . .. .... ...
'
.; '
-,
. '
' 5.3 . .. .. , .. .
'

Arbitrary~preci.sion . aritbmetic ..
' .. '
.
This choice supposes.that a}lrtumbers up to 108 lie within the permitted range
.. ' . .. ' of limited-pre cision arithmetic. The quantity baseSize is needed for printing
.
The aim of this section is to show how arbitrary-p recision arithmetic, the arith- numerals. To illustrate the choice of base, observe that
.I ' .I
.. .:.~ '
metic oflnteger, can be implement
. . .
ed in terms of arithmetic on limited-pre cision ..
integers, the arit!unetic of Int. The full installation of a new class of integral [1, 2345, 89] represents 123450089
': .
numbers in Haskell is a significant task, sowe will go only part of the way . .
t
. .
[1,2,3] represents 100020003
.. ....... ,, '
An arbitrary-p recision integer will be represente d as a list of digits in some
- -
. I .. . . given base base. Each digit d will lie in the range 0 < d < base, except possibly
' These representa tions are _n ot unique, since an aroitrary number of leading
. .

r.
'i' .. ' for the first one, which will lie in the range -1 < d < base: An initial digit of zeros can be added to a numeral without changing its value.
' .. ..' ... -,-1 will signify a negative integer. The representa tion of negativ.~ numbers is
r- .. '
. .. ;.
. ' . .We can normalise a numeral by applying a function norm to strip off nonsig-
considered later on; for the moment, asswne that arbitrary-p recision integers
nificant zeros .. In particular, the number 0 will be represente d by the empty hst.
'
'
i .
are nonnegativ e.
. ' '
. '
'
!
All numerals will be built using no nil, so we can suppose in the definition of
The declaration

.. ' .
' .
. ' ' . the operations to come that numeral arguments are in normal form. It will be
-.
1 . I :

newtype Arblnt - Norm [Digit] convenient, however, to define norm as a more general function, One that con-
' ' ..
. ... type Digit . - 1nt verts an arbitrary list of integers, rather than just a list of digits, mto a numer,al. .
:. .. .
....
'

'... ,.'
Thus, the typeassign ed to 'nann ~lfbe norm:: [I~Jt] -Arblnt. . . . . .
. . . . .
introduces Arbint as a new type ratherthan a type synonynib ecause we are.go-

,. ..'. ,..
' ' ~

To specify norm, define


'

"-- '
'
.: ,,
.: .';
;
.
. ing to install Arblnt as a member of the class Num, and so will need instances of
. . '
. ''......
..' . ,' Show andOrd that are different from the generic instantiatio ns of these cla~ses convert :: . [Int] - Integer
' ....
'. .'' for lists. For simplicity, elements of Arbint will be referred to.as numerals. ' .
. convert = fold/ (EI:l) 0 where n il1 d =base x n + d
'
. ' . ' " '.
(: . '
The conversion function . ..
-~ ... . ' .. . .., . '

Then norm is specified by two conditions . Firstly, .


digits
. .
:: Arblnt ~[Digit]
.. . . ,. , ; -
.

digits (Norm xs) - xs . .. . -... '

'

.
convert . digits . norm . -= convert

returns the digits of a numeral. Numerals will be represente d with the most -. ' .. . ' .

.

i
! :- ' ..
; :: signifi<:eiht digit first. This representa tion is the one used with ordinary decim- ' '
This condition states that nornidoes riot change the value of the represente d
. als and, in the absence of a compelling reason to th~ contrary, is the sensible integer. Secondly, norm should.ret urn a value Norm xs, where xs is a list of
I ."
I'' ...
' . ''

<
~- .
one to adbpt for our arithmetic package. Thus, an integer xis represente d by
'
~~ i: -I
a:-'
' .,
digits x in the range 0 x < base, ~xcept possibly for the first digit, which will
i-' _,- ' ;I '
,.~ . ,
1.. :_ ,
. ,: a sequence. .
.
[xo, xi, ... , Xn-d of digits, where be in the range - 1 < x < base.
:1;:-
I t";<.l

To implement norm, we process the list of integers from right to left, re-
,i

.. x..., Xo x basen-i x base""" x base0


I
,.,.. ' .'
' <.:... -' +Xi 2 + : + Xn-1 . . :
' , i i
' .: . .
.
- .
-'


' '
'
.. . ' .
. ' . ducing each digit modulo base-after adding in a carry_from the preVious step.
The initial carry is .0. Forexample
'

I I' .
':' ;- . '
The m~or c:riterion influencing_ the choice of base is that we want Q.igit -by-digit . , .supposing base= 10, the list [11, 9, .16] is
' . .- . ..
. normalised by beginningwith a carry 0, reducing 16 to the digit 6 and a carry
\ t
,..- ' :
....-- .
.- .,. '
multiplica tions to be performed by the built-in multiplicat ion provided by Int
... 'l .
Without qanger of going out of range. On the other hand, we would like our of 1, reducing 9 + l to the digit 0 and a carry of 1, reducing 11 + 1 to the digit 2
digits to be reasonably large in order to keep the representa tion of numerals and a carry of 1, 31ld fually a&Ihtg ill this carry to give the normalised number
reasonably small. For concretene ss, we will take . [1, 2, 0, 6].
I " ' ,
'
''.. .. .
' '
....
. ..
. If the final carry i: is n6t ill the -required range - 1 < c < base, then it has to
.
. '.' .. . .
base, baseSize :: Int . .. .
'
. '.
. .be. processed further. For example, again supposing base= 10 the list [9S7] is
~ ...
.. .
~ . .. base . . . - 10000 ' .- - ..
'' normalised to [ 7] with a carry Of 913. This carry is not in the required rang', so
.
.' :... .
'

- 4
.' .

baseSize it isreduced to the digit 8 and another carry of 9 .


'

... .

..
. '. I
' .. '
. '' .'
' . .- ..
'' ..
,.-.. ';'
..
. .... .
'

1
I
152 ,
... . . ...
. r..,_ ...,. .... . _ . .".' .s [ Examples 5:3 I Arbitrary-precision aritluneric '153
. ..
, .... .. . .. : ........, . .

.. ,.~.. ~.
... :. ~i ': -:r;_,.;i-:....,..f. .
J ~"
. . .
The compa risonf unctions can now b e'inroducedoy :
The pro~e'ss cim be descri bed in terms_of /oldr. P.~fiQ.~, .'. \:~ > .;
,,,
'
I

. .. .'"'._ . -. :'"' ......- .


...,; -- instance Eq Arbln t .wh ere ..
I
type Carry - Int .
(==) . =. m ;mslcue <==)
!
..
Digit - (Carry ,'[Digi t]) ~ (Carry , [Digit] ) ' '
I carry ..
'I
'! ca rry x (c, xs) - ( (x +c) div ba.ie, (x + c) mOd base: xs) instan ce Ord Arbln t where
( <) = transla te ( <:)
Then norm is define d by
I

I norm :: [lnt] - Arblnt . cranslate :: ([Digit] - [Digit] -c Boo/) - (A rblnt - A rbfnt - Boo!}
,j
transla te op x y . = op.xs ys .
' ' '
norm = Norm dropWhile (== 0) addCar:>' (oldr carry (0, ( ])
where (xs , ys) = align (digits x, digits y)
The tenn (0, [ ]) ensure s that normalisation starts off with an initial carry of 0,
the term addCa rry adds in the final carry as one or more new most significant
The test for ze~o c~n a,iso be implem ented directly by
digits, and dropWhile(== 0) removes leadin g zeros. The definition of dropWh ile
was given in Exercise 4.3.7. The final list of digits is conve rted to a numer al by islero .. Arbln t - Boo/
applyi ng the constr uctor Norm. The defini. tion of addCa .. ..rry is :.; ...
. . "' ... ' ~
isieio - null digits
(Cany , (Digit ]) - [Dig!t ] . .,
c:
addCa rry ..
This uses the assum ption that the argum ent is a numer al in normal form.
= if ( -1 ;!;; c) A (c <base) then
addCa rry (c, x.s) ,YS

else addCa rry ( ~ div base, riiodb aie : x.s)


.:-:-~: ;. .. .
c
. . . :..
.. ,_ . . . 5.3.2 Additi on. and
. '
subtra ction
. We will leave it as an exercise to show that addCa rry tel'min ates and that norm
! satisfi es the first condi'tion of its specification. It is clear by.con srructi on that . The func tions ( +) and (- ) for 'doing arbitrary-precision additi on and sub mic-
tion are easily defined. We can align the two lists of digits, do the operat ion
.l
norm ren~ns a lis t of digits in the requir ed range.
t digit by digit, and then norma'lise the result. for example , suppo se we want
to add the numb ers (7, 3, 7] and [4, 6, 9], where, tempo rarily, we suppo.se that
.
I

5.3.1 Comp arison oper ations


base = 10. The digit-by-digit additio n of these numbe rs is (11, 9, 16] and, as
Given ~ur choice of rep~esentation, which has. the mq~t :sig,niD<:~t digit first, .
I we saw above, the norma lised result is [ l , 2, 0, 6]. .
compa rison operat ions on numer als can be based on the standa rd lexicograph ic . Th~ addit1on arid. subtraction 'opera tions can be introd uced With their con-
orderm g on lists. We first have to align the two lists by addip g nbn~ignificant ven tional names , by declaring Arblnt as an instan ce of the class Num:
...I zeros to the shorter. one. .For example, 57 is les~ thari 1?.6 bec,gQse 0.?.7 is .
l?Y.: , . instance Num Arbin t where .
';,,
, .... \
'
'' I
lexicographi. cally less than 126. We can align two lists .,9.f. digits
. .. . .
norm (zippWfih.{+) (align (digits~. dig irs y). })
. ~ . ~ ~
.
x +y .-
align: : ((Digit], (Digit]) - ((Digit], [ Digit] ) .. . . .....~ -~ ~ .... '
i.
.
x- y = norm (zippWith (-) (align (digits x, digits y).}}
alig~ (xs, ys} .. ' ' .. . ' .
xxy =
n>0 - (replicate n 0 H- xs, ys) , .......
negat ex = ...
.. -
ns O = , plicate (.- n)O* YS) - --
(xsre
where n = length ys - length xs
.. . The definition or (X ) and negate is consid ered later on. Rccall .that zippWith is
. i ..
the nonclllTied versio n of zipWirh. Thety pe class Num has both Eq and Show
The functi on replicate can be define d by . as a superc lass, so the install ation of Arblnt .as a Num type is incomplete until
:: Inc - ex- [ex] A rb!nt is declar ed as an instan ce of the Show Class. Tlus task is post})oned to
=-.,replicate . .
the end of the section.
... rep/icale n X = (xlk -[l..n ]]
,.. ' ... -
154
:,
: 5 l ~xamples -5.3 j. Al'bitraryprecisioll aricllm.eli c ,. . 155
.. . . . ... .
The .intere~~g pqint about subtract ion is what happe1,1.s when the se~on4
+-- .;

multi :: 'Arblnt - .Oigit - Arblnt ,


argumen t is greater than the first, so the answer is a .negative 'number . For mult.l x d =:' norlj'i (map(x d) (digits x)) .
example, .agairi supposin g base= 10, subtracti ng [3, 7, S] froin [1; 0, 6] gives
the 4st [ -2, -7,1) after digitbydigit subtracti on, and normalis atiqn yields The function rrJUllJ multiJ2Jies a numeral by a single digit To do the shifting
Nonn
- [ -1, 7, 3, 1].. These digits represen t the number and adding, let spfus be.dd'ine d by
.... - . .
- lxlo3 +7x l0 2 +3x10 1 +1xl0o = .-269 sph1s ..
.'
Arblnt - Arblnt - Arblnt
splusxy = shiftx'+ y
The answer is correct since 106- 375 = -269. After normalis ation, ancgative
number is indicated by a leading digit of -1. The absolute value ot'"a ~egative
mimbcr can be obtaiJ:led by negating all the ~igits in the represen tation and shift Arblnt - Arblnt
normalising. It follows that we can define the predicat e negative, which tests ,shift (Norm xs) = ,if nu./l xs then Norm [] else Norm (xs H [OJ)
whether the result of subtracti on is negative, and the function negate for neg . . . .. . ...
ating a number by The. definition of shift does not use nor:m, but i( xs is nonp.alised and nonempt y,
*
then so is xs [0~. Now we can define . ,
negative Arblnt - Boo/' . .
negative (Norm xs) - not (null~) "(head xs < 0) .' . .
x x. y
......
= (oldl splus (Norm [}) (sums x y)

The reader should consider why.fold l is used here ins tead of {oldr or {oldll.
negate
. .. Arblnt ,- Arblnt
negate == norm map neg digits where neg x = -x
~ ~ .~- 5.3.4 Division .- : ..
This method of representing negative numbers is called signed-c ompleme nt ...,
notation. Signed-complement repre$en tation is convefuent both for arithmet ic Finally, we turn to the diyts~on o( ol_le ~nteger by another. As evcly schoolch ild
. and compari son operation$, since no special measure s have to be taken for neg knows, division is the hardest of the arithme.lic operatio ns to ~et ~ight; not only
ati~e argumen ts an<;!' results. Weleave.the pr.oof that tile comparis on operatio ns is the algorithm complica~ed .. it also involves a certain amount of guesswork.
work without modification for negative numbers as an .exercise. In fact, the following algorithm for division is p~obab\y the mos~ complicated
Another represen tation of negative numbers is the one normally used .witl{': .... progr~ ii1 this book. We .will define division only for nonnega tive integers, ,).
decimal calculations'' done by hand. Tllis is called signed-magnitude no.ta.tiori. . leavi.r)g the extensio n to negative integers as an exe_rcisc. Our aim is to define a
Here, a number is c).e,noted by its absolute vail:ie, together with an indicqti_o n of fw1ction .. !.
whether the number'is positive or negative. Arithmetic with signeclmagnitwie
, ..
representat1o~_requires case analy~es on the sign of the number. : . .. .quotrem .. Arblnt- Arbint - (Arbint, Arblnt)
. .. :
.' . ~ . i

.. .
'. for returnin g the quotient and remaind er of the division of a nonnegative nu !
i '

5.3.3 Multipli cation . .. by a positive numeral... We w.Ul n~>t. however, install Arblnt as an instance
'

-.
r " '

. '. ;mer~.
' /

. .
... ~- . : : :- #
:~- # of the type class Integr:aCso .the us~ of the names div and modare denied
. ... Next, w~. dejlne (x) over the wpe Arblnt. The straightf orward definitio n is a. us. Haskell has a hierarch y of type classes above Integral, including Realand
transiatiCni of the .#hool book method, whe~cby the multiplicand,is m~tlqpliec\ Et1um, and we do not \\'.a~1t ;to tomp,li~~tc matters by going into a discussi on of
... . by each ~igH: of the multfplier and
the partial sums are added together ; shifting_ this hierarchy.
appropriately: Tpe"list of partial sums, in de(reasi ng order of-signif1cance, is Before tackling the fulf algorithm , let us consider a simpler problem first,
~eturncd tiy the func'tion sums, where ., namely to compute the quotient and remainder when a nwneral is divided by
. . . .
. .' . a single digit The correspo nding fimc~ion is
sums: :: Arbint- Arbinc - [Arblrlt] .. ... '

' . . ' ' , '


sumsxy = map (multi x) (digits y). quo{rem l :: Arb!nt - Digic - (Arblnt, Digit)
-.
. ..
156 ... . :. . ~ ; . ' ..~........ 5 I fxarvples . 5.3J Arbitraty-precision arithmetic

-
+

. . . . ' ' _.,._.,... .. t . - .. . ' . ' ' "' ' "' .:;: ..
. .... .~. . .., , , '
. ,

For example, considei d.i\fiding 5'hno 369. The sr~ps or'the proc;;ss are leamed The remaining function step has type . ' . ' . . .
- ~
by rote in childhood: we divide 5 into 3 giving a quotient p.(:..QUI)I;la remainder
:
'.
of 3; we then divide 5 in0 36 giving a quotient of 7 and a remainch{r of 1; finally, . step :; Arblnt - :(Digit, Arbln.t) -;<Digit--{Digit, Arblnt)
we divide 5 into 19 to give a quotient of 3 and a final remainder of 4. The final Ev.aluation of stepy (q, r) d involves dividing the .numeral y into the nUmeral
. ~-
quotient is 073. . , .. ~- = splusl r d, where
In general,
. suppose X = Norm [~. XJ. : . Xtl-1] is the..numeraf, and d the ~- ...
digit. The (unnormalised) digits [q0 , q1 , . .. , qn- d .of the quotieli(can be com- . splusl :: A rblnt - Digit - Arblnt
.I;.
puted by setting an initial remainder r0 = 0 and evaluaring, for 0 5 i < n, . splusl r d =: Norm (digitsr [d]) *
- (base x r; + x;) div d ...
.. .. ' :, ... ' ... ~,. :. : ', 8?'::;~~' -.::.~.:.:~ ~! .."';.r:. ; : '
The function splusl is simihir to the function splus used in the definition of
, .

multiplication e.xcept for the change in:type. In the algoritrun for step we ~11
need tO distinguish three cases, depending On the number of digits in X andy,
The single-digit' remainder is r 11 We can ilnplement this scheme usin?: the func- so ~ve define . ,. .
tion scanT. Recall that . .-
rn = length (digits x) (= length( digits r) + 1)
I' .. . . ..
... : . .~ . . ,... . . . . . .. . . ..
[e. eGl xo. (e.ED xol E!J x~o ... ] .
. ..
n. , .= , )engt,h .(dlgJts_:y,):.:>,.:::.:.,;:: '' .:... .
' \ '
scanl (Gl) e [xo, XJ, .. ] =
.... . . . ' ... ~ : :::;:~:~:.,~;. ~ ~:,.:,:<:::..>.;).:~.':). ';. .':.\:..;. . . . ., ; . . ' : '' . . -: ..
We can defi.r)e . ... . .. Note thar'm:5 n+ l.siiic.e r:,l:i~inithere:nia.irider f:roll) the previous step, is less
than y and so caimot b~ve n~ore' cUgits thany. The definition of step is
quotreml .. A'rblnt - Digit - (Arblnt, Digit)
,quotreml x d = finishl (scanl(stepl d)_ (0, 0) ,(qi~it,~.) t.
. ' . . . - -~
, ..: stepy (q,r) d
m<n = astepxy
stepl .. Digit - (Digit, Digit) - Digit.- (Digit, Digit) m :: n - bstep x y
stepl d (q, r) x = (y div d,y mod d) where y = base x r + x = ,. .
. .... - . othenvise cstep x y
=
~

.. where 11'!
' - . . .. . ..:.
length.(digits r)
... . : . ' . . +l
[(Digit, Digit)] - (Arblnt ,Digit) .... : ,.,,:"'-:":".. ' ;i>': .-~ ~; 'liin'gtlf( digits'y)
.'~
finishl ..
finishl qrs - (norm (map (.sc qrs), snd (last qrs)) )< = splusl r d
. ; -. -.
' ' ... '. .. "
... ,
. '
The function finishl finishes off the computation by normali~ing the qtiotient The three cases, astep, bstep, and cstep, are in increasing order of difficulty.
.. . digits and extracting the.final remainder. .. . . . ' ' ~ Th~ (lefinition of astep is easy: if m < n, then the new quotient is 0 and the new
..... ~ ~.
For the full algorithm we will start with exactly the-sam~St-rucni}.:e;: Later on remainder is x. Hence
' . . .
. we will need to revise it slightly. }.fence .we take ..
.. , ,
- ' ' ' .. .. :,. . > . ' '

;o'- : astep ';''~~-' -: ::"<,:A.r[!Into ,7,Ar,bll'it f(Digic,Arblnt) ' ~

quot~em .. Arblnt - ;\rblnt ~: (Arblnc: ;\~b,L~f) - -~:- . astep x y = (0, x)


quotrem xy - finish (scan/ (stepy) (0, Norrri'[']).(digits ~j) Next, consider bstep. If m= n, then the new quotient q ii:Ug~t be any value in .
th,e range 0 ~ q < base. However, we will see that in .the final version of the
... ,1

finish .. [(Digil,Arblnt)]- (Arblnt,Arbint) : , .. algori.thm, it will bea condition on the divisory that y 2:: base/2. Herice there
finish qrs - (norm (map (.sr qrs), snd (last qrs))., - ::. : . can be a quotient of at most 1 and we can define
., ,.,_,. ...
-.
' .
-
The. difference between quotrem and quorrernl is that, in the former, the re-
~

-
bstep .. Arblnt - Ar:blnt - (Digit. Arblnt)
mainder at each step is n<;>t nec:essarily a single digit. Theofilrrctio;ns finish and bstep x y - if negative z then (0, x) else (1, z)
'finishi ditTer only in their types. . where i = x-y
. ' . .... , . ~ .- ...- : -

.I
lSI:!
:s'/ Examples 5.3/ Arbitrary.,pmcisiqn.ariJ/lmetjc . .. 159 '
.. ., ..
Iiios~ Complicated case iS e,step when ;m = n + 1. ._S~ppose X = ~X1 : .: ;" ...
I
. i:he . The function guess)~ defined by .. ' .
andy :..: YiY2 ... y~ are nonnegative nUmerals with xty < base. We would like
. , ..
-
aquick '\yay ofestimating lx/yJ and we can do thls by looking at the first two
' ; ,

. . guess Arblnt - Arblnt - Digit


digits of.x and the first digit of y. For example, with base= 10 and.x = 37'??? -- guess xy = if xO.-;:: yl then base - 1 else ~xo x base-+ xl) divyl
andy = 4???, \ve wollld guess a .quotient of 9 bec~use L37/4J = 9. S~ilarly, where x.O - xs!!O
with x = 27??? and the same y, we would !,'Uess a quotient of 6. On the other xl = xs !! 1
hand, with x = 41??? and the same y we would guess a quotient of 9 , not 10, xs - digits x
.. because 9 isthe maXimum quotient possible. Accordingly, define the guess q
by yl - (digits y) !! o
I
. q - . l(XQ x bpse + xr) /yd
. min (base - 1) . .... That leaves us with the p~oblem of ensuring that the first digit the divisor Y . of
. is at least base/2. We can do this by multiplying both (he dividend x and the
divisor y by d = lbase/ (y1 + 1) j. For a proof of this <).Sserti~n see Exercise 5.3.6.
~

How much can q differ from the true quotient q = lx/ y J? The answer, proved
' ' ' I ' ,

in Exercise 5.3.5, is that provided y 1 ~ base/2 we have q- 2 :S q :S q. In.words, The result o( tllis scaling will
leave the_final rem!}.inder too large, and we will
provided Yr is sufficiently large, the guess q can only overestimate q, and then have to divide it by d at the end of the algorithm. Accordingly, we ,revise tbf!
by at most 2. . earlier definition of _quotrem to read
We Will take care of .the assumption y1 ;:: base/2 in a moment; let us first A.rblnt- Arbl~t ~ .( Arhfnt, Arblnt)
qtwtrem
. see howto deternune whether-q is too large. First of all, by definition of floors,
=
' Lx/yJ q ifand only if ' .. .. . ' qiwtremxy - fi;ish d (scan/ (step y') (0, Norm.l,J) (d.igi~~ x'))
where x' - multl x d :... .
". . "' ;
q X y.:$ ?< < q ~ Y. :!y . y' . - . )r,ru_ltl y i:i '

Next,
. . since
. .q is never
'
an. unde-restimate,
.. we
. ' have
.. . . ' >
.. ;-. ,

.
d = ba.s ediv (head (dif!itSy) +1)
. .
t~
'I
"

,.
x <. lx/yJxy+y_~qxy+y {in ish :: Digit :- ((Digit, Arbfnt)) -
(Arblnt, Arb.int) .
. .. . , . ... finish d qrs = . (norm (map {st qrs), divl (snd (last qrs)) q) .
Hence \-YC obtain. t;hat Lx/yJ = q if and .only .if . ~- X y ..;x. This leads to the
of
J . , '
following implementa~ion cstep: . divl Arblnt .:. Digit - Arb!nt
' . .~
..
div1 ;I( d - fst (quimeml x d)
. cstep :: Arbint - Arb!nt - (Digit, Arb!nt)
# '
.. . .
..
"
cstepxy. ' As we said at the begiruli.~g. 'di~ision is a complicat<;d process; now the reader
.,
::
: : nor( negative rO) : - (q, rO) . 'c~ appreciate why. !
. ' .' -. . . !

. not (negative
.
r1) - (q -d. rl~ . : '
.. :;
'\

, '-othenvise .. - (q- 2, r2) .... . .. 5.3.5 Showing numerals' ..


I

- wh:e re q .:' _: .guess.xy .: '..... ...


' . ..

' rO - X '- multlyq , .


. ' .
. .. .. . 'ti-ie deciaration of Arb!i1t '~5; an instance of Num
is not legitimate in Haskell
:.
. ' : uhle~s we also declare Arblnt to be an instance of the type class Show. In the
rl = .rO+y ..,
discussion of the Show classin Section 2:7 we said that thisinvolve~ defining
r2 ~- rl +y . a: 'function
.,
... . .
..
. ' .
'
..
' ... ... showsP~ec :: Int "'" ()( - String - Stri11g
.. ' . .
The function showsPt-e'c takes an integer as argument to enable the user to
control whether the printed string .is enda.secl ill brackets. It then takes the
.... , .
.. ..
:I

' .. ... .,..,


160 . . '
.. ... .:~ ;._5 I Examples . SA I Printing a calendar
161
'
'
.
.
. .
.
. .. -
. ...-.1. -- -
., .
.. . . -' - ' .. .. . '
buta functiopjrom
-- ~ ~

value to be converted and returns, not a string,


. . _, -r:..
strings to
- - --
5.3.3 There is another way to define norm by using the furicti~n stanr. Recall .
strings. The function showsPrec should satisfy the law that
. ..
showsPrec d x xs * ys == . showsPree d x (xs * ys) . scanr (m) e [Xo,X 1,x2] - (X() ffi (Xl ffi (X2 ffi e)), X1 ffi (X2 ffi e), x2 ffi e, e)

The extra argument ys is called an accumulating parameter and is there for Define ffi by x m ( c, y) = ( (x + c) div base, (x + c) mod base). Hence define norm
efficiency. The reason is explained in Chapter 7. The auxiliary function show using scanr.
'
, '

iii is defined by
. . ' ' ''
t
II 5.3.4 Prove that the comparison operations work correctly when the arguments
:It, i. . are possibly negative decimals.
showsPrec 0 x [ ]
q =l (Xob + xJ) jyJl, so that
' ,. show x == :'
!h
'
'
5.3.5 Let X == XoX1 ... Xn andY == Y1Y2 ... Yn Set ,
'' The argument 0 means that the result is never slirrounded With brackets. ' '

For completeness, we give the folloWing instance declaration of Show. The


qyj:S Xob +X) < ZiYI + Yl .
'
undefined functions are part of the standard Haskell prelude (in fact, showChar
"
. Using only these mequalities, together With two sirrruar ones .'
.
'
'

is a synonym for (:) and showString is a synonym for (*) ).


. - . . . . ' I
'

Ylbn-1 <y < Ylbn- 1 bn- 1 + . -rr


instance Show Arbfnt where ,. .
X()bn + Xlbn-1 :S X< XQbn + Xlbn-1 + bn-1
' '
, .. - ~ -~
''
' ! - '
~I .' '
'
... -.
showsPree k x -~
'

isZero x - showChar '0'



.prove that q- 2 < lx/y J < q + 1 provided that y1 ;>: b/2 . .
negativex - showChar '-' showDigits (digits (negate x)) 5.3.6 Suppose y and b are integers with l :,; y < b. Prove that
' ' . . . . . . . . : - -~.i~

== .
.,
otherwise . !;howDigitS('digits x) .- : : . c. -
lb/2J < ylb/(y +l)J < b . '

- .
- _ . , _ ,~_

showDigits :: [Digit]- String - .String . . . . 5..3.7 Construct a function toArb :: String - Arb!nt that converts a string of
'
showDigits (d: ds) . . - .
. . .. : ' .. .::
-

decimal digits into an element of Arbint.


'
' ',
'i,.
. ' '
" .
= showString (show d) showString(concat(map showDigit ds)) 5;3.8 The d~finition of quotrem given in the text can be tllned in.a number of

--- ways. Inparticular, it is possible toimprove the guess for q- see Knuth (1981} .
. ''
. , . (
....
_ __

showDigit Digit - String . .-., -:: .


-and a number of length calculations can be avoided by using versions of addi '
'
showDigit d - zeros* ds ' .
tion and subtraction that produce ( n + l )-digit results from n-digit arguments.
... where zeros - replicate (baseSize -length ds) '0' Show how to make quotrem more efficient.
.
ds == show d '
..
....-:.... 5.4 . Printing a calendar . .
'

. .
'' -
'

: -
'

All digits except the leading digit have tobe padded With the=eo,rrect number . >
'

'' of 0 characters. - ;: : ,...,



In this section we will construct a program forprinting acalendar. The aini -'
is to design two functions year and month so that, for example, . year 2000
..
.,. -... - - "-

Exercises
. . ...
will produce a complete calendar for the year 2000, and month (1, 2000) Will
'. .. - .. produce ,.
.
' '

5.3.1 The program for add Carry terminates if repeatedly replacmg c by div c . '

. -
base eventually leads to a value c in the range -1 < i:: < base. Pi:o.ve that this is
.

I the case. . .. . .. ..
''
- '

.
' r '' , ," ' '

5.3.2 Prove that convert digits norm =


.
convert. - '

. ..... .. '
'

. ~ -. - -
I,.
'
". ..
....... .
162 5 / Exiimples 5.4 /Printing a.. calendar . .163
' . ... ' . ' I ' . (~ . - . ,;- ;:~ ... . ..
. .
' , . . .: J anuary. 2000 ... . ; :. . . :' . :; .' .. .. by i:n(lexing into a lis~ of'all firs rd.ays for the year:
SuMo Tu. We Th Fr Sa :. -. ... ...... . .: . . . . ...
]:- . .. -., .. fstday .... (Month, Year) - Dayname
2- 3 4 5 6 7 8. {stday (m,y) = ({stdayS.Y) !! (m- 1)
9 10 11 12 13 14 15 . .;; .

16 17 18 )9 20 21 ' 22 fstdays .... Year- [Dayname]


23 24 25 "26 27. 28 29 {stdays = take 12 map (mod 7) mtotals
30 31 . '' . .
mtocals .... Year - [Tnt] .
mtotals y - scan/ (f-) Uanl y) (mlengths y)
The :right way tQ tackle problem~ of thi~ kind is to separate the construction
phase from the printing phase. /\s logically independent tasks, we ca~ consider mlengtbs .... Year- [In(]
how to provide tile necessary information to build an abstract calendar and how . mlengths y - [3l,{eb, 31, 30,31, 30, 31. 31 . 30, 31, 30, 31]
to print it in the required format If we succeed in this separation of concerns, _where feb = if leap y then 29 else' 28
modifications to the program, such as printing the calendar in a different format
or printing only part of the calendar, will be easier to carry out.
. . . leqp Year- Bpol ... . . .
leapy - if y mod 10_0 "".0 th,.en (y mod 400 = 0) else (y.mod 4 = 0)
5.4.1 Building a calendar
The list of first days is o~tained hicomputing ~he accumulated totals of the
The primary purpose of a calendar is to provid.e a suitable presefltatlon of there month lengths, starting at the day on which January 1 falls, reducing th!lse
lationsh,ip_ bet~een day n~e.'>. \lnd dates. Each date is associated,with a unique totals modulo 7 to find 'the day names for the first days of each month, and
day name, so the abstract problem is to determine a ftmction day that takes a finally taking the first 12 values. Note that sca~:~l applied to a list of length 12 ,.
date and returns tb.e correct day name. Since we will need to do aritlunetic on produces a list of length 13; the last value on this 'list will be the day on which
II
day n ames, we will code them as numbers, with Sunday as day 0, Monday as january 1 falls in the following y~ar. t
day 1, and so on. Accordingly,
. we introduce
. the type synonyms. It remains to defindanl. ln the Gregorian calendar, january 1 in the year 1 '
- was a Monday. Hence, in order to.discover janl y, we have to count all tl1e days

type_Date = . (Day, Monti!, Year)
.. in the previous (y - 1) years, ad.d 1 and take the result modulo 7:
type Day = In~ I
type Month - Int jan~ y :: Yeqr - payname
type Year - Int . janl y - (365 X x +xdiv4 -xdiv100 + xdiv400 + 1) mod 7
-
.. where x = y -;- 1 ..
type Ddyname
. . Int ~

.. . .. ., .~ . . . . . .. ~~ . ' ... .. ~ T!1e extra te.~ms a.ccoi.mt for'ie~p years.


. Given a f~c.t.ion f~{iiay :~ ([vfonth, YearJ. .~ pay.n_am~ tha_txetl,lrp~ ~1c n,am~: Of,
..
.' thefirst day .in a month, we
.. . . . .can. defint! day. by_. :.:.. ... . . :- . .~- .' ... ..,,
' '

.... 5.4.2 Pictures


day . Date - Dayname . 0

.....
......

..
is
.. .. ;
day (d, m,y)'. = (fsiday (m,y) +i..:.-1) m~d 7
;

Let us now consider. how to: pictili:e a calendar. The calendar for a year built
.. ... . .. . ~ out of_t~1e c.atendar for i,ndivid\tal \n()J1ths, so the tdea is to b!Jlld pictures. out
In particuiw, day (1 ,m, y) = (stday (m, y). . . Of snialler pictures. For the moment it is best to think of a picture simply
To determine fstday we need to know th.e lengths of the.months and the day as an element of some type Pitture. Ead1 picture ls a rectangular ei1t1ty \.Yith
on which January 1 falls for the given year. The value of (stday is then obtaineQ. a positive-height and width; so there are two primitive functions defined
' . . .. .
on ,.
I
.. 0 ~

. .. . . . ..
1
I '
I
\64 5./ Exanmles
. , ~,

., ~l . . .. ~.A./ P.rinting a calend(lr 165


. ..
' ' I . ' - . '

~ ~ - \ .. .. ~- ,..~-... 2 '

pictures , height and width .. We introduc e two synonyms~ ..


+
.,

: ~ . Using spread we can define a fUnction for turil.iilg a rioflempty string into a
----.
- -
. .# - .

.... picture: ..
type Height - Int .
"'\( -

type Width "' Inc - . . .... - - row .. String - Picture


.,..G I "'' , -row = spread m~p pixel
and \-vrite the types of height and 'width in the form
. .
.. height .. Picture- Height
The function row turns a string into a (1 x n) picture, where n > 0 is the length
of the.'string.
i . Using row
. we can define a.blanl< picl'tll'e of given height and width:
1. width .. Picture - Width . .
. .. blank .. (Height, Width ) - Picture
To start with we will need some atomic pictures. Since our pictures are pictures
blank = stack map ro\v blanks
of text, and the smallest piece of text is a single character, we could get away . ' .
with a single function where blanks (h, w) "" .~eplicate h (replicate w 'u')

Two useful variant.s of stack and spread insert blank picrt..ires between two
pixel :: Char - Picture
picti.iresbefore combililng them:
for converting a single character into a (1 x 1) picture. - .' .,

We can build new pktures out of other ones in a number of ways. Two fairlY.
.srackWith ::. Height~ ([Picture] ] .:. Picture
or
obvious methods are toplace.one picture' above another, one.pict ure,besid e
another. So we introduc'e two combinators
stackWith h = {oldrl (Gl)
where p Gl q = p above (blank (h , widch q) above q)
'

' ' .
..r . . .. .
, .
.. ...
(above), (beside) :: Picture- Picture - Picture ...'
sp~eadWith Width ..:: [[Picture ]] - Picture
. spreadWith w = {oldr_l (Gl)
It is clear what should happen if the widths of two pictures p and q are the
. where p Gl q = p beside (blank (h.eight q, w) beside q)
. .
same: the width of (p above q) will be the' common width, an'Q its height \"'ilt be
the sum of the heights of p and q. If the widths of p and q are
not equal, thep
. .,. .
The function stackWith h stacks ~ list of pictures verticillly ~vith ~ ibter-picture
we have a decision ro make: we can decide to align the thinner picture with
the wider one in sonic way, or simply nor define the value .(p above q). Dual gap of height h; similarly with spreadWith w.
remark s apply to ihe operation (p beside q). Rather rha~!Ua~ this decis{on Given a list of lists of.pictur es we can build one large picture by tilingthem, ''
now, we will wait .to'see whether a 'iogical choice arises dtu:,ingth e course of ~he that is, arranging ti1em as a iectanr,rular array.There are two varianrs:
developm ent. What eve~ we decide, both operators are -associative; it d oesn't .
matter whether we put P above q and then the result above r , or put p above tile [[Picture]] ~Picture

the result of putting q above r.


j

, - ::~~.~ .. : ..

tile = stack map spread
.. ... .:: ... .. ...
Given above ariel bes.ide, we can stack a nonemp ty list ot'-~didres abov~ one .
:

. . . ..
another, or spread a nonemp ty list of pictures beside oneanother:
~ . -
'
. tile With .. (Heigll_c;Wide h) - [[Picture] J - Picture
tileWith (h, w) = stadiWilh h rmip (spreadWith w)
stack, spread . .... [Picture] -'Picture
I

Fin~llly, \\le will need a fun~tion to display a pkture 'ori a tcmunal screen:
stack -
{oldrl (above) '
..
.-- '
' .' .

spread .-. {oldrl (beside) . .. showpic :: Picture - String

We choose to.stack and spread only nonem pry lists in order. to avoidint roducing We will reti.u'n to pictures and their represen tations after having seen how to
empty pictures. make use of the combina tors for p_icturing calendars.
. . ....
. .. ~.
'
16.G 5 I Examples . 5.4 I Printing a calenda:
... t' ' .. 167 .,'
.. , , .. . -; . ,. ,. ...:.;r- :. ) ' '. ~ . , . ' .
5.4_,3 .Picturing a_cal!!p.dar.: . : .. , . . ,. . . : . .. . , . .. .. ,. . . Now we need to deal wHP. P.ic:ture. The picture of a: month will consist of a
.. ~

beading and some entries , so we define


. Recall tha.t our objective is .to d~fine !l.ftm~tion. Y.ea./'"J<;>{ displaYing. a cal end~
. for~~ 'year, and a function m~nth for displaying the calendar for single month. a picture ::. (String, Year, Dayname, Int) -Picture
One way of defining year is to write picture (m, y, d, s) =' heading(~. y) above entries (d, s)
yeqr . :: ,: year - S~ring . .. Let us deal with entries first. Suppose we set up an array of consecutive numbers
year. ..= sfuiwpic tileWith
. (1,4) group 3 map picture montl1s ananged so that the first day of the .moo.th occupies its rightful place. For :,
example, with d = 6 (Saturday) we get the array '
The fuhction year is defined as the. composition of five simpler functions: ... . ,I

months takes a year and turns it. Jnto a list of length 12 of information for -5 . -4 .. - 3 - 2 - 1' 0 1
.. I

each month; picture tW"!JS this infonnation into a picture of .the month; group 3 2 . 3 . 4 5 6 7 8.
t,troups these piCtures into a (4 x 3) array of pictures; tileWith (1,4) combines 9 10 11 12 13 14 15
these pictures, putting in one blank row bet\.,.een vertical components and four 16 17 18 19 20 21 22
blank'coltllll1ls betWeen horizon.tal compcinents; .finally, s/10wpic converts the
23 24 25 26 '27 28 29
picture to prlntable form. The function 'month can b~ defined using a similar
30 31 32 33 34 "35 . 36.
- scheme,
.. and is left ' . . exercL~e.
as an . T~e function grouP. is defined by. . . ' '
n . -
' . Each of these numbers c~ be converted into a lit~ie picture of hei~l1t {and
group Int- [e<]- [[e<)] v.'idth 3 and then coinbined with tile:
group n xs = .ifJH1llY$ then [] else ys: grorwn ~s . '
. . . w,her e (ys, z~). ~ _sp,litA~. n ~ entries (d, s) - tile grouP. ? pix
' .
-
pix(d,s) - map (rOlf: rjustify 3 pic) .[1 .:. d .. 42 - d]
The functiOI)..SPliiAr was 9,efined Jn Sectio!\4.2 . where pic n = if 1 ~ 11 1\ n ~ s then show n else."" . .. ..
'roemi.U.ns to define picture and months. For each nionth we will need its
name, the year to which the month_ applies, the day name of the first. of tb.e Tlie re~ult i~ apicture of.....1drh 7x'3= 21.. Using this infmn1ation, we c;~ def~e
mon.th, and the ni.unber of. days mthe !J.10rith. So we define ' , . .
heading by . .
' , . ... t
'
.
- . :t
: ..
months :.: . Year - [(String, Year, Dayname,lnt)] . heading (m, y) = bam1er (m, y) above dnames !.
monthS,y = zipp4(mham~s. replicate 12 y, {stdays'y, ml~ngths y.) banner ( m, y) = r 6W ( rjusti(Y 21 ( m * "u'' .-tt showy)) ,,I,
.... .... . dnames. = "uSuuMo~Tu~\-VeuThuFruSa" .,. !:''i :

produces a list of quadruples


t : . ' . :.

. . . ,,
:~ !'
The function zipp4 i.i similar to zipp_'e xcept that it
rroni. a quadruple orlls'ts. ' ~ . '. -. .. . . . .: '- -. .This completes the definition of year:
. The :moitthnames.a're iiyen by' ~ll.st-: . ... - ..
:.:'. ~::~ . . . .. ' . . ._... _, ..
. .. .... . .;,:' ' .... / . .. .
~
. .. . >~ 5.4.4 Representing pictures
. ..
mnames . ::- [String] ., ' '.. .. - .
mnames == ["Jaimary'\"February". "March", The final task is to settle on an!presentation of pictures. One possibility is to .
"April" ,'"JI,fay~;.;'Jun:i:!". , ' take ,. ..
.. "Jttly", :'August"."September''. type Picture = (Heigh(, Width,{[Char]])
.~october",
. "NovE:tnber",
. "December:J .
: . "' -~ ". ., . . . . : However, not every t1iple { 11, }v., ~s) represent~ a valid picture; we need h =
The functions {stdays.and ~tlimgths wer~ defined earlier. . . length xss and h > o. and w should be the coinmon. (positive) length of the
.. ' '
, ., ~ :
. ;
.
,
.. ,.. .. . .. -; . .
' ;
.
.;:\
.. ' '

.. . - ., ....... ..
. .168
..... , ....... ..... 5 I Examples .
5.5 / Text processing
"
. . ~~-
.
~
"
169
.

. - - . . ~
'" - .: ' -- .

- .. .. ._ .. :_ .. ,- __
.
com pon ents of xss. WHh this rep rese ntap on we hav e : ... --~~
" _ _ :

~.:
- ..
' ..
5.4.6 Develop a modified algebra of pict ures that con tain s anwl 'ptc fure null of
. . - .... ..,_ . . .. .
. ,, 7 . .
_,
. . . ... - .,_
... zero heig ht and width and is suc h that null is the unit of (abo ve) arid (bes ide) .
.. .
.. ,
.
-. .. . -~-' . 5.5 Text processing .. .
'
~

The com bina tors (abo ve) and (bes ide) can be imp lem ente d as Our aim in
,.'
..
. this sect ion is to con stru ct a num ber of func tion s for proc essi ng
-~ -

.
text in.vari ous ways. . Mo
.

(h. w, xss) abo ve (J, v,ys s) . . st of thes e func tion s com e in pair s, one func tion doing
'

. . the opp osit e of the othe r one.


(w == v) - (h + j, w;xss yss) * A text can be viewed in man y diff eren t ways. The basi c View is that a text
otherwise - erro r "above: diff eren t widths"
. is just a list of characters, incl udin g bot h visible and invisible cha ract ers. For
' i
the mom ent, we sup pos e that ther e are just two invisible cha ract ers, a space
( h, w, xss) bes ide (J, v, yss) . -
cha ract er 'u' and a newline cha ract er ' r\ Later on, we will also allow a tab

'
(h == J) - (h,w +v, zip Wit h(* )xs sys s)
.
character, which we will den ote by '-1'. Depending on the problem, it may be ..

otherwise - erro r "beside: diff eren t heig hts' ' mor e convenient to view a text as a list of words, or as a list of lines, or even as a .
. . . . .
list of para grap hs.
. .
Our prim ary objective is to develop func tion s for converting
. .

sillce we did not exploit the idea of putt ing two pictuTes with ctlfferent widths . . ..
'

from
'

. . , one view of texts to ano ther. . . ... . . . ' . ._., .


above one ano ther , or tWo pict ures with different heig hts besicte' one another,
'


Let us star t by intr odu cing som e type synonyms:
we hav e dec~ded to mak e both ope rati ons partial.

It rem ains to define showpic: . type Text - [Ch ar] . .


.
.
.. -. . . .
. . -, ..
type Line - [Ch ar]
....
.
. . . . ..

showpic Picture - String - ' . ' .

. . . type Word - [Ch ar]


showpic (h. w, xss) - unlines xss .. . .

By definition, a Line is a list of cha ract ers not containing newlines, and a Word
The fun ctio n unlines was defi ned in Section 5.2 and will be disc usse d again in .
is a non emp ty list of cha ract ers not con tain ing spa ces or newlines. The se re- - --
the following section. All the oth er pict ure fun ctio ns are defined in term s of : '
1
stric tion s are not cap ture d by the type syn ony ms but have to be enfo rced by
the fun ctio ns above, so we are finished. I' '

- . . .,. ,;,. " the pro gram s that create line s and wor ds.

..
.....
. . -. - . . - ..
..
' . . . . ..
Exe rcis es . . . .. . . -. . . .
' ' "
-- . ..
- .. 5..5.1. . ..Tex ts as line s
. . . . .
5A .l Simplify the expr~ssion for jan l yus ing (365-mo d 7)
-
... . . .
- -.. -
'
.
. 1. ;.. ,_
tonside~ fus t' the prob lem of converting a text into a list of lines_. We are inter~
=
. . . ..
.. .
5A. 2 Def ine mon th:: (Month, Year) --:- String. . ..... .. . .' .e sted in con stru ctin g a fun ctio n lines with type
'
r:-
-- ...
. . - . .: , .
'. - '

. .\ . . .
5.4. 3 Define a version of the cale nda r prob lem thai prfuts i!n6 nth With the . . ' ...
'
' ' ' . .,

- . ; .
day s of the week i-Unning from Monday to Sunday. .. . -:;~ lines :: , Text ~. [Line] -..
. ; . - ', .
i.'

. .
For exaRlple, we wan t to have
...
5.4.4 Define a version of the cale nda r pro blem that has the day s dow n the left
-
.
-~- - '
. . . . . -.- . . . -

. han d side rath er than acro ss the top.


'
.' '

--
.
. -
.

?lines 'Thi s is a+text+''


-
. . .. . ' __ ,. . --
.. .. ~-

.
5.4.5 Und er wha t con diti ons doe s the irit.e rcha nge law - .
[ "Thls is a"/' ~ext", '"']
'

. . - . ..
,

. .

(p abo ve q) bes ide (r abo ve s)


. .;-:

(p bes ide r) abo ve (qb esid e s) .. . - . .
..
..
. ' l

.
'

... . ..
~ '

? lines "This is a + +uuu +text f' . - .. . .


hold ? [ "This is a" "" "UUU
" "text" "u] I I
. . .. .

I J I

. . ' - - r
.. -

. .
. . . . ., '
',,..
'... .
.
170 5!5 / Text pro.cessing 171
. . . .... .. .. ..... .__ ;::.::- .. :~ -
.. ?. lines "Thi~ is a text" . .
... '. . . . ':' ..
.
Consider the tvvo furktions. breakOn imd join With, d~ed as follows:
r.,

["Tbls is a text"]
breakOn (Einx) =>ex- [ex]- [[ex]] 0:
- if .nJ~l/
. .zs then [xs] else ys: breakOn x (tail zs)
'

As these examples illustrate, any s~quence. of characters between two breakOn x xs . -


where (ys, zS) = span ( x) xs
~ ' ' ' .
*
\ ' '

ive newllne characters constitutes a line, as does the sequence of 0

..,
0

from the beginning of the text up to the ftrst..newline (if any), and the
' + i

. joinWith
of charac ters from t.he last newline to the erid of the text. Note that the ""''ucuL\ :: (x- [[aJJ. - (ex]
, 0

.of chm::acters-arter the last newl.irle may be empty. The decision'to break a joinWich x = foldrl (e)
up ln this ~!IY re.fl~c~s the view that a newline is a separator charactir etweeri .... where
... . . xs..ei..ys = xs * [x] * ys
a
~

lines rather than terminator charac~er t9 'Si~al the end 9f a line. In pruti~ular,
The relationship bet:vveen these two CWlctions is that
it implies that the :Uumber of lines in a text isalways one more than the -number
of newline cparacters. An empty text therefore has one empty line in it. . join With x (breakOn x xs) = xs
The f'linction lines can be specified as the inverse of second fUnction, a
unlines,ctefmed by for all lists xs. ln particular,
., ~ ~ '
' ..: /.i11es - breakOr{f'
unlines . :: ,[Line] - Text : . ..
'unlines "' joinWitif;-~, : ~ .;
unlines . - .'{oldrl (e) ,o
' ': ~\.

. where xs e ys = xs * " f' +1- ys ',

5.5.2 Lines as words 0 '


, o

The op,erator e is associative but does nq~ hay.e a unit, so the value .of unlines []
. ''
is not define~. Hence a definition by {oldr1 is appropriate. We have alreaqy used
By definition, a word is a nonempry
. . sequence of.visible.characters.
. In a Similar .
spirit to before, we can seek a dcli.nition of a fW1ction words :: Line - [Word]
unlines in Section11 ~ .2 and 5.4.
'

.
,I

.
' ' ..

that breaks a line into a list of its )'\lords. The companionfunction un~vords is
.The. relationship
. . between
. lines and unlines is
. ... . that
. defin~d by
,.: .',

unlines X.s . ... ,'

. . ' .(lines .xjo) =.


. ..
o,'
unwords 00
[Word] - tine. ...
=
' '

,(or all SCqu~nc~s XS .ofcharacters. We also 'have . unwords J'oinWith' u '.. .


' ~ ' I , '' '

, .This takes a nonempty1ist of woids , puts in a single space between each word,
0 0

unes (unl!nes xss) = xss


and concatenates the result. It i.s. tempting now to define worcls = breakOn 'u',
f or aU lists xss of lis~s of characters that d,o not contain newlin~s. ' Vsing . but this'idea is not quite correct: tinlike a line, a word is a nonempiY. sequence of ,
I
firs t-equation, oile:c~ sYnthesise the.fqll_owing implementao~iori of-lines: characters. Putting it another way, if two newline characters are adjacent, theri I

. ~here is an empty line between 41em; but if two space cliaracters are adjacent, !
.
.- . .. then
. ~here is no word betweep them.
. . .. ..Instead, we define
. . .. :-.
.. .
;s,""' .
lines :: . Texr - [Line]
. . 'lines
. . .
if null zs then [ysJ: else ys: lines (tail zs) .
.

. . words :: Line ~ l ~Vorch :- ...


, :. '' -, where (ys, z:S) ='Span (*:-f) xs . . ''
o
' , o
I

' .,
words

=. filter (not : rzuiO. breakOn 'u'
. <\, .
' ' '

Thi.s breaks.a text xs into ys (the longest inipal segmentof xs tl:lat cl.oe~ not ..
This defiJt1tion filters out empty \vords.
0 '

. . .'. '
c'o nt<l;in newlines). followed by zs (the rest ofxs, if any). If z~ is not empty, theri
As one application of the fun~ti.i::ins lines and worcis; we.can count the nwn-
-its. first character is' anewline, so the process of constructing additional lilies
ber of words in a text by .:. . .
is performed ontail zs. Details of the synthesis are left as an exercise, We \VUl
,
sec other instances of similar defmitions, so the p;,Htern of computation abqve wordcount 00
Te-xt - h it
deserves to be generalised. wordcounc - length concar map words lines .
: .
-.. 0 0
- ..
;

-; .
', '
~~
.,
)i

II ' ..,,
.. 1-72 : :

.' ..... / -. '~\."':~ ;:' .. s.:j/


-
~
I~ ..~. 5'/ examples . .Text 'proces. sing 173
., ' I . ~- f~ -...,
This breaks a text into lines, breaks each line into wo.rds, (:Qnca~epares the result
-. , .: o ' - tL
.,
'' ._ U~like the funcri ons imiines and 'unwo,rds, 'the ftmctiori unfie/ils isno't defined
to 'obtrun all the words~ the text, and ~aily counts.bm~mai:ly;tl{ere aR
'
. .... ,- .. , as join Wi(h '-t' becau se we want to replace tabs by spaces. Since the number of
As anoth er application, we can r eformat a text by
spaces to which a tab expands depen ds on the numb er of characters co the left,
{orma rl Text - Text we hav.e to rebuild the line from left to riglit. So we define
......... ......
{orma tl = unlines map forma tLine lines ~ ;: ..--- . unfields .. [Field] -: Lirye . . .
4 -c
{orma tLine .. . unfields - {oldll. (e)
...
eys = xs .ft. 'spaces ( t.- (length :(s) mod t) * ys
Line- Line . . .
{orma tLine

= rebuild ; words . 'Y'here xs
where rebuild ws = if null wnhe n'fTe lse unwor ds ws . T~e termxs mys puts ill enough.s~aces a.fter xs t~ reach the. ~ext tab stop; thar
. . is, the next rnu.ltiple 'o'f t.
The functi on forma tLine breaks a line into a list of its words . If rhis list is ..
empty, then an empry line is retwned; otherwise, the line is reform atted by The problem with the progra m for unfields is that it is fairly inefficient: the
removing redun dant extra spaces benveen words . The function f'orrna tl applie s . length of the line up tO the next tab is .recom puted for each fi.eld. A better
this operat ion to every line i.n the text. It therefore replac;~s lin~s containing_ imp!em entatjon is to use a rupling strategy, specifying a function expand by
,only space charac ters by empty lines. Below, we will seea, monFsophisricaied .
vers1on,'{orm at2, of this ftmction. ,. .... .-~
.
... - . expan d
. [Field] - (Line, lnt)

=
o I
. . . . . expand {s . .<~nfields {s, length .(_u nfields {s) ~ .
! : ' ' I ' :

. 5.5.3 Tab charac ters ...... The cup ling strategy for improving the performanc~ of programs will be con-
si~ered in Chapt er 7. However, the follqwing progra m for expand is quite
easy
Some. iexts m.ake use of tab. characters.. ln. order tq. displ.~r.-EJ text containing
tabs, it is necess ary to replace them by the right numb er of-space charac ters to
to synrhesise and we leave details as an-exercise:
,.,. reach the next.tab stop. For simplicity, we will suppose tha:qa b stops are fixed expand
I; ar every t colum ns for some given consta nt l.
I . . . . "' {oldll (e) map addLengch
f The function detab, for removing tabs, works line by lif:!~. s:o Vle can at once w.here addl.e ngthxs
i . - (xs,len gth xs)
define : , ' .: (xs,'m) ei (ys; n) "" * ys, m + k +n)
!
l
(xs *spac es k
' ..
detab .. Text- Text .
... : . .: , .... .- ... where k = c- m mod t
'1
detcib = unlines .' map detabL ine lines
~ I - + ~ , ,' : ;~:: Now we can define unf{e/ds = /st : expand.
The functi on detabLine removes tabs f;~m a single line.- On~. \v~y fb hnplemefi.t
it is to break, the line up intO fields, that is, lists of charac ters char do not contai n 5.5.4 Parag raphs
tabs. Introducing the type synonym : : .
.. . ......
' .......,
...... . .. .
. .'s6m~ 'r~xt~ tan also 'be 'Vie\ved as aIHir of paragraphs. Such ~ext.s consist of
type Field = [ Chin:) ~- . > ~ :. .-. : -.
. ,, .. . ..., _ continuous prose, witho ut bits of mathematics,. tables , poetry, programs, and
.. ..... ....
we have so on. Logically, a p~iagr~ph is simply a no~empry list of.words, so we declare
'. ..... .;. i. .; .. '"
. .
fields .. Line- [ Fiefd]
. .. . 'I . f
type Para = [ Word]
.. . ..
. .:"-
.... . .....
.fields - breakOn '-i' , .
.. .

.,
. . ...... 0 -

The function parcis converts a cexc into a list of irs paragraphs:


Now we can define ... ~ ._
. .'' .... .. .
paras .. Texr - [Para) .
detabL ine .. Line - Line ~.::.. :_~ '
.. '.. ...;. . .. ..! - paras = map con cat filter (not null) ' .
detab Line - unfie/ds fields
0. ~ .. . breakO n [ ] map ivords lines
. . .
: .(. e',t

...
.....- ~ -
-- ~

- - .
r ....

.; ~

. . .. ~,
' 17.4 5 I Exarnplcs 5.5 /Text proccs.~iruJ . . .,.
l
I

'I . ' . 175 . 't


' .; : i
'

. . .. ., . '. . . ... , .- . ... :. .
' ' . : ~ . .' . " '' ri
. Jhis.t<\kes a text, ~onvens, it to a list of lines;and converts each line to a list ..we are left with,. .thE:! funqi.on.fi llPara, so let us conclude by irnplementfug '
I

..of word~.. Paragraph breaks are signalled by the presence of a iine containing _the greedy algo~ithm.for filling a paragraph. The program is
I

.,
~6.\-vords. The.empty paragr~phs are thei1 filtered out;: and the reinaining (mes ..
are flattened into Lists of words, discarclinginform'!-tion about what words ru~ {ilfPara :: . . Inc- Para - [ [Word]]
I
. on what lines. fillPara n-ws ~ if nul(~ then [ 1else xs : {if/Para n YS. '
''
The reverse process, that of rebuilding the line structure of a paragraph, is

= splilAt (greedy n) ws
I . ' :
wher~. (xs, ys)
known as iilling. To fill a paragraph is to arrange the words or the paragraplf
. into a sequen:ce of nonempty lines in such"a way th~t. firstly, the length of nus splits a list ws of words into the longest initial segment that will fit on
each line docs no~ exceed a fLxed max,irnum a.nd, secondly, the s equence as a a line of maximum width n, and the remaining words, if any. The proce~s is
. . c~mtinued recursively on the remaining words.
whole gives an aesthetically pleasing appearance .. Note carefully tl)e ~ssential
difference between filling and formatting: filling says what words go on what The function greedy is defmed by
lines, formatting says how they should be displayed. greedy .. I nt - [Word] - int
One way of fonnalisi.Og the notion of a pleasing paragraph is to ask 'that
greedy n - length last: filler ((s n) length unwords) initsl
some measure of waste be mininlised. For instance, we might want the number
.
... of lines ill the filled paragraph to be as ~mall as possible. One simp!~ algorithm The value of greedy n ws reads: the length of the longest nonemp ty initial
'

for filling a paragraph is greedy_in nature: at each stage select .the longest .. segmentxs of ws satisfying length(u nwordsxs) s n. The function initsl returns
irlitial segment of the remaining words thatwill fit \-\'ithin the maximum limit. the.list of nonernpty initial segments of a lis t in increasing order of length; hence
For this algorithm to work, indeed for tbe filling problem to have an)~' solution the last element in any subsequence .of initsl ws is the _longest element of. the
at all,. it is nccessa:ry to assume that the maximum line limit is largeenOtigh
subsequence. Recall that unwords is not defined on empty lists, which is why
to accommodate any s ingle word. It can be shown that the greedy algorithm.
' +

. we generate only niinempty initial segments. Recall also our assumptio n that
. . . . retmns a shortest possible list of lines. 'the line limit n is large enough to accommodate ari.y sirlgle' word, so filtering
Suppose we are given a function {illPara >vith type .~1?-e.initial segmems of a nonempty sequence of words produces a nonempty
' . subsequence.
fi/IPara
,
:: I. nt - Para- [[Word])
', . Although this solves the problem, the progrrun for greedy is inefficit:nt be-
The function (ii/Para,i1 rake~ a nonemp ty list of words and structures it into a . .cause the value of unwords Is recomputei.l for every nonemply initial segment
nonempty list of nonempty lists' of words. Each. component List of words will ' ' of the given list of v/ords. ~ fact, greedy n takes quadratic time in the ~ize of
constitute a tine in the reformat~ed t~t.. We will give.one imp~ementation of the result. Let us finish by deriving a more cl'ficient version.
(illPara below. We.tan now reformat a text by a function (ormal'2, defined by As a first step, we can replace {liter by take While ih the definition of greedy.
. . . ' . ,, . . . . The reason is that if lnltial segment. XS fails' the test, so lengt11 '( unwor ds XS) > r.r.
......
. (ormat2 .. then so docs.any longer initial segment. We can combine this substitutio n wHh
;: [n,t -
..Text ...:. :Text . : .. l .... .
.=
'
the property ,
.,
(ormat2 n u n~aras map (fil/Para n~ paras

. This a text into ~~ag~~phs , fills .e<r.Li:\. ~aragraph; and theh rec'onstilu teif :. ... :_.~ :. .~e~gth last ta~eWhile_p inilsl = length take While p initsl
. .breaks
'
. . ' . .... ' . .. . ' ..:
. ... '
the text a:s a string. The function unj:Jaras can be dcfine9. by
~ .
,

. ' . . .
'
It is easy to sec why this law is valid: if takeWhile p (initsl xs) returns the list
., ., '
. '
'
..
. unparas .. [((Word]] ] - . Text'
tlxtJ, (Xt,X2 ], . ~ , [xr,xi, .. . ,Xn] ]
-unparas = : unlines joinWith [] m_ap. (map !-lnwprds)
. . . . then the length of the l<ist element, namely n, is the iength of the whole list.
This :tO~\I~l'tS thewords',lii each lln~ Of each 'paragraph back into line., jOinS a Applying this rule gives .the following expression for greedy :n:
the lines together witJ:l etn).jty lines. and ol1.ver.ts the result back into a t.~xt by ,,
inserting i1ewline characters. l~ngth take Wilile (( s n) length umvords1 initsl
'J'
\
.

. . ' . - .
' . - . ...
-----
176
'
. .

' .
. .../.
. :A>"
5I Examp
.
les 5.5 / .Text processing . 177
<< -

'
The next law We want to use is


.. . . ..
....._ ; ~ .y :'"... .
. ' :-

.
.
. .
-
. .:--.0;:, . : _-.. :.. ;' _
. - ' .
: - . . -_ .. : - ~_.._\_::.' :::': .;'. _ ._, ~--> ~ i _. ...... . .
. -:
' '" .. -
..... ..-' < -; -
0

-
: ,,
. . .The end result is that we can comp ute greed yn by the progr am - .. . . .
-
'- ~-~,.- < .

.... - -- . . . . . ..
map f take While (p f) - take While p.map f _. ~. .. . -
. .
. greedy n = lengt h take While( <. n} scan/1 (<&>) map leng(h .
'
. .
.--r
.
The aim is to apply this law to the expre ssion for greed y n wit-hp;= (::; n) and
. .
' o ,-o_" -

. This versio n takes linear time in the lengt h of the result .


J
. ' . -
f = length . unwords. To do this, we will need the factj: hat , -.
. . . ~

.
~
'

. .,.
.
._.._..... --
length = length map f . .
Exerc ises

5.5.1 Prove that unlines -lines id. Why is it not the case that lines nnlines
for any f. Appl ying first this law and then the one above ;":':we obtai n a new . . ., I'd? .. ..! ,..
=
. ,.:. ' .,. . ...
expre ssion for greedy n:
'
.

.
.
. ~ ~-

.
'

.
' ' r - ',

. 5.5.2 Descr ibe the lines for which unwords words rerurn s J.. .. .

length take While ( < n) map (length unwords) initsl


5.5.3 Suppo se we adopt the conve ntion that a newli ne chara cter is a termi hator
For the next step, recall that unwords = foldrl ( ffi ), where xsmy s = XS* "u" *YS. for lines, rathe r than a separ ator. In this case the numb er of lines in the text is
An appli cation of the fusion law for foldrl yields exactly the numb er of newli ne chara cters. We can then define u nlines by . .

..' .. . ._ -.. , .. . > tm1ines . ca~(al'; inav(+f''~+''> . .


. --
. .. . . .
= foldr
.
length unwords 1 ( ). map length. . -
'

- .. '- ' . .
. .
'
"" .- :' ' ' .
,_ . _ , .. .. . ...
_
"
- . . '
.' . .. . .
. wher e m n= m+1+n Use fold-m ap. .fusi~~ 'to
.
rewri
.
te the
. . .
defuu tion
.
of unlirw
. .
s as an instan ce of(old r.
. -

Apply ing this result , we now obtain the follow ing expre ssion for greedy n: What is the corre spond ing defini tion of lines?
- .-
5.5.4 Synth esise the efficient progr am for expand.
.

len.gth takeW
. hile ( < n) map (foldrl (<&>) map lengtn r:iiTf'tsl
. 5.5.5 Define a versio n of detabLine that does not first split a line into fields. ..
-
. .
'
The .next .step is to use the . funct or prope. rty of map, to obtai n the new expre s-
'
. .
'
. .. . 5.5.6 One way of comp ressin g texts is to reduc e the numb er of space s.a.nd tabs
SlOn


' -. . -.
to the minim um requi red to achieve the same spacin g. Traili ng space s and tabs
length take While ( < n) map (foldrl ()) map (map length) initsl 'can
' ' . be
remo
.-.. _ -: --- vedJr om the end -..of. ..a.
. -, .. _ line witho ut affect ing its visibl.e appea rance . .. .
.' ,_,,_ _,;.<-- . _._ ... . . .
-, . _.--- . ,, -, .~ . : ;.f- ~ -, "" -t --:;-: ' ~ ;

Define a funct ion entab for insert ing tabs.


Next we make use of the natur ality condi tion . '. .. . .
5.5.7 Why can't a text conta ining a mixtu re of prose and poetr y be regar ded as
'

.. . . --..... _-
'
'

allst of parag raphs ?


. ,
. -- .
. . . . . . .. .
map (map f) initsl = initsl map f
,. . .. - . 5.5,8 In the text, parag raphs are forma tted by left-ju stifyin g lines. DeVise an
.
.
. . . .. ..
to obtai n a furthe r simplifi,cation: . . -
algo rithm for forma tting lines so that, excep t for the last line in a parag raph,
. .

- - -

. .... ...
. -' .
.
they exten d from thele ft to tl;leri ght marg in when displa yed. ..
lengt h take While ( < n) map ({oldrl (<&>)_) initsl maP;j.eDgth . . . " ' '

.. .

For the firial step we would like to apply the following pr~perty.:ohccin/1:
.. . . - - .. .. . . . .. . .. . ..

scan/1 (<&>) = map (fo/d/1 (<&>)) initsl .... ._, ___


... .



' .
But, at the last hurdl e, it seem s that we .have come unsru ck: the abbve expre s- .
sion .for greed y n conta ins {oldrl.( <&>) not fold/1 ( <&> ). Fortlll1ar~:Iy ; the:fi rst dualit y -- . . . .- -
.
. . .' - .
. . .- '.
. .. . . . . . . ' .. . . .._ .

. e: <&> iS an assoc
.
theor em. come s riding. over the
. hill to our rescu iative opera tor,
' - . - :' -' - . .
as one .can
'

easily check . Moreo


''

ver, the initial segm ents


' ' ' '
.
of. a lisrar e all
.

--- . finite . ' .
. .' - . . . .
' .
Henc e we can rep!ace foldrl (<&>)in the expre ssion by {bld/1 (<&>) . ._ . . . .
-1 - ---
._,

-
. - _. . . ~- ----.,:; , '

.. . . .
'
. . . . ~

,_ '
,.
. .
"'
'
\,
' ,
' . . .'
t . . ... '
~- , ' . .
. '
: - ~
.. , ~
.. . '.
~ .: . I :' , . ..
.. ' ..., ., ., ..., ..
"
.. . . ..'' . ., .

'
, .' ,' "- ,

1,,
I

.: -
:


. . :. ..
..i : ::. . ' . :

Chapter 6.
. ( .'; ~

.. ... ..
,';
'
' I
., ' ...: J' . .

--:.
........ f
. ,
.. ,
__
,. . .'

-..
Trees . . ' .
.,
..

'

. Any recursive datatype that exhibi.ts a .nonlinear structure is generically called


.. a free. Trees serve as natural representations for any form of hierarchically
+ ! ' :'

; ' ' I ' ' ' ' ~ ' ' , , ' ,_ , ,' ' ', ' ' , , , , !- '

.. organised data. The syl)tacric structure of arithmetic or functional expressions


..
'

" . can also be-~odelled by ~ t~ee." Perhaps niost useftD. of all, trees provide a
generalisation of lists as a means.:ior.organising infonnation .and retrieving it
... .; ... .- . ..
..
.. : . efficiently. . ' . .. .
. :.:. :rilere a~e:n,;~irous spe~i~s anct s~bspecies or tree. 1-r~e;: ta~he-~.i~sstfiect
~ ,.

. '. . ' . .. . ..
.acco~ding to the,precise forl]l. of tb~" b,ranc~ling s'tructw~.
'
' , .
.
the locat)on.of
. . .. ,, . .inform
. .
ation \.Vithin the tree, and the relationship between the information stored in
..
t .

' . ..
, :,
.. . .
different parts .of tlle tree..~n the ,pteseqtch~r:Her we will intrOduce <;me or two
~ ;

.. . ..
, .. :
, . oft:J::te-mor~ common species, deS~J,'ibe. (}little of the .basic terminology associ-
ated with trees, and give one or twp,simple applicalions. Further applications
. ...
'
. ... ,. .. are given in Chapter 8: -- "':
: .. ' . \,, .. .;. : .... .. : ,.'
... '
. . . : -. ...
.. 6.1-. .Binary
.. ' ' '.',
trees
., ' ' ' ' '
'

., . ' . . ' ... . ,:


' . .
..: ....
. ' ., . ' .
.. As Hs name. implies, a binary: tree is a tr~~ ~Vith a sirriple two-"XaY bJ;;mching
. ..:
snucture.
~;
.. ,., .. ..
... .
-:
-
' 1 ' I ' , ' ' '' ; >I, , ,), :
....
o

.. .. ... . . ...' '.;,\~:-. There are two .or tluee cJ.i.ffe.r;ent subspecies of binary tre'e; but we
..; -'' r
' " .; _ . .:- ...: . ' : ....... ,. '
1
, :~ ' ~'
... ,.. '. ::- . ..
'./

., ' ":.:.:..:. : : :-':' .,


.

:. ..
._,,.... ::.-::. ....vill-star.t by discussing the-datat)fpe .
.. . ', . .. .. , : , ' ~ : o : ~, ~ ~'!.: : ''
. ,. ..
: I,
.. " ' ... ' ,. . ,,
/ ~~ '
. ' ; '.
. .. .. .. ,.,
. .
'
.-. .. '
~. ~
':: ,......
. . . . ' . . . ' . l' ... ... . '

ex -
:
. '
data .Btree Leaf lX. ' I Fork (Btree iX) (Btree iX) . . ..
.. ' ., .. '.,
.. : .- . ' . .... .'
.' . " .
~.

A Y.alu~ of ..Bti:ee c.x -is either 'a.:ieai;1od~; \vhich 'co~tains a v<llu~ ~f .tf.Pe ()(, or a
l :- ' '

.... ' . ' ,

.
' fork-node, ~vliith consists oftwo further.trees, called the left and right sup trees
.... . ' . '.,-.: .. . . . ' ' .:
-
'\

.. . .. .
'or the'i10de... i:\. .leaf fssometihles ca.i.Ied Cil~ e,-iitei'n~l ilode, or Up, an_d a fork node
.,
... : ~-~- .' .
-
.. is sometimes called an il1ternal node.
' . ,.

.; '
. ...
.. " .
:
. . ". # ~ ~-

.- ..... .. ."
.. -. .... -
~ :
"" . . ., '
...
. . ' , ..
. ....... ' . ... "

.''lI
. '. .
-_, . _ .
~ -
. .

180 ' . .. ... . _...I ' Trees


. .. '. ..... -,-.y.
. -.. li:--...- . . .6

'. -. - :. _ .
.
. . . . : ._. ,. . . .. . ... .
. . ...

6.1 / Binary trees 181 .
.- - . .. .'"
.
. . .- - .; , -
.... ! ~~ --:-- --.,. -. --.: - --
' ' .. . '
': , .. . . . -
.- ..
'
'
.
. . - : ,. ' ., . - .. ..'
For exam ple, the tree . .
- ' - ' '

. _, .. , . ' . ; - ' '


..
-- 6.1.~ . Size and heigh t . . . . . . ' '. '

- . . . . . ,.--- . . ..
.
-. .-.-...
Fork (Leaf 1) (Fork (Lea{2) (Leaf 3)) .. .
There are two iinpo rtantn umer ical meas ures on binar y trees, size and height. '

consi sts of a node with a left subtre e Leaf 1 and a right subtr ee which, in turn, The size of a tree is the numb er of its leaf nodes :
consi sts of a left subtr ee Leaf 2 and a right subtr ee Leaf 3." Comp are this tree ..
SIZe :: Btree IX - Int .. .,...~

with a secon d tree


size (Leaf x) = 1 ..

Fork (Fork (Leaf 1) (Leaf 2)) (Leaf 3) size (Fork xt yt) = size xt +size yt
Altho ugh the secon d tree. conta ins the same seque nce of numb
The functi on size plays the same role for trees as length
.
ers in its leaves . . .. does for lists. In fact, ..
as the first, the way the inform ation is organ ised is quite differ ent and the two size = length . flatten, wher e .
'

expre ssion s denot e differ ent values. In essen ce, differ ent eleme nts of Btree IX
expre ss differ ent ways of brack eting a seque nce of values. For example, 1 (2 3) flatten . :: Btree IX - [IX]
and ( 12) 3 are the two ways of brack eting 12 3. There ate five ways of brack eting flatten (Leaf x) . . .
- [x]
four value s, name ly ... . _., ., _ _.;,.
. _
.. flatten (Fork xt yt) - flatten xt * flatten yt
. .
' .. " . . . . . .
. ...
l( 2 ( 3 4) ) l ( ( 2 3) 4) ( 12 }( 3 4) (1 ( 3) ) 4 z ,. . .
( (1'2) 3) 4 The functi on flqtten produ ces the seque nce of leaf values in lefHo -right order .
..'
' . . . . . . . '

A tree is finite if and only if it has


'


Henc e there are five distin ct binary trees with this seque nce of leaf values. .- . a well-defined .size .
. . . . .
There is a siinpl e but impo rtant relati onshi p betwe en the n umbe r of extern al
Since we have used the names xs, ys,.:. to.. denot e variab les that range over .---
. -
. '
and intern al node s in a finite binar y tree: the forme r is alway s one :inore than
seque nces, we will use xt, yt, . . , to denot e variables, that range-oveJ..t rees: . .. '' ' ..
.
.
the. latter . Suppo se we cotint the numb er of intern al . nodes by the. functi on ..
' ,
' .. . . -- '. .' . . ' ' ' '
'
nodes, where
, '

6.1.1 Induc tion on trees -- .- .-


. . . . . . . .. .. - . ;
::
. -

The princ iple of Stmc tural induc tion that We have se'eri for natur al numb ers nodes Btree IX - Int
.. .i " '
and lists is easily exten ded to binary trees: in order to show that a propos,ition . ' . nodes
,.., (Leaf
. . . .x): .... -.. .. 0. . '.
. . .. -. .
' '
... ''. . . ' : , -- ': - ' ...
. ' . ..

P(xt) holds for all binar y trees xt, it is sufficient to shOw: . ' nodes CFork xt yt) - 1 + nodes xt + nodes yt .
.. .. ' ..- . .. , - . . ~' . .
.. ,, . ' . ..;
case CU. That P(l) holds ; Then size xt = 1 + nodes xt for all finite trees xt. This result is prove d by
. ' '

.. ...
-- ..
'

.. - -.-.... .. ..
- . .
stmct liral induc tion over trees, and detail s are left as an exercise. ... -
Case (Leaf x). That P(Lea f x) hoids for all'x; . . <. ; . . ~ .. .

.. . The secon d usefu l meas me on trees is the notio n of the heigh t of a tree.
-. - '

. Case (Fork xt yt). That if both P(xt) and P(yt) hold, fhen 'P(Fork xt yt) holds as . . "fh~ heigh t of a tree meas mesh. ow far away the .furth est leaf is: .
.
..
well. . ... . . .
. . ...
. . .
. . .

_ ,,. ,,.,: . \;;;,-~- ..~- -

' :.
.

: _ .
!- - '

. :
..: :~: . :.<_t;'-- ~-, ;_:::::.~.-=. . ;:_. .-:-~:.: 4.: . ~-----.' -~-'-. : . . ; . height . :: Btreecx - Int
If we want P(xt) to hold only for all finite trees, theq t.rf:{)uffici~nt to prove .. . ' : .. ...
0 .
,

height (Leaf x) - .. '

only the last two cases . Bydef initio n, a finite tree is bh~ Wlth a finite numb er
.

:' . . :.
of leave s. An exam ple induc tion proof is given below. : : > ._
'
height (Fork xt yt) - 1 + (height xt rnax height )'t)
. . ~
-

. . . .
.


For example, the tree '

.

.
,. . '
. .. - ' :
. ' .,.
. . -
' . . ..
'

- .. .
fork (Lea fl) (Fork (Leaf 2) (Lea{ 3)) .. .
. .
-
. .
. . . ,_ . . . . . ,_ -

.. . has heigh t 2. The heigh t of a hee xt is the maxim um cif the depths of the leaves ' ---
-- . . . . .
in xt. In the tree above, (Leaf 1) has depth 1, while (Leaf 2) .and (Leaf 3) both
.

--

..
.

.. .
..... ..
-
;

- ..
.. . ./

.
. . . . .
I
I
.. 'I
; .; ..
. . . '
182 G/.Trees 6.'1 "! Binary trees 183
.. . . .. .:
.: . ; . ;-,
.- .. .. ~: .
hav.e.depth 2. Thefunction depths takes a tree and replaces the value at each Case (Fork xt y t ). We reason: .... ... .
. ..

leaf by. the depth of the leaf in the tree:
:
..
size (Fork xt yt)
depths :: . Btn~e IX - Btree Int
{definition of size}
depths = downO
size xr + size yt
down lnt - Btree IX - Btree Inl
.s {inducti~n h)tpothesfsl
.do wn n (Leaf x) - Lear n
down. n .(Forkxt yt ) = Fork (down (n + 1 ) x.t) (down (n + 1) yl) 2 I (height x.t) + 2 I ( h~ ight yt)

If .we define max.lllree by .s {arithmetic,. "vriting h ;. (height xr max height yt))


2 I h.+ 2 I .h
max.Btree (Ord IX) ~ Btree IX - IX
mllx.Btree (Leaf x ) - X {aritlunetic}
max.Btree (Fork xt yr) = (max.Btree
. . xt) max (maxBtt;ee yt). 2 I (1 +h) . .
then 11eig(1,t =. ma~tr,ee qepths. For a proof, see Exercise 6.1.6.
,,
{definition
.
of h and..'i1efgfJ't]
' . ~ '

A bimuy tt:~~ )s said to b.e peif ect if a11 its leaves have the same depth. For 2 1 (height (Fork xt.y!')).
example, the tree . .
.
7 ., 0
Fork (Fork (Leaf 1) (Leaf 2)) (Fork (Leaf 3) (Leaf 4 )) .
... . . ,.
' ~iv,en any list x.s of positive length n, if Is possibleto construct a tree xt with
.

is a per.f~ct binary tree. T.he size of. a petfect binary. tree is always ~ power of
two and, disregarding the values in the leaves, there is exactly oneperfect tree flatten xt = x.s and heigh.t xc ,;, liog nl
.. .
for each power of two.
Although two trees' of the same size need not have the same. height, the :
0

Such a tree has rninitnum possib)~ height. In general there will be more than
'

two measun!s are not i.D.dependent The follO\ving result is one of the moSt onetree of minimum height witlr a. giv~n sequence of leaf v~ues. Minimum
. irnp ?rt~nt fa~ abou_t bi~ary tree~ . It says that . height trees are useful bE;caus~ ~hey en sure that the cost of retrieving a leaf
height xt '<size xt ~ 2 I height... xt . value is as ~mall as possible in. tlle worst possible c11se.
. . One minimum height tree can be obtained by dividing up the (nonempty}
.for:ill.L.finite
'
trees xt. Eq).livalently,
. taking logarithms
.. to.base two, we have ,
.
input into n-vo equal halves and recursively building a minimum height tree for
. . each half:
flog (size xt) l :S height xr < sizext
rnkBtree ::[a] - Btree (X .. .
.-wnere-rx.l (the ceiling.Qf.x) denotes tl1e smallest integer ~t least ~- The proof' .. .
is
0f tlli~: flindamental rel~hi'qilship oystriii:t:Ural iridtic~~?.n::. We will prove orie .
' mkBI'ree
.
xs
(m == 0) - Leaf (urrwrap xs)
irieqt:iilllty and leave the- other as an exeicis'e.'
. . . . otlwrwise - :For.k. ( mkUtree ys) ( r.nkBlree zs) .. .
Pr9Q.f. We prove size xt .si I heigh~ xt by..mduction on xt.'. . where m ==. . .. ...(length
. . div 2 ..
. xs)
..
.. . . .
'

. ...' ..: . .
., .. .
. . . .. . . .. (ys, zs) =:' spli,tM rn ~ . .. . '

..
, \

Ca~~ .(Leaf x). ~n a llnc, we have


. Recallfrom Secttori 4.2 that spiitf.\t n X.s = ((ak'e n xs, drop n is). The function
' I

. ..
. . . . . unwrap is defined by unwrap ~~x] = X. We wi!J analyse the r.unning time of this
siz~ (Leaf xf = 1 = 2 I 0 = 2 i height.(Leaf x) pr'ogram in the following chapter, :s.ho'wing tlw mkBtree takes time proportional
-
.: . .. ..
..
' ..
.., .
. ~......-:- ... . --
... . .

184 6/. Trees . . : 6~1 I Bina.r y rrces 185


.. ' ', ;: .;, ,~~~~ -~ r

.. . . . . . :' . :.. ' . ' ::~~ :;~\. : . '::~~.~; ' . . .. : ' ., ,

to. n log.n steps on alist oflcngth n. As we will alsqsee i,n the.following chapter,
.. . .. ....f ~- ... ~~.
flatt~n = foldBtt.ee ~~ap (*) . ...- ' ... _,.,.
"
. ...
i~ .is possible to give an implementation of mkBtree that:\.vorkS..i n linear time. . ......
maxBtree - {oldBtree id (max)
6.1.3 Map and fold - .. ~ .'
mapBtree f = {oldBtree (Leaf {) Fork
The functions map and fold for Lists have analogues maJtree and foldBtree
for trees. The function mapBcree is defined by ... . .
In the first two example~. the srandard function const is defined by
mapBtree (a - /3) - Btri!e a - I.Hree j3
mapBtree f (Lea{ x) co.n st .. a - /3 - {)(_
- Leaf (f x) . . . ~ .
mapBtree f (Fork xt yt) - const xy - x
Fork(mapBtree.f xr) (mapBlree{ yt)
The funclion mapBtree satisfies laws similar to that.of inap. In particular, The function wrap is defined by wrap x = [x].

mapBtree id - id . .
6.1.4 Augmented binary trees
maJ!Btree ({ g) . = mapBtree f : mapBl"ree g . :. ; .~.. . ..
: .-. ' :., ...... . ,: ::
' . ' . . . .

. . .. .. ~
Th.e binary trees futrot;luced above have information only in the tips of the tree.
Thus mapBtree,like map, is a functor. We also h(IV~ A. slight but important variation !:m the b.asic ii:lea is to allow inform~lion to
= {latce11 mapBtree f be stored in the nodes as well. The technique of labelling ,the internal n<;>des
map f flatten . .. .. '
of a binary tree has many important applications in the design of efficient al-.
The-function
' '
{oldBtree
.
has
.
to prov.icle
. . .
a repl.acemenr for

ea<:h of the
-..r '
constructors . gorithms on trees. We ~vi.ll give one illustration no\v; others are 'given in the
of Btree a. Th,e two constructors have types . . . .remainder of this chapter and in Chapter 8, . .
Suppose we augment binary trees with size information. More precisely,
Leaf .. a - Btree a
cortsidei: the datatype
Fork .. Btre~ a - Btree LX - Btree a ~. -.
data Acree~ Leaf{)( I 'Fork lnt (Acree ex). (Acree a)
. Hence {oldBtree has ro provide two replacement functimis, '{ andg, .\vi.th types
.. ...
I' .. a-j3
., ,' . ... .. ... .
.
" '
For.simplicity we use the same constructor names as foi' Btree, though different
. nam~s Would have to be chosen in any script making use 'of both data types. In
-~ .

g .. 13-{3""/3 . thl,! data type Acree{)(, th~ internal nodes a.re lab~lled with an integer. T11e idea is
... ..
The definition of (oidStree is
J.
. that in'the element Fork n xt yt, the integer n satisfies th~ condition n = siiext,
in
... ... .
. .. : where siz.e.is defined the same way .as for Btree .ex . .Of course, we .have ro
{oldBtree :: :: (tx..:_. /3) .:__({J.~ ~-. --. Jfl:-:-:Jit;~e a- /3 .. ~nsme that\:his conditlori is satisfied when we constmcuhe nee. We will do
.
x) ,. = 'r x
. .
... ' ,.';.:;.. : :>;:~.'..;. ..
~

to/dBtree f g (Leaf . . . ~ -+ : :'thiS by building fork nodes only through the US~_9f a ftQictiOn fork defined by'
. -
foldBtree f g (Fork xt yt)
.. . .,
= g. (foldB.treef
,.._ . w., . .. . .
g"><.r) ({ofdBh'ee
~

f g yt)
t '

- . ~.
..
. . .
. \ . .. . . . ..
. ~ . _. fork .. A tree{)( ~ A tree a - A tree{)(
Many operations on trees can be defined in ~erms of1oldBtree. As examples, fork xt yc - Fork n xt yt .
we have ,. :. ... . . .
.. n = /size xt + lsize
' where yt ... -.
~
.
size = {oldBtree (consfl )( +) .. ' ' " .:.
..

/size ..... Acree ex - Jnt ,'
...
..
height = foldBt ree (canst 0) (ED) ' . /size (Leaf x) - l
wliere m ED n = 1 + (mmax n) . /size (Fork n xt yC) - n
' - ..
- ~ .
..
6.2 I Bif!ary search trees 187
186 . . 6 I Trees . .
., ..
I
\
. .. : ' .. : . ... ' ~
:' ., .
. .. ' , ' ' $r '
by
6.1.3 The subtrees of a binary tree can be
I (. '

de~ed
For examp le, we can mo.d.ify thefu nction mkBtree. to .giv.e a .functi on rnkAtree .. 'I
for erecting a minim um height augme nted tree on a given sequence of values::
. . . -. subtrees :: Btree IX - [Blree IX]
_mkAtree :: [IX) -:- Atree IX subtrees (Tip x) := .. [Tip x] . '

mkAtreexs _subtrees (Bin xt yt) "' [Bin xt yt] *subt rees xt *subtree..~ yt 'I
;
..
(m == 0) . - Leaf (unwrap xs)
State and prove a relationship betwe en length (subtrees xi) and sizexl.
othenvi$e- = fork (mkBtree ys) (mkBl'ree zs)
where m = (length xs) div 2 6.1.4 _Prove that heigh( xt <' size
.
xt. ,
.
.. = 6:1.5 ~~ove that a list xs of length zn can be made into a m.inim.um height tree
:
(ys, zs) splitA l m xs

Now, suppo se we want to' implement a functi on retrieve.specified by


l .. .
xt satisfying {/allen xt = xs fu exactly-one way.
6.1.6 Prove that height = ma;-:Bcree depths by first proving the more genera l
retrieve .. Acree IX- Irit - a result
recrievext k - (flatten xt) !! k
( n+) height - max.Btree down n
In words, letrieve indexes a tree in the same
. . s a list. We can
way that(!!) i11dexe
...
use the fact that
.. .

((<S * ys) !! k = if k < m th~n~ !! k else ys!! ( k - 1?1) 6.2 Binary searc h trees
where m = length ~
Subj~ct to an exrra condition described below, a binary search ttee is ~1 eleme nt
to synthe sise the following more efficient progra m for retrieve: ..?~ tlie dataty pe .
... .. '.
.
=
, '

retrieve (Leaf x) 0 := X data ( Ord IX) ~ Stree.IX Null Fork (Stree ex) e<' (Stree IX) :j

retrieve (Fork m xt yt) k


This is the first examp le of a dataty pe deClaration that makes use of a context:
.I
= if k < m the.n retrieve xt. ~else r.etrieve yl (k - m)
I

the type Stree (!( is introd uced only for types that arc instan ces of the type .i'
This implem entatio n of retrieve uses the. size inform ation stored in binruy .class Ord. Elem~nts of Scree IXno long~r have Leaf nodes, a.1.1d the inform ation
'
to
,I
nodes to. contro l the ..ie~ch for an eleme nt in a given position. What we have . stored .in the label~ has been.m'ove'd come between the two subti.ces for a '
.gained .by this move is a potentially more effiCient ru~~rttative to index:in~ a rcaso~1 explained below. The new constr uctor Null denote~ the empty nee. The
list. In~tead of storing information i.I,1. a list' and using (!!) to retrieve yalues, dataty pe introd uces a kind of tree that is either empty or consis ts of a node
we-cajt..turn the lis't irtto ~ mini.rn~m lieight binary tree via mkAtree, anCI.then with a left subtre e, a label, and a right subtree. This species of tree is also called
use retrieve. It is dear' that retrieve takes a numb er of s teps propo rtiona l to -: a labelled binary tree. The [J.mc.tion flatten, defined by
log n, where n is the length of the list, while. (!!) may take a, munbe r of steps
'
.. ' I

propm iional to Th{! .(Qrmer is mu~h mor,e ~'ficient whenever the ntimbe.r of
n: . . . flatten ' ,.. .. .(Ord a)~ StreeiX - [al
relriev~s is large enough to outweigh .t~e.c'o ~t of compu tmg mkAtree. . . flatten Null = [)
. . .. . . .
.flatten (Fork xt x yt) . = . flqtce_n.xt H [x] *flatt en pt
.~

...
Exercises
.retur ns rhe list of labels in. a tree in lefr-to-right order. i.'he secon d equation
.. 6.1.1 tiowm
..
any binary trees are there. of. size .five1 Write a progra
' .. . . m to calcula te . 'for (la den' sho..ys why ~c h~ve placed 'the label of each.~ree between the two

'

. theOIJ!llber of binary_tr:es of si;te n for a giyen n. . .sub.trees.


a binary tree is ahvays one more _than'
in . There is an extra condition on ~Jements of $tree cx that make them biliary
6.1.2 Prove that the nu.nlber of tips
search trees. The condition is that flatten should return a list in ascending
the numb er of internal nodes. ., .

. ..~ . .. ""'
188
... 6/ Trees 6.2 I Binary search trees 189
-< - '
~. ' . ': .:...... ~.;t ,.:. .
. . ' ' ' . .' . ' .''1'., , - ....._;. . ..
"order. TIUs is >~h~e the type clas.s Ord cort1es .~. 'in 'sy~bois,xt is a binary The function partition is speqfied by :.. ..
':

. . .. .
\.
..
search tree if inordered xt holds, where
' ' ; ' I

....
partition .. (tX- Boo/)- [tX)..: ([ tX),[tX))
in ordered ( Ord tX) =:> Stree tX - Boo/
... ...... ..
,..,. ~ ~
partition p xs - (filter p xs, filter (not p) xs)
inordered - ordered flatten
}"

J, - ~-

The implementarion of parfilion. as an instance of {oldr is left as an exercise.


Here, ordered xs is the condition that xs is in ascending order, ..
The difference between mkStree and mkBtree is that mkStree does not guar-
As its name suggests, binary search trees arc devised for efficient searchmg.
antee that the result. has minimum possible height. For example, the value
The function member, which determmes whether a given value. appears as the
X fn the second equation may be smaller than any element in XS, SO mkStree
label of some node in a binary search tree, can be defiried by - ;,
may quild a tree in. which tlic left subtree of every node is -Null. Whereas the
member :: tX - Stree tX - Boo/ function mkBtree can be implemented to run in Imear time, the most efficient
implementation of mkStree requires at least nlog n steps on a list of length n.
member x Null = False
member x (Fork xt y yt) The new version of mkStree can be used to implement the function sort for
... sorting a list.:
(x < y) = member x xt .. . ::::.
(x == .y) True , '
,.
-
sort .. (Ord rx) =:> [tx]- (IX) , .
>
(x 'y) - .fnember x yt sort = flatten mkstree'
..
In the worst case, the cost of evaluating memberxXt is proport~onal to the height
of .xt, where the definition of height is a modification of the earlie!. definition: This algorithm will be studied ill the following chapter, fllld we will see that,
..
. . . . . . by eliminating the intennediate tree, one..can arrive at a version of a famous
height .... Scree tx - Integer soi:ring algorithm called quicksort.
I
' heighr.Null - 0
height (Fork xt x yl)
. . - 1 + (height xt max height yc.) ..
.
6.2:1 InSertion and deletion '
The size of a binary. search tree i~ the. ~~ber of labels the and the tn tree, ' .
Binary search trees are useful fo_r represen ting sets efficiently, a topic that will
fundamental relationship between size and height takes the modified form
. . . . . - - be consid~,red a~ greater length in Chapter &. "rye will give the gcn_eral flavo~r
height t $;.size t < 2 t (height of the more advanced algorithms qere by implementing functions that add and
.. -. . r)
remove labels from a tree: .,
' . '"'" ' for ail trees t. Equivalently, a binary search tree of size ri has a height h sans The function insert is easy to defuie:
fying . ' .:. -
ins~'rt ::.( Ord rx) ~ tx -
._ ' J
.. Stree tx - Scree C<
... "!' . ...
. ,' .
" insert x Null,;, Fork Null x Null
One can btiild a binary searchtree from a given sequence of values by modifying insert x (Fork xr y yf)
the definition of mkBtree given in rhe previous sectfoi\: - (x < y) - Fork (insert x xr) y yt
..
. ' . . ..--
'
.. . (x == y) - Fork xc y yt
mkStree . :: (Ord
. tX) =:>- [ tX] .- Stree tX . (:< > y) = Fork xt y (insert x yt)
mkStree []
'

= Null
mkStree (x: xs) = Fork (mkStree ys) x (mkSrree zs) . ~ Note that if a label is already present in the tree, then additional copies are not
where (ys,zs) = pr;~'rtition(s; x) x.S. added.
.. --' -
. . ....
t
. . ..
.... .. ... .
" .~

. ... ... ; ., ,' .. . . J

.. 190 . : 6 /-Trees 6.2 I Binary search tre~!!.. . 191


. .
.. . ..
.,
. . . ',/
....
'\
- .
""""! .-- ...... .: ;~~
. .. ,.. ..
: ~
;t'
'
~ . .....

Th~J{mctiQll. d~{ete)~ slightiy mor~ ~owv.Hc atcd: .... ' where. .......,
. . .. . . . ...
~ . . ~.
I . ' ' , ' '
' . .. ' .: .. "':
.. Scree ex - Boo/
delete :: ( Ord :ex> ~ o( - sn;ee DC - Str:ee DC empty
delete.x Null = Null empty Null .. ... = True : .. ..
.. '
de)eiex, (Fork xt y yt) .. .
'
-empty (Fork xlx yt) - False
(x< .y} - - Fork (delere xxt) yyc ..
To check rhls definition of join, we reason
(X7=Y) . = joinxt yt _.
., . f/allen (join xr yt)
(x > y) - Fork xt y (de/etex yt)
{definition of join; assumi ng not (emply yt))
The subsidiary function_foln has to join two trees willie satisfYing the ecquation
flatren (Fork xt ( headTree yt) ( rai/Tree yt))
(/auen (join xt yt) = flatten xt fr flatten yt
= {definition of flatten)
One possibl e implementation is to replace the righnno st emply subtree of the flatten xt * [headTreeyt] * flatten (tailTreeyt)
fust tree by the second tree:
{specification of headTree and tai/TreeJ
.. ' - . : ..~. ... .
=; .
.. Stree DC - Stree DC - Stree oc
.
join . flattf!:n xt It [ftead (flatten yl)] *tail (flatten yt)
.'
join Null yc - )it '
. = {identity on sequences}
. join (fork ut x vt) yt - For~ ut x (join vt yt) . . ~ . . j' ':
(lac ten xt +t {lateen yt
Trus definition .. is .unsatis factory since .it re's.uits ., .er.. ~~ight
in a tree of.&rea~ . . than (
. . ~: .. ~. .. "{

necessary. The,.efficie ncy of tree membership and insertio n depends on the It remain s to implem ent headTree and tai/Tree. We can combine the two func
~

!'
height.t>f the tree being traversed, and we would like to ensure that when joining lions i11 a functioil splitTre e satisfying
trees we keep the b.eight as small as is reasonably possible.
A secOI1d implem entatio n is to promot e the leftmos t label.of.he s'econd tree splicTree .. Stree DC :... (DC; Scree a)
(if. there is one) t<? be the new label of the joined tree. In other words, we can splim:ee = pair (head Tree, tai/Tree)
exploit the identily .. .:. ..
. An effici.en t del'i.riiti:o~ of.,splitTte,e is easily synthes ised, and tuins o_u t to f?e :
xs * ys =; xs * [head y) * ta'il Y_S
'. . . . splitTre e'(Fork xi y yt)'' ..

.. Tllis equad~n is .valid provide d ~s ls not the empty list. Suppos e 1-Ve sJjccify the = if emptY ~t then (y, yt) else (x, Fork wt y yt) .
functions he:Oarree and tail Tree by where .(x, wt) = splicTreeXt !
.
. .. ... :i
..
.hea.dTree :: :: Stree IX - oc .'
...: : .' .; .: ;
:..
'
' ...
.: ... ..\..:. . .
-~. ,, ~:
~ ~ :: ... ,
-,..... ..
.... ..
. .. ! heiulT~ ~e ; =. .. .head. : flatten.
. .. . . . .
. .. ''
., , . ....,
'
'
~ I' ',
, .
' ' ' I, ., ,.
; ' .. . '
..
.' ' .
.. ' ... . . 6.2.1 State the .principle .of structu ral.inductlon fo.r the type Stree DC declared
0

tai_/Tr.e~ .. Stre~ ex - Stree DC... ., .,


in this section, ai1d ilse 'it to' prove 'the fundam ental relationshlp between. .size
; .:
. . . .:. .. .
flattert
. .
: tai/Tree . = tail flatten " . . and height.
.. .. . ...
the
.
6.2.2 Defirie mapStr. . ee fo~ 'data type srree DC.. ..
Then we c~...de fink . ..
.
6.2.3 Define f'o/dStree f01; the data type Stree e<.
' . ' k

join xt yt . .' ' .' +

- {~mpty yc then xt else Fork xt (head Tree yr) ( tai/1iee yt) 6.2.4 Prove that ordeied (insetr x xt) = T111e for all finite trees xc.
' . : . .
' .. .' ,...
.. . .. : .
' .. .. ~
:
I'

'
.. . . l .. . ~.

195
. . .. 6/ Trees .. 6:4./ J{ose trees
... . . ... . :
. ''194 _.. :.: ' .. . .... .: ~~ . , . '
. .. ..
' , , ., . _., , . : ' ~.

c
.: ).'.~ .. .. .. ., t . ...
. '

..: 6:.3'.2 Nex~; fu~ fun~tl~;,n0-it~~~ t~es the list of l;~-~~ returned by level.~ and
. . ::I. sirt~ (Fork'y a fJ)'(Fork ~ d} . :. ' . . . . . .
' . ....

,
:- . : .
: ~ bUilds a list of trees;~ , : -' -
,~ -...... :_:_ _ x:S (y min.~). ; Fork x(Fork y a b) (Fprk z c d) ~ .. . .
y :S (x min z) = Forky (sift x a b) (Fork i c d) mkHtrees :: (Ord .ex) -:;> [[ex]] - [Hlree a]
=
' !

er [Null J
~.

;. ;s (x nful.y)
. ' . . . . y .a b). (Sift. x c ..d)
Fork:z (Fork ' I mkHirees
. . :; .: fo.{q('Cl,dilf:._qy
. . . -.
Fo'r ' br~vity, we have used the' singl~)~tters a, b, c, d to denote ttees in ._tlus ., . Applied to a list oti'~b.els [~: x1 ~. :.j .and a list of trees(~to, xt 1 , .. ] .the function
program. The code.is-straightfOIWaFd and we omit a formal proof th~t t~le addLayer produces. the newlist of i:rees

result satisfies heapOrdered. [Fork Xo xto Xl t, Fork .Xt xt2 xt3; ... ] . .
Let us now.show that heapify takes linear time when applied to a tree t of
size n ana~~il.lim~~ height h ,;, rlO'g(n +1) l Observe that the operation sift is If the list of trees is not long enough:, it is .filled with a sufl'icie~t number of.
applied at every node of the tree arid can take til.ne proportion al to the height empty trees. Give a definition of addLayer.
of the node. Now, t l!~s one tree of height h, namely t itself, up to n-:'0 subtrees 6.3.3 Using the previous exercises, give a definition of mkHtree. Give an in-
of height h- 1, up to four subtrees of height h - 2, and so on. Hence: the total formal argument to show that mkHtree takes linear time.
time required to perform heapify is proportion al to at most
' ':
. . . . . .. ' ' , ' , ' .' ,. ' I

.
h ,.... ' . . 6.4 Rose trees ~ .

h + 2(h.-ll -i- 4Ur.- 2) :1- ,


. . .
+'211.:.1

~ L.
k ~l
zh- kk : -~ . . .. .. .
The ~arne ~rose tree', a translation of rhododend ron, has been coined by lam-
~teps . But bert Meertcns (see Section 6.6} to describe trees with a mulH-way branching
if . . h . . . .. .. . structur<:!. The datatype 'Ro,~e a i.s defined by
L k~'~-~k = zh I. k/zk < zhH <-~(n +.1) . .
data Rose ex = Node ex [Rose ex] .i
' k=l k=l
.
sincell.;, flog(n + l>l <iog(n + 1) + 1. :_ .' ~ . . An element of Rose ex consists of a labelled node together with a list of subtrees.
Finally,.we can use binary heap trees. to obtain-ano ther algonthrn for sorung: . . :.. By definition, external nodes have no subtrees, wbih.t.inter nal nodes have at
.- .
.. . . least qne. .For example, Nod~ o[] is a rose tree, and so is .

" . !
' . -:. ' ;, ' : '\ ' f

sort :: . (Orda) =>[ex]- [ex) Node 0 [Node i [];Node';([. ]):,rode 3 (]]


.. ..
. .: . ' . . .:..

.mk.Heap . ....
# .

sort = flatten ...


' -...
:
. . : : )t_is even possible to have trees with an infirJite number of immediate subtrees;
. Thlsalgori tlun is known as heapsorr. . . - ... ~ fol example,
. .. .,
. .: .
.... '
... Node 0 [Node n [ J I n - .[1..
. . Ex~rci~~s. ' . . . ' ..,. ' . . ]] '

. -........ . tiee t {s.liliitaiy. ~f e'~e~ ri~d~:, .of~has' a finite numbe~-~f


:~=- ..:.-:, ;:ti~~:r one -~ay ~f bllildtiig a ~ree is t~ t~~~ a li~t [~;xi~_::~j.?~~ build a ~iee,\~~1(.< -~_;:~-~~A: "' . . ..
immediate subtrees.
_.;:_, ., ,..._...Xo p~\he: label vf the Jree, x1 , x2 a~ ~_e:_lg~els of the -~.0, '~!fliDediate subt~~e~ .. : . . :.-:~_The 'tree above is therefore not finitary. Note that a finitary tree need not have
. x3 ; X4, x5_, x6 as the labels of the four g~and~S~ughter. trees, a~d so on. This way finite size. A rose tree t has WidtJ{\. if all nodes oft have at most w immediate
.. . of ~hyi~lrig.~ list into subli.s ts of ler1gths ..tha(ate succe~,si.~ep()\1ers ()f .t:vo can. . : ,..:_~jl)l;>~tees. All finite r~se trees)iave..f~te wi~th. A rose tt:~~,is callecf k-ary if every
,
' .: i-nternal node has exactly k immediate subtrees. Binary trees are structmall y
. b~ implemen ted by ;;r.f~nction levels, def\ned.by . . . ..-. ...
:

.. : . ..... . - ;~ ' r~quivaient to 2-ary rose trc.es. - ~ ..


~ _-:_levels . ::' [ex J .~ ex] J .. :. . . . u

the p rinciple of induction for fin1tary rose trees says that, in order to show
0

.
: that a property P(xt) holds for all finitary rose tree.s xr, it is sufficient to prove:
: 0 - -

. . : :: :
... .
.. . -le'l?els. ,;. . leve,isWith 1 .. . . ' .
.. :. '

Give the d efinition of levels With. _: . .. :


~- . . .. . : . ~ -.
i:--'

. ~ ~ I '
..
. . : .

- <!. ..
0 - .
. .... .~

:, I o . : . -~

. ....' - . . .
# .. .
' .
. . . ~< .~. . .
\ ... /. ;._ -. . .
...
6.4- I Rose trees .
~

..,.. . .... :~~~


-196 6 I Trees .} 97 ..
..- . . ' .' .
~. : : .! #,.,~f;. ~ : . . . . ., . ;.: . . . '. . .. . . . ...
. .. . . . :._' . ....... .
. . Tbdold function .{oldRose cruu i.lso be defined forilie<latatype EoseC<. Since -
. :
.
. . .

Case (.L). That P( .L) holds. _ ,


: -:- .. .. .... .. ,e,;,f:......... .
Case (Node x xts). That P(l','ode x xes) holds if P(xt) hoicts for:aUtees xt in the .
. .
Node e< .- [Rose C<.] -Rose .. . C<
(finite) list xes. . . ' ..

: .' . "- . . >' ~.; :~.,!'- "'\ ' ' the function foldRose takes a shig!e' argUment f with rype
If. we omit t]?e first..case,. then we can conclude only ,.. - J for. allthat ~P(xtf'h.olds ..

.
. the
fini te r ose 'trees. Note the restriction .to finitary trees in ' . . . . . - of the
. statement f :: . e<- [/3]-p
induction principle. It is 'po:;sible to formulate a more caretul staH~ment of what . . .
has to be shown in the serond case when xts is a possibly partial list, but we for some type {3. Thedefinition of {oldRose is
will not do so. .. . .,, .. . ... :.... ... .
The notions of size and h eight extend to rose trees. We have ;: foldRose :: (e< - [p] - {3) --Rose C<- {3
(oldRose f (Node x xes) = f x (map (foldRosef) xes)
size Rose e< - Int .
. .
size (Node x xts) - 1 +sum (map size xes) As e~amples, we have

- . size = (oldRose f where f xns .,;. 1 + sum ns . .


height . :: . Rose X - Inc . -
., rr~a0iose'' ~ . {o:t~iR~;~ (' :~~here' /~ n~ =~:ina.~ ~a~Jilt ns
height (Node'x xts) = 1 + maxlisc (map helghc xrs) - "" .. ... :. . . ..: : ' , ' : - : : ' + '; :
.,
where maxlist = fold/ (max) 0 - The map function mapRose for rose trees is defiiied.by : . .

According to this definition , the height of a rose tree is always greater than . rna pRose(e< - {3) - Rose' C< - Rose {3 .. . .
zero. !tis left as an exercise to show that . ,. :.::=---..:
- .mapRos_ef = {oldRose (Node {)
height - maxRo~~ depths .... . . .. . . ...
.. ..'
where .. . .. . by binary trees
6.4.1. :Representati on
~

. .- . '
"
. . ." . I '' . "" 1-~.. , ,. ' ' :0, .-~~{ ' I ~... ,.,.,--.. ; , '' ,', ', , . , " " ""' 4 ~ - t : . ~

depths Rose e< - Rose Int Fii)ite rose trees, with their multi-way branching struct:Ure, 'seem capable of .
depths = down 1 m.odelling more general structures than binary trees, so it may come as a sur
.. . prise .that they arei.n 'onCtOOnecorrespondence: every. finite. rose tree.can be
down Inc - Rose e< - Rose Int. ::. .:.".. . .: .. .
..... represented by a unique finite binary tree and conversely. .The correspondence
down n (Nodexxts) - Node n (map (down (n + 1)) xts}: ,
).t.self is not unique, but one me(hod of associa~ing rose trees ..with binary trees .
... ... . .. .. . '

and
'Ts ~xacrly the same as that berween expressions written_in cwTied or n~mcurried
.. . . .. .... - form: for.exrinfple; consider the two expressions '' . _
. -:- .ex..-~>;~..;.::_=0_. ..
~.-- -.

..: -
(Ord e<) ~ R{Jse.e<
. ... ..
maxRose .. . ;. .. -. .. . ~
. .:.: : .... .. : ~ ~
!

. { (g (X, y) l, h (t)) and (. (g X y) Z (h t)


~-- -~

x max maxlist {mqp maXRosex~~>


! ,.

maxRose (Node x xts) - .


. . . .. ~.. ~

. . A rose tree is said to be perfect if all its extemal nodes haVe the same depth. The expression qn the left ~an be represented by: the .rose .tree
. . .. .. ' .
The basic relationship between size arid height. Say:~ .that: : .~ "
:

..
.. -....:'" - . : /)/ode f [ Node g [Node x []. Node'y
'. . . ...r .h [Node t [ J])
[]].Node. .z [], No((e
height xt ~ sizext ~ ( k I (height xC) - l.)I (k:- 1) -. . .~;- .:;
....
" + + .

. . .... ' .,
. .. . . - - . Thc.expr.
. . .. .
e ssion on .rhe right in. .fully parenthesised f;r;~.. ,is.
.
.. ...for all finite k-ary rose mes. The proof is left. as an exercise irrJnduction. A
perfecT"k-ary rose tree wit:l height h hassize ckh - 1l 1(k -:.; 1 Y.. ~ .. . .. ({ ((g x) y) z) ( h t)
. . .. - .. .. ~

. . .. ....,. : .. . ..... . .
' . . l .. . .. -

>:.. .._ . ..
.. . _.._ ' . '
'
~:
,. ..>..'. .,..... . ." . ..
... . .... :-. . . ;.
.

..
6 I .Trees . 6.4 I Rose tn~e~ ' . .'1 . . .: . '
199
-
-~;~::~ .
.. .. -
. :::_.
_

' . ..
. , , ... 4 -:.\..., ..: .

. ,,,,_cis~:'(Node x.<xts *.[>;tl :.w~ i-ia~!l:. .: ...


- - ,; ..

.and can.h~ reQrescmed ~y, 'tl~e binary tree


:. ' 'I'

..
''

.. .. ... .. .: ~ ...
. I'
'.
. . ' '~
. -. ~ . ' .:

toR (toB (Nodex (xtsit [xt]} )):., Nodex (xts * [~t])


.. ..
:Fork (Fork (Fork (Leaf f>
' (Fork (Fork (Leaf g) (Leaf x)) (Leafy ))) : {se.condproper.~ <if toO} . ...
(Leaf z)) . toR .(l~;rk .(roB. (Nc}Cie~
: .
~t;) )) (ton ~t) = Node. x (xts [xt)} *
. (Fo.rk (Leaf h) (Leaf I)) - . {introdu.cingxU.}iifoB (Node x xts) and yb;, toB x(}
. We can convert a finite element of Rosea into im clemem of Btreecx by a function: to.R (Fork xb Yl?l"? No._df!; x (xts * [xl])
taB, dcf'i:'led by. Where Noae x ~~.~ = toR xb
.. .
xt - tol<yb
loB :: Rose a.- Btr:ee .a
toB (Node x xeS) = fold/ Fork ~Leaf x) (map taB xts) In the last step we used th~ specification of toR t\<\-icc. ln. summary, V\:'e have

rn words, to convert a rose tree to a binary tree we first convert all irs subtrees
tree.by folding
derived
..
(via map tpB) and then combine the results j.nto a single binary toR (Leaf x) = N,oa~ x (] .-
fromthe left, following 'the left associa tion order of applicati~n. . . . . . '.
....
.. toR (Fork xb yb) = "Nod~ x (xrs * (xt)} '
... ..
. It is trior~ difflcult to implement the i-nv~se correspondence. toR. ~his func; ~here Node x xts = toR xb
..
.
.
han is. sp.gcified by . . . .. - . .
. .: :.. ..,, xt
'
"" . toRyb ..
'
.. \ ,

. .
t~R Btree ix -
. Rose <X
.
. This 'program is not very effi.deqt since appending xt to xts tak~s time propo_r- .... .
.- . . .
..-.. . .
~

toR <wB
.
~t> = ~r ' tional to the length of xts. F~r ainore efficient version, defme
<
' ,; ,:

.. -:........ ..... . : . . '


:i
where xl' t .anges over finitary rose trees. In order to syntl1csise a program from
,. . .#

collec;t :: Brreit.'<;...., -[ Rose a] .:... Rose a ,,.,


. this specification, y.:e will .need the f9llowi ng twoproper~es of lpB: ..
.collect xb yts = Nodt x (~ts. * yts) . where.Node x xes = lOR xb
. -: ..' .
toJ! (Node,x []) Leaf x .. = .~
..... I'
In particular, toR.x.b .~ collect.x ~ [.}: It is now easy to derive that -: .. :
, . loB .(Node. x (xts.
.. ..
[xt] )) = Fork (toB (Node
. . .. : . .
x xts)) (toJJ xt)
:.. . . . . *
. " .. ' . .
. . . , ... . . .
' I
,f
.. .. coll.e.c t (Lear'x ryts . .;.~;_ Node x. yts
7 .

.The firs t e_g,uation is. ~e~ia1e from the d,efinitibn of tpB, and. the scc.ond c~ ..

be
proved by firsrapplYiug rhe. third duality theorem to :rewrH~ the definiti6n :
of to.Bui..the fotm . :. . . . . <...... :: . .: . .. ... .' ' " .':..
collect (Fork xb yb) yls = .. collect xb (toR yb: yts) , - ..
. .. . .
"
., I
. . .. . . The idea here is to use an accumulating parameter to elimina te the expensive
. .. toB (Nodex xts) .:.: foidr'({lip Fork);(~et;i(x} . (r~verse.(map taB ~ts}). ": . * operation,s. The accumulating parameter technlque will be studied ln the ... .
behiricl
.; :
' : +

. : ;.follo.wtng chapte(, but e~actly the sanie id.ea is the 'tiaQsfotmatlon or' .. >:.
:. .. '
to
' '
..
.
. ' . . , ,,
~ " ,, ; '

. Further d<:taiis are left asa.n e'xer~lse . . .. . :... : . ':.... ..-:: .: :. . '. :.:::.:: :
' ., ' I ' \
~ ' ' ' '

. .. tii~ .riaive
' ' '

. d~finitl
- on of reverse the more efficient o~e.
The syhrhcsis of a prog'ram .for toR isbyt ases. . . '. . : : . ::. ' .> : - . . . ...
.. . . .. . . , . . .
, ' +
..
<o

. . . . , . ....
.:
We reas~~: :' '..
:
" 6.4.2. Depth-first and brear.lth:~r~l-order . ..
'

Case (Node X ( ]). . ' ~. :.;. .. .. : . ~ . .


. .
.'

. ': to~ (rein (Node.x [])) = Nod~x [) The function {latten lists thciabk'> of a rose tree: .. ..
..
t,

. . . . . . ~- .:: . ..:~~.. .. .. . . ...

.. ~ : .. ''[tirsq)r~p~rtY of toR}
.. ' . ' ' '

...... ...., ::- .. .


. . . . . flatten , :: :: Rose 0< - [ L'<) .
flatten. (Node x xts ) =...x:. concal (map flatten xls)
. :~
. .. .. Wfl. (Leaf x) = Noqe x [ ).
. .... .. . ....
~

. ' . .. ; . \ .~ ~. .. ..
... .
.. , .. .
. : ' . . 'I ' .~:. ~

. .... . .: ' .f :. ....


..:,

.. ..
'.
' ~ .
.. . ~~
\;. .
'
.. . -' ' ... '' . . .
.' . ., 200 . : ~-''~ 6 I Trees . 6.4 I Rose frees 201 . .
. ..... . '. .: ' . . , 4 .. . . : :o-t'!i , t,'':~ . . : ' .
. ~ .. ' . ' : . . ,. =. : ..~ 'J-...~:... " ~-#:~... . .:-.. ..,_
. . .'
. Til!S ftinction prodliccs, in order, the Jaber of tli~ tree, the !dbel~:Q,f'the
C"
l~f.tmo~(, . Suppose we defui~ index by lo.
'


'
1 : . : .... .. . ...... .... .
subr,ree, the labels of the second leftmost . subrree~ an~ so on.: T::!lbels are pro-
. ' t ,. ~

duced in wha t is known as depth-first order. As we will show in the following index lnt - [[e<]] - [e<]
chapter, flatten takes time proportional to at most n log n, whesoe.-n is the size of if i < lengch xss then i<ss l! i 'else [ ]
iiffie
index i xss -
. of th~ ~ree, but it is possible to implement depth-first order in proportional
to n. Equally important, the amount of' space required ro ca'fry out dep th -first Then we can specify combine by the condition
order is proportional tQ at most the height of the tr~e qi~ll'l.pli~ by the maxr index i combine ~ concat map (index i)
imum numqer _of subtrees of any node. The COQclusion is that depthfi!s t order
is efficient qoth in ti.me and space. . - : .
. . .
for all i. Since coneat = '{oldr ( * ) [ ], it seems reasonable ro look for a defin.ition
..Tl~'ere is another way of. flattening a TO~~ rre~. one that works Jive! by level. of combine of the form
The idea is to produce the label of the tree, then the labels of its immediate
subtrees, thim the labels at the next level, and so on. This wayor producing combine [[ iX]] - (ex]
the labels is known as breadch-firsr order. An example of a problem in which combine - {oldr (e) [ )
bread th-firs t order is required is given in Section 6.6. Breadth-mst order has
for some suitable operator w. Appeal to the fusion law for {oldr gives us the
th~ . adva):1t~ge that it can be applied to ap iiJf:i.nite ~re~, prQ~u~Jng an infinite
list:of. all label values. On tb.c other hand, a deptli-fir.st orderinjfof an.infinite . specifiCfltiOn of e: . . .. . . .
tree' will not in general produce an infiiTite list containing aUth~.}flbel values: in ' '' ' I

index i (xss ED yss) => ' ii'ldex i xss ti-. index i yss
particular, if the leftmost parh is infinite, then flatten vvill produce .. only those
. ;

label values along this path. - ;"


It is now a straightforward exercise ~n synrl'~esis to derive the following program
.U;ili..!<e depthfirst order, the breadth-first ordering. of a tr-.ce.c.anilot be prq- for w:
duced from a breadth-firs t ordering of its subtrees. We can, ho~:v.eye r, define a
'' I ' , ' ' o ( ,.

flm ction leve ls by ' :t.: (!D ) [[e<l] - [[ex]] - [[ex]]


..
.;-., [ ] e yss
-
: ; yss -
. levels .. Rose ex - [[,(x) J
(xs : xss) e [ ] = xs : xss
levels (Node x xts) = [x) : combine ( map levels xts ) :.
..
. ..
..
; (xs : xssf Eii:(ys :yss)-.. -= ;(xs ys) : (xss.e yss) .*
..... ..
. . ;
. . .. .'
The qperation (ED) is similar to zipWith (* ),except that the lists are .not trun-
.
for a s~ table function combine, and 'tberi defirie . .
..... . ' :...
. . cated to the length of the shorter one.
llivel :: Rose ex- [ex] .- Although the. t\o\'O procedtires, {lateen and level, have the.same time com-
level = concar . levels .. . . : : . . .1:
~:

plexity, they have quite different space.costs. The space required ,to carry out
' .
evaluation of level t is proportional .to the size of r. To appreciate what this
Tl~e-.f~netion le~el produces labels in brea.dthfirs.t. onkr.,_.':':.~ ~:,::;:~ -. . second statistic means, imagine a tree o{height h with k subtrees at .each node.
t he problem now is to specify combl'rie::.[[a')(.:..[~j,~;fhiS' i\inction has :t~ : Then level requires space proportional to hk whereas !7atten requires space I

c::oncatenate corresponding levels in the argument iisr. Fo~.e~am:pic 1 iiven the ..' proportional to h x k. It. is sfrnply not .P.ossible w flatten a large tree using
llst' 0

0
. :"":.,. :~'" o0 0 M' 0 0 O ,
. , . breadth-first order without running out of available space. This point is taken
. " , _

" .
, J

up in Section 6.6, which deals witha prob)Cin re~uiring jus t such a tree..
;' < ' ' , ' ' . I ,,. '' , , ... ',, ~
. :: .[ [[xl,x2], (x3, x4,xS],(x6]], {(yl]]. [[z1, z2,z3],.[z4]J)";:' . .
.: ~ . . ,' : :.. . . : ;: . '
. ...
'
.. . .
. ....''. .."' ....-: . ExerCises
~..: ' '

.the :~esult'rerumed by combine will be. tl~elist


.
.....
. : .:. ([xl ,x 2,yl ,zl ,z2, z3],[x3, x4, xS,z4],[x6]]
.

.. .. ,.:...
:-:
. 6.4.1 What relationship, if any, holds between the size and .h eigh t of a rose ...
tree?
'

. . . ' .. ;
. . ...' . ..,.;;-;
. .. I ,.,, _.
=~

.'~
..
.. . . . .. - .~~.. .
~4o
\
. ...

:
.. .;

~ -..
. . ' .
203 .. ~ .
. . . . . .
202 . .
.- ' . . . . . . . .~~ . :' . ~
of th e te xt ca n be re'co vered by decodmg_
e. D oe-scoB t prod-uce-rui ...........4' d1a.racters
fixed Jength. code, so the
.
.
;,.

6.4.2 Su ppo~e ti s a finit ary ut b n ruu.te-ros e tre


ea ch successive group
eigh of
t bi ts .
,
the ired to code a te xt is to
1.
. of bi ts re qu
. bmary tree? to ta l nu m be r
- : . -. . - One idea' for reducing de s, an d sc ek .m st ea d a coding sc he
me
' f . . we also -le ng th co
6.4.3 The effid en( defini.tIt?n o coR ~as ,ob~amed in two st ag es, l;>Ut if ed

, then
ab an do n the notion of fix rr en ce of th e ch ar ac ters in the text. The
make us e of th ~~ binary trees xb ue~cy of. oc cu
op er ty tQ xb ) == xb fo r al l fi ni ba se d on the relative freq tim at e th e nu m be r of times each
we c . d . . e pr
B (lo R te xt , es
by pl e pi ec e 'of
an
It m one s~age_.-- Defin eco ll e~ t
ba sic idea is to take a sa m co de s fo r th e m or e fr eq ue nt ch ar ac te
rs
ch oo se "'s ho rt
. character appears, an d ph~. ~f we take the co d.e
s
:: Btree a - [Rose a] . ~
Btree a th e ra re r on es . Fo r ex am
. co/fee~ ap toB yc;))
and lo~ger codes for.
collect xb Yts ==. toR (fold./ Fork .xb (m .
. ..
n in th e .text.
'
r - o
llect to derive the one give
Use thi s defin. i ~o

, p of ~o e - 10
dfo (for depth-first or de
r) by
G.4.4 D efine th e fu nc tio n X - 11

[R os ea ]- [a ] be co de d as th e bi t se qu ence O lO llO of length 6.


dfo :: th en "text" can -m us t be ch osen in :su ch a way as w
is e .Lhat c;o de s
d(o -~ concat:. map, flatten It is i.nlportant to re(\l er ed un iq ue ly . To illustrate, su pp os e
xt can be de ci ph
en su re th at the co de d te
...
program .for d{o:
Synthesise the folloWing th e co de s ha d been
.. -
- . . . ..
d{ o [ J . == . [) -
0
=.' . [x ] -it dfo (xts -t+ )'t s)
t . .<

d{o (f;l~d~x xt s: yt s) ' e - 10


.... ..
Ho\.v is - ~atten defined fu terms of dfo? X -. 1 th 5.
der) by
5 efine the ~cti~n . bf~ (for br ea dth-first or . ld be co de d as th e sequence 01 01 0 of le ng
6
:~ . ' . .
D
_ . .. Undek this scheme, "text"
w ou
be 'co .d ed by ex ac tly th e sa m e se qu en ce , and
" would
However, th e st ri ng "tee ay 'o prevellt the pr ob le m
'

b{o .:: '[Ro;s-e.q] ~ - [e<] t i~ w an .te d: Th e si m pl es t w


els obvious!}' this is no t w ha de is a pr op er in iti al se gm en t (or pre/1x)

bfo == concat : combine
: m ap lev s so th at no. co
ar is in g is to choose code . .

-~i s \y iri i prognlffi. f~r b(o~ .. -. of an y other.



..
synthe
Asa d.i.ffitult exerc_ise_iri _
.. de riv e the fo llo
ue de ci pl ier :ab iliry , w e al so want th e coding to be
As well as requiril\g uniq m in ilnis es the ex pe ct ed le ng
th
:: [R!Jse a] - [~] optimal. An optimal codi
ng sc he m e is on e th at
j s. n, have prob-
bfo ch ar ac te rs fo r 1 s.'
prec ise ly, _ i~
. _ Cj .
of th e. co de d .te xt More

des with le ng th s lj su ch
_ _ :_ []
b{ o[ ]- oo se co
-H- .xts) ' - . , th en we \V an t to ch
* abili_ties of occurrence p1
.
b{o (Nodex.~ ts' : yes) 7 _ [x ]_ bfo (yts
. . , . . .-. .
. . _ . . .. - th at
: trees __ . . .. . .. . .. - ..

_6 s Ex~Ie: Huttm~i; r
I n
Pj{; ...
'; "
' ,'. ' _;, ' '
~ ' '


I ' '
~
~ ~;
' "' .', ' '
'' , ', '
'
.,
',

m of da ta co m
' '

.. - ' : ' ' '


.,
A good lllustrati ?n of t11~ use of ?mary trees is in rhe pr ob le
'
' '
. '

J~l
.-
.pr es si on . A . ell, it is. often n.ec...essary
' ' . .'
. , . ..
\ :'

~ qn ly to cn .Y
. . . to st or e fi.lessomf:rco~r.ute us er s k'\'}o
1
w
b
r to

fr

ee preci~J.lS is as sn'lall a'i possible.- al co de sa tis fy in g th e prefbc pr op er ty
m at 10 n as c t le _in or de in g ru l'opt i.m
. , or
: .' om pa ct Y as P_ o ss
io n to be st or ed =: O ne m et ho d fo r co ns trp ct Huffman). Each characte
r ' .
~p_ace for ot he r . s. e tl~ e.m fo rm at . (a fte r its in ve nt or , D av id
is a 'rext co nsis;- m?r; :urg:,~l~~ p~pose Su pp os
u'd co de us ed rn Is called Huffman coding wlvch is de termined by
the
0 ~ s_e qu en cc of ch ar ac te rs . Th e 1$ 0 st an dr na ry tre e, th e st ru ct ur e of
_H k ll . ID g _
en t ea ch of 28 = '2 56 'dift'er.en t cl1ruac ters, so is st or ed as a tip of a bi a ch ar ac te r ci s a se qu en ce of bi na ry values
bi ts to re pr es e c,0 de for
. as e uses el gh t
of ir ~f or ma ti d~ l. Th e ISO st an da rd is a co m pu te d frequencies. Th
nt ai ns 8n bi rs
a t~xt of n ch ar ac te rs co .-
. .. . -
,.
. ..
. ...... .
., .. . _..
... ~-" , . ,
- .:.'\~ -~
6.5 1 Example: Huffman rrees . 205

. ~-he. functi~n trcms{orm produce's ~ table consiiaing ofa.lisrof pairs <i charac-
ters ~nd bit sequences. Now we can define
' ' '

. 't')
' 'x')' (Leaf 'e')) (Leaf
Fork. (Fork. (Leaf
. .
~ .
\~ ~. '
' . ;- . encode .. Btree Char'.:.. [Char)- [Bit]
In thi$ tree the character x is coded by oo, the chara<:t~t "e"oy 01, and the encode t ; 'conca.c :ma,p'(fo.okup ~odetable)
character 't' by 1. __. ,. . :.--. ~ where codecable "" transform r
There arc four aspects to the problem of implcm~ni:ing Huffman cow rig: (i)
collecting information from a sample; (ii) building a binaw tree; (iii) coding a
text; and (iv) decoding a bit sequence. We will
deal-with codh1jpand decoding
lookup . .
Jookup ((x, lis) :'xbs) y .-.
.. CodeTable- Char - [Bil]

first, rhen collection, and finally building a tree. .if.x ~= y then bs else lookup xbs y ..
. ,. ... .. '

The time required to perform a lookup operation depends precisely on where


6.5.1 Coding and decoding in the table the character is found. H seemssensible to place characters that
. . . . are likely to appear in lhe input before characters that are Jess likely. Since
The function decode for decoding a bit sequence with re~pecr to a given Huff-
'

the frequency of occurrence corresponds inversely with the length of the asso-
man tree is fairlysrraightforward. We use a prefix of the hitsequence to traverse ciated bit seque)lCe.{aftct.all, 'th'at is the whole point of Hqffrnan coding), the
the tree until a rip is reached. The associated character is then proclttced and, ' sorted
, ' ' I ' '" ,
:conclusion Is tl1ar the cod~ table should be in ascencling order of length
if the remainder of the bit sequence is not empty, tl1e 'tree is traversed again to of second component We hence define
find t_he next ~haracter . .It is assurried that the bit sequence CQr].'espondsto a
correct encoding; if it does nor, then decoding will fail. The program is transform (Leaf x) - [ (x, [ ])]
.. . ... . .
decode ::. Btree Char - [Bit] - [Char] transform (Fork xt yr) = hufmerge (transform xc) (transform yt)
decoder cs . . . . -' .,.'.
.. The funcnon hufrnerge merges two tables, adding a zero hit to all ~9des coming
= if rw/1 cs then [ ] else decodel t cs :. ' . '

:from rh~ fii-st table,. and a..one bit to codes coming


where dec9del (Lea( x) cs -
-,
.. ...
'
x : decode cs
' . :
:"'-
t
' '

.. - . ,,.., ,... ~ '~..; :,:. .. ....::.,.


. f~om .the second. table:
~ .. ,.,.. ... . ' .
aecodel (Fork xt yc) (0: c~) = decqd~~ xt cs hufmerge :: CodeTable - CodeTable - CodeTable
decodel (Fork
. xc yt) (l .: cs) - decoqer yrcs hufmerge.f]yc s = [(y,l:cs) 1 (y, c~) -yes]
. . :.
The rime for decoding is clearly.linear in the length onhe bit sequence, which
"
hufmerge xbs () = [ (x, 0: bs) 1 {x, bs) - xbs]

. is.the best one can achit~ve. . . ~ .. ::-. \ .._, -' . :


The function encode for codihg a sequence of chai'acters with respect co a hufmerge { (x, bs) : xbs) ( (y, cs) : yes)
. . ' . .
given Huffman tree is not so. easy ro define if one .wMt.s :4v.:effi~Lent program. length bs s ler~gth q . = (x, 0: bs): hu{rnergexbs ((y, cs): yes)
... .
H~frt1an t'rees are good for fin~l.ing th~ c4aractcr ~~so~f.ati~ Y.-,1 a given bit otherwise - (y, 1 : cs): hufmerge ((~. bs): xbs) yes
seqtience, but poor ar finding th'e biLsequence associated'Wfili:a gi~e n character. .. . .
What v...ewould like ro do is first transform the tre.e into .some1hing.for which the The efficiency of che program can be improved substantiall> by avoiding the
second task can be made 1rtore effieient. One possibility is' to.cte'fihe a function recomputation of the lengchs of bir sequences. Code tables should therefore
' . . ..
' .:.,., . really .hav.e been lisrs of triples:
:tran:~rorm
. ~..

.. Btree Char - CodeTctble


....,. ... . - rype Code Table = (Char, [Bit ]; lnt}..
where ' '
. ; . ' ~

The thir'd component describes rhc' length of the second. We will leave tltis
~. -type CodeTable = [(Char,[Bir]) ] - . optimisation as an exercise.
.....
'

.. .. ........
'.

. ..
~

.. -~'-
# t ' '

. 65 I -.:ample: Huff.roan trees 207


-,0 .
.' . , . .....
... ;. , .: . .. . . . . :. :. : .. . ' :

6.5.2 Analysing the sa~ple '


.; ' .... . '. ' , In.qutli.ne, the proceduie ~or 'bi.tilding a Huffman tr'ee is first tQ conver.t the
. .. . .
We will assume that the sample contains all the ch<iractcrs in the text to
'
.
' . . above list of pairs info a'list o'f' trees; and then repeatedly to combine twoti'!~es
with lightest weights until just one tree remains. The weight of a tree consisting
coded. Tpe reiative frequencies of the charaqers in the sample can be com- of a single tip is._the weigfit of the ch~acter contained in the tip, and the weight
puted by first sorting to bring occw.:rences of the same character together, of a tree consisting of a b.inary node is tbe sum of the weights of its two sub t~ecs.
then replacing ft+IlS of a -single character by a pair consisting of the charac- . To avo.id recomputing weig~ts, it is convenient ~o label trees >Vi til. their weights.
ter and the number of times it is repeated. Finally,.' we can sort the result in Hence we introduce the:type .
ascending order ?f frequency. The program is ...
. .data Huff - Tip Int (har I Nodeli1t -luff Huff
sample . :: . [Char)- [(Char,lnl)J : ,. '
'
sample sortby freq collate sortby id
' ' .
When the tree has been' built, we can strip off the weight information by a
function unlabel defined'by
Recall from Section 5.2 that. the function sortby has type
..
. sortby -:: (Ord {3) ~(ex- {3) -[ex]- ~c:x] Lmlabel .. Huff - Btree Char
un/abel (Tip w ;><;)

'

= Leaf x . , .
. : I.n partic~ar~ 's'ortby id :: [ Cl~w) - [ ~har] s.orts.a list of charact~i:~ into ~p~~~.
0

'

. : uhlabel (Node w'xt yl') '.;; .Fork ( unlabel xt) ( unlabel yt)
' . ' b~tical order.' ' . " . .. . " ' . . . ' . .
'
c~llate replaces runs o( a singl~ character by the character and
' ' '
T.be functio~. ' The function mkHuff for building a HuiTman tree takes the form_
the length of the run:
' .

.. (Char] - [ (Char ,.Jnt)] .. mkHuff .. [(Cfwr,InOJ- Huff


collate .
U
' unwrap until single/on combine map mktip
= () mkHu{{ -
collate
col/at~
. .. . (x .; xs) = (x, 1 + length ysY,: co!iate zs where
where (yS,ZS)= Spa11.(==X) (x:xs) . . ..
' ' .. . '.. ~.

mktip (Char, Int) - Huff


Recall that spcm p xs = (takeWhile p xs, diopWbife P xs) .
mktip (c, w), = Tip_.w c
Finally, the flinction where
. . .. sortby freq,
. ' . . . The. standard function untii p f repeatedly applies f until p becon'les true, and
{re1 . . ( Cha,r, Inc) - Tnt.
:: _ ' ' '

sirigiruon' is the test for a singleton list. The effect of combine on a list ts of
fieq (x; m) ,., rn
trees is to combine 1:\vo trees in l'S with the lightest weights.
so;ts a list ~f pairs il~to ascenclli~g 'order of rrequency. In order to d~termine at each stage which are the lightest trees, we simp~y
. '
0 ~. ..

keep. ~h~ trees in ~crea:$ing order of weight. Hence ..


. 6.5.3 -~uildii!,g. aHuffmap tree.
0 0

. . <> . ,.
0

... [Huff] - [Huff]


turn' t'o. the 'most 'ill~er~sting part, which is l:iuild.ing 'a Hu.t'rmant~ee:
c;ombine
No~v we cornbine,(,l(t :.yl : xts) ' = insert (Node w xt yt) xts
Having analysed the sample, .\ve m'e givena list .~f .pairs: ,. .
' ... '. . '
.' where w = weight xt + weight yt
. '

... Huff - Int


where c:J (0.' ~ J ~ ri) ;re the characters a~d ~~i '(0 ~ J 5.. n) are,~~bers. called
weight . ...
. .

weigl1t (Tip w c) - w
~eights, indicating the frequencles. The probability of character CJ occurll?g ts
therefon~ w'-; w, where w = I Wj, We are also given that wo .~ .Wi :;; .. . , ~ Wn. weight (Node w x Y) . = w
J. . " . '
...' . .
\. ' .. -
0

' ., 0
' '
.. o I o
0
... ""'!'
208 ..... . . . '" , .... ~ _. .,. 6 I Trees 6.6 I '<ample: Meertens' number
, ', l l' " ' ',
. . . ...~ . : ::-
,:.... .. l,";,;.s
' ;!'.._._
. ,.,; . .
. 209
The function insert inse rts g tr~e in the correct place t~. w_a\n .:. .r. .. .
a
~

t~~ theprop~rty . The average, or expected, leng th of character code is -' ...
that the list of tree
. s is in asce ndin g orde r of weiglit: . . ..~ : . :' > :- . .
- -
insert :: Hu ff- [Hu ff] -[H uff}
... .
insert xt y~s -
uts * [ xr] -tt vcs

-. ' .
.
where lj is the nurnher of bits assig ned tochar acte r 9- In the
above example
.
- .
whe re (uts, vts) = span pycs .. . . ~
this val\lc is
pyt =
.
(wei ght yt !> weig hl'Xt )
. .. -
((U+l3+17)x2+(8+9)~3)/(8+9+ll+
Let us see this algo rithm at work on ~-example:
l3+17)- 2.29 ...
C.o~sider the se_q~~ce
.. . . ,.- ' . The crucial prop erty of a Huffman code is .thai H minimises
expected length.
[ ('G',
. 8), ('R',
. .9), .('A', 11 ), ('T',
. 13),
. ('E'
. .
,17) ]. Putting it anot her way, a Huffman tree has the prop erty that it
is abinary tree,
of characte rs and their weights. The first step is to convert tllis over tip values w 1 , \.?, ... , w,1, which minimises the swn of the
'weighted' path
into the list leng ths Wjlj for 1 !> j !> n. For a proof of this f~c t, the read er
shou ld cons ult
[Tip 8'G' , Tip9 'R',T ipll' A',T ipl3 'T',T ipl7 'E') the r.eferences given at the end of the chap ter
..
The next step is to combine the fi:~t t>~o tr~es and inse ;t th~.resuffln_.the correct ..
Exer cises . . ~ .
place: . .
6.5.1 ~'C]Jlain why a Huffman code has the prefix prop erty.
[Tip ll'A ',
Tip 13 'T', 6.5.2 Construc t a code whic h does not satis fy the prefix prop
erty, but which
Node .17 (1 'ip 8 'G') (Tip 9 'R') , . neve rtheless is such that every text can be urliquely de~oded.
Tip 17 'E'] 6.5.3 Optimise the definition of tran sform by including len~
th info rmation in
. code tables.
The resu lt of'th e.sccond step is the list .
. . ---
.. .-
[Nod e l7(T ip8G )(Ti p9'R '), .. 6.6 Example: Meertens' number
Tip l7'E.',. '. . ' .
.: - ... .
Node 24 (Tip 11 'A') (Tip 13 'T')J -The _a im of this section is to illus trate theuse of rose trees
. ..... in organising the -
.
sear ch for a num ber With a peculiar property. The problem conc
-;

The third step give s erns the prime


. - f~c~o risation of n umb ers . For exam ple, 400 = 24 352 and 432
'
. .: .. . . - = 24 33 50. Sup-
[Node 24 (Tip 11 'A') (Tip l3 'T')'; ~ pqs e we define g(n) by taking the decimal repr esen tatio n d1d2
.... ch of nan d
, '
is
-s~ttil;lg g(n) ::, 2t1, 3't f! ... pfk, where pi: 'rhe kth pririle. t hus,
-
34 (Nod - ..
Node
. .. . e 1 7 (Tip 8 'G')
. (Tip. 9 'R')) "
-
g( 402) .;. 400
(Tip l7'E '))
. and g(43 0) == 432. The num bers ri and g(n) are not always so
., ... ... . i'' -
close toge ther as
thes e t\vo iristances suggest; in 'fact , most of the time they are
~. ' '
I ' " ' I

-
'

wildly different.

The- final tree is .. ... The_ques tion is: do they ever coincide? .
. Thefunction g is namec! after Kurt Godel \.Vho exploited the
.
.a
. '
idea of coclin g
Node 58 (Nod e 24 (Tip 11 'A') (Tip 13 'T'))
.
- -. sequ ence of char acte rs as a sing le num ber in his famous pape
r on the inco m-
(Nvd e34 (Node 17 (Tip? . 'G') (Tip 9 'R')) --
.. . ; .
'
. . . plete ness of arithmetic. llere we are using the sam e deVice,
codillga tiurober
(Tip 17 'E')) by codi ng its decimal r epre,sent ation. .If n = g( n), then n is called a Mee rtens
. - .' number. The first Meenens' num ber was nam ed. in hono ur of a colleague '
n this tree the char acte rs 'A', 'T' and 'E' are coded by two of
bit sequences and 'G'
..ours
. ; Lam. .bert Mee nens , on the occasion of his twenry-f1ve years at the CWI,
and 'R' by tluee-bit sequences. ...' . -
.....
; - ~

Ainstcrclarn.
-. .. . . . -
'
" .
.. ...
-
.:
,. .. ,
..
. 6/Ti e~s
' .'. . ..
. 6:6/ Example_: l'vleertens' number ' :. 211
210 . ...
in
-!.t

brea dth-
th~ existe~ce of arvreerteiis' number'is: ~ot at' all ob~ous. The i:ltirnb~r lias Recall from Section 6.4 that Ie\lel pr0d uces the labels of a rose tree
10 subtr ~es;
to be even, and_a little men tal calculatio n shows that it cann ot have
on.e, two, fifst orde r. Each node in thetree iw ee, apar t from the very first, has
with a
or three digits. 'For' example, any tluee-cligit num ber woul d have to
end with a one for each digit. The first tree has 9 suqtr ees since decimals begin
hand , there nonzero digit. Eacl1 node'.'in tl'le iree is labelled with two integers,
n and g;
zero arid so be b oth diVis ible and no.l divisible by five. On.th e other path in the.
rue some-n ear miss es; the eximiples above 'sh.m~ that tllere arc numb ers nfor where g = godel.n and tf:te d ecijl1al repre senta tion of n defines the
the.~~ atue tree to the given node ~ TJ~e rr~e t).l~refore has type Tree, where
which n and g( n) differ-by at most two. Furthermo re~ as n increases . .. '

ld ,
g(n) jump s abou t qwte a lot, so there is no obvio us. reaso n why ,thcy shou data Tree = Node Label [Tree]
.never coincide.
of. the type lAbel - (Iii'teger, Iriiegir) ..
The p roble m is qot specific to .decimals of co~rs e. ln base two each
'

astarting label' of (0,1),


' '
y is 110
n umbers 2, .6, mid 10 is a. Mccrtens' nwnb er. For example,'6 in binar The follo wing p rogra m builds an infirlite tre~ with
three: 10
and 6 = 2 1 3 1 so. The nwnb er 10 is also a Meer tens' num ber in base which is corre ct since g(O) = 20 = 1:
but finding
In terna ry is 101 and 10 = 2l3S . Such resul ts are enco uraging,
1
on the
the Meer tens' n wnber for mere bits and byte s is not enou gh. Mere tens, glree .. Tree,
otj1er hand , woul d be qljite appro priat e. gtree - snip (mklreeprps (0,1) )
Our ai.n:l~n ow is to ,cqnstr uct a program for findi ng Meertens' numbenL:
:fh~ .. .., .
. .. .. .. ... . . : . ',
b eginn ing
.
most obvio
.
us. meth od' .is
. . . .to. .defin
.
e . The flinction snip snips ort: Fh~.lefm1os t bran ch to r<;;move decim als
with zero: ..
/m ertens .. [Integer) '

.
meertens = [n I n- [1 .. ], n == godel n] snip ::.. Tree - Tree
.. ..... ... .
. . snip (Node x ts) = Node x (tail ts)
:: Integer .:.. Inceger
~

godel
go_del n =. prodLICt (zipWith ( t) prim es (digits n)) funct ion .
,. The work of building the ti:ee ls.i;elega ted to the function mktree. This
list prps
takes an infin ite lis t prp.fof_th e'pow e.rs of each prime and a label. The
'
The func tion digits re-n;r ns the digits of a natu rai n~mber. Tlie list
of.pr imes .'
is defined by .,
cari be defiried in a nilm ber of ways , inclu ding . ' . .. . . .. . ...
. ~. . .
prps .. [ [lnc~a~r i) .. .. ,.. .
.:

. . ...} . .
. primes .. :: . Unt
. ~ .. ...
. ... J: . "
~

prps - map POV(e~s primes


. prim es. .=. [p lp- . {2 .: ].prim
. ep]
.. .
.:.
We wil( leave the definitions .of-prime, product, and 'digits as an exercise.- nwn- . Th~ value of powers pis an infinite lis t [1, p, p , ... } of powe rs
2 of p:
The value of_ meertens iseithe r an infinite list (if there_are an infini
te
'
. .. b~r of Meertens' ~uml:iers) or a parti al list. ln eithe r ca~.e, evalu
at~on ~ ~ot . powers :: - Int eger - [Integer)
out to be .
term inate. Evcri if we ask forhead meerlens, the comp utation twns .: . : ....
powers p = . .uei,a ie<v xrL . _..
..
painfully slow:: Tli~ GGd~l -numbe~ of each cand idat.e is. comp uted
af~e~ti-iui~
~

' . . - : . ~. . , . :~. =.

t~listakes a ~igrufi~~n-t'niimber of ?teps : . . . . .. .:...'.' : Thestand ard func tion i(er;qte is del'ined by
As prep aration for a chan ge in repre senta tion, we can r ewrite th e
de~tiori ...
:: ((x ~'1a) .::: C< ':.:., ( c<]
or 1neeitens .in the fo~fu: ' I ' . '
... - , ;.. ; , iCe rate
. .. ... . ., . . ' \' ~
. .. . .'
= x.:. i.r..~ra(e
'
.
.r:neertens. ==. li-r(( n,g) -mapgn [l .. J,n==g] .. : :::.~ iterate { X
. .f.. <f.x)
.
' . ' .:.:.
..,
.. . ~. *b.~re gn .n ..; (n, godel n) .
.. . . . . .
-:~.
. ~.. . Now we define
... ...
. .. . - . '
..., ..
. . '
' ...
. .:. . '.
, .
. The. .idea. now
. is to
.
. . . e a rose tree. gtree' so. that
defin .
-
..... .
~

' mktree ... [[fnie~er]J -La bel- Tree


.
mktree (ps: pps) x = fi9de x.(map (mktree pps) (labels ps x))
.,

level grree = ...map gn [1 .. ] .. . .


. . . .
-
. . .:
.. ,. . . .. ... ,;
. . ' . , . .

. -.
~ .

. . . .. .
'
o '
.. ~
lo ' 0

212.:- .: .. 6 I Trees 6.6 I yample: Meercens' numbef 213


.. .:...

. . "' : ....
- . . < lOk; To incorporate this test without ~arryillg around
(n, g) in the tr'ee haven
an extra pararneter,we will make the functions mktree and /abels!o<::al to. the
(:.

Tabels [Integer] _: Label- [L~be.l] ' ,.. ... .


defuiition of grree:
zip (map (m+) ds)(rnap (g?<) ps):_. :,.

.lapels ps (n, g) =
. ... . . .
.. where !'1'1 = 10 x r; ds 7 [0 . 9J-",,:..:- .: ,
- ,.... . ~-
gtree k.= .
The list meerrens of Meertens' numbers can now be computed,:.in theory at snip (mktree pi-ps (0, 1))
least, by where
prps - map powers (take k primes}'
meertens . = [n l(n, g) - level gtree, n =f gj ' .
.: ~
mktree [ 1x Nodex [ J
'. . .
There is no theoretical difficulty in priming out the labels of an infinite tree mktree (ps: pps) x = Nodex (map (mktree .pps) (labels ps x))
inbreadth.first order because the ordering proceeds level by level. However, labels ps (n, g) = zip (map (m+) ds) (chop (map (gx) ps))
there is a substantial practical difficuhy: the computation rapidly r uns om of where m = l 0 x n
space and grinds to a halt. Searching a tree in breadthfirst order.requires space chop "" cakeWhile ( < lOk)
proportiqnal to the size of the tree, and-.the si?-e of Me.erteo~')xce.gjows expo : . ds . - [Q .. ~]
nentially. No evaluator, real.or imagined, has Sl\fl'icien.t reso\:ft:ces, 'to proceed
very far wi~h the computation. . ,. . , .,._ , .. Ev~n with the.se o'p~imlsatio~s the s.earch is still fairly ~loW. ~p~t from studying
Th~ obyious solution is to restrict the heigh~ of the tree and to switch to theproblem carefully to see what number theorytan be applied, there is one
depth-first search. We have to make the tree finite if we want to use depth-lust general technique for improviilg matters; and we consider this riext.
. because one caimot traverse
searcb~. . an Infinite Meerten.s.' . tto~e .in_
'. . .. ..
order. lf \Ve build a nec of height k, then we can search for Meertens' numbers
depth-first . .'
n in the range 1 .s n < 1ok. The.revised definition is .. . . 6.6.1 Deforestation
..
-
meertens Tnt - [Tnt~9.er] . . : ,... :.
'"":: .;. :._ ..
Deforestation is thegeneral name for a pro~:,rramming technique that removes
meertens
.. k - [n I (n,g)- flatten (gtreek},n" gJ.. : . .:: . interme.d!..ate 4a.tatypes from a program. The idea \vill be considered in a general
. .... .... setting in the following chapter, but we will employ it now to get rid of the tree
.. . ... . --
The function gcree returns trees of given height . ... ... ..-
we have so carefully constructed. The saving will n<?t be huge_but it wi)l be
... .. ~

. 9~ree .. Tnt- Tree signifisant. If the re~ulting program can be sped up by, say, a fac tor of two, then
gtree k - snip (mktree prps (0 , 1)) the optimisation is worthwhile.. (Surely by now r)l.e reader will have suspected,
.
corr~ctly, that the first Meerrens' number is not a small one.)
where prps = map powers (take k primes) ~
Like all sound tedmiques for optimisation, deforestation can be carried out
- ~.:.-
. . .. . ..
: iriktree .. [[Inceger] ] - Label- tre:~ .:-'~~:~::_:. ---~ by program c'alquation. The theme of t.he calculation is to combine fWlctions .
Node x [ ] --:.. ~- .<'f; that produce and consume elements of an intermediate datarype. \Ve begin by
::iilktree ( ] x =
. . . . . ,.,. c(\lculating, for k > 0, th~t
, 'ml<tree (ps : pps ) x
)

= Node x (map_(mktree pp~) (Ja~e,p PS-.X))


. .. .. .; . . . . .~.:~
(flacten gtree) k
Notice that we have replaced level by flatten in lhe definition of -meertens. It . . .
follo\.vs t1,at meercens is no longer guaranteed to pioduce J:lt~in~ers.,in:increasing {definition of gtree, with prps. = map powers (rak~ k primes) I
order. . ' . :,~.' :. - ~~:- . (flalten snip mktree prps) (0, 1)
. The reyiscd definition is fa ster, bur it is Still very slb~v:~:fflier~-i s another
optimisation that can usefully be applied. There is no pomt. ill generating any .. {defini tion of mktree, with ps: pps = prps (since k > 0)}
. '
subtre~ Vfi th a label (n, g) in which g ~ 10k since, by c~n-~t~~_!=ti'~1 all labels (flatten snip Node (0, 1) map (mktree pps) labels ps) (0,1)
. .. -:-- ' . 1:,,.

.> ~: : .'" .;: -: ;:; " ;'


... : ... . -~ .. . . ... ..;:_J

.. + ~ . :-.
..
2\4 6/ 6. 7 I Chapter noce~ _ 215
.. ...

- Vfe conti.J.lue by simplifying -- .. . . ' ? meertens 8


[81312000]
_. flcitte~
. . X : ,~ap' ( mkt;ee pps)
- sn-ip ..Node .. - (2227857 reductions, 5423538 cell~, . 57 garbage collections)
{since snip - Node x = Node x rail} ' , " . ..
' . As far as we are aware;8l312000 is 'the only known Meertens' numb~r. To
flal'len Nod~x tail map (mktreepps) reiterate, it has. the peojliar piope'rty that
,.
{since fail map f = map f tail}
flqccer1 Node x map (mktree pps) ~a.il .-. - . .
= {since flat~en Node x = (x_:) :. concat - map flatten) Exercises
. . .. . ,.
(x :) concat map flatten map (mktree pps) tail 6.6.1 What is the first Meertens' number in base five?
{since map is a functor} 6.6.2 In the definition of g(n) the most significant digit of n is associated with
(x :) concat map (flatten mktree pps) tail the smallest prime. There is a variant in which the most significant digit is asso-
' 1
ciated with. the largest prime.; Define h by taking 11(n) = zdk3dk _, ... p~', ~vhere
searc~, defir].ed ,by
:;rhe finql <::xpression suggests . the.. function
introducing . dt d2 .: . dk is the dedmalrepresentati,on of n. What is the smallest number n
+ , ' '

" . . . . . . . . . ;
,; flatten mktree-pps
. . . ' . for which n = ll(n)? .
search pps
. 6.6.3 Are there any amicable Meertens numbers, thilt is, prurs of distinct in-
It is this function that captures the idea of deforestation. The building and tegers .rn and n such that m = g(n).and ri = g(m)? More generally; are there
flattening of a qe~ is combined in a single function._ any cycles?
The aim nowis to get a recursiye definition of search. The simplification of . . . . .
search []is straightforward, and that of search(ps: pps) xis similar to that of 6.6.4 'Find another 1\-~eertens:_nurnber. or prove that none exists!
flatten gtree. The result is .
.
search [ rx _: [x]
'
.
' , ..
. .
...
' '
6.7 Chapter notes
search .<Ps : pps) x = x : concat (map (search ps) (labels psi,)) . . , Gooi:l'soui:ce bookson trees include Coimen, Leiserson, and-Rivest (1990) and
.. . . . .<:; ''\

Knuth.(l973b). Rose trees~ which also go under the n~e generaJ. trees, were
.. t
. , " .. ';,

'
. program,
Here is.the final in which we suppose k >. 0:. .
so nru:ned in Meertens (1987). Gibbons' thesis (1991) contains a systematic
. . :

meert~ns :k = [n- ( (11, g) - candidates ( . i), n == g] 0, ..


treatment of~ number of algorithms on tree~!.
where Hu{fman coding was described in HuiTman (1952); see also Hu (1982) and
candidates - concat map (searchpps) tail label~ ps _ Knuth (1973a). Thompson (1996) also gives a functional program for Huffman
ps: pps = map powers {take k primes) ~oding. . :
search [)X =
[x] . . .- . . . . ... :__ . . : .. l;he problem o'f comp(iting MeeFtens' number was first considered ~n Bird
= x: coricat (m;p (sea~ch pps)/rlabels ps,~)) '
(19'91). Godel numbering was used by Godel in his 1931 proof of his famous
.. search (ps: pps) x
theorem on the incompleteness 'of arithmetic; see the collected wotks: Godel
labels ps ( n,-g) = zip (map . . ds) (chop (map (gx) ' ps))
(m+) .
(1990). Popular accou~1ts or nie. i~.portance of tllis result on ti:Ventie.thceritwy
where m == 1-0 x n
thought. arc given in Hofstadter (1.979). tUld Penrose (1994).
'chop, - take While (~:to.kJ . . . . ... .
ds "' [0 .. 9). .
. .
This pro~:,rram was ruh oii a small, and rather arident,' machine with a limited -
amowtt.of space: ..,
.'
.- .
I .
..
. - -
. -.
. ;: ."'
- ..to ..
-
'
. .
..

.. ..................,..
'
. . .. Chapter 7
\ . ,;
'
; II ~

!I ,... .. .Efficiency
,;I,
.. ..
. -
fl
'

i
:I
ili .. .. ..-:'1,

'I ' '


I

References ro efficiency have increased during the previous chapter, and. the
........
Ume'has co:rne tb fcicu~ nn this iinp6rtant issue: .In. this: chapter we \\rill take
''':. ." :.. a .dos_e r look ~t the: tind.erlylng model or reduc.~on and ti.ID~ arid space the
~I resources required to evaluate expressions. We will' also describe asunple cal
! culus for estiinating the running lime of PI:Ograms, and presenr a nwnb'er of
..,,' prograrmning techniques, some of which have already.be en exploited, for im
' i
..... ,. . . proving performance.
. .,

.. 7.1 Lazy evaluatio n

Let us start by revisitlrlg~rh~e\i~li.lation of squa;e(3 +4) c~nsidered in Chapterl.


Recall that one reduclion sequence.is .
'
.
.
'
'.
sqtwre (3 + 4)
= . {definition of+}
... square 7
; ~-.: .

. . .. ' ' ,j '

[definition of squarel
t. ;:: ,',' I ' ' '

,. .' . f..
7x7
-- :
= {def1nitlon of X) ..

'
.'
.. . ' ... 49 ..
i .. ,
Another reduction sequence is . ' ..
square (3 + 4)
,, = [definition of square}
.' .'. . ....
. '
: .. ..
..
'J

'
218
:::. . : ' .
7.1 I -' . . . . J:.
La zy eva/ua(iqn
\,
219
,'.
: .. :,. ".

, J3 + 4) X (3 + 4) {d~ffnitf~;~ :~f sq~~re}


..
: , I.. ..

.. ...... ..... '
; . ' I
... . 4X4 .
== {definition of +I "

' '

(x(3+4) = {defini9on of x}
. .
= (definition of+} 16
..
7x7 'This reduction sequence takes tluee steps. By using outermost reduction, eval-
tdefi.nitlon of x} uation of square 2 was avoided.
The two reduction policies have dil'ferei1t characteristics. Sometllnes outer
49 : most reduction will give an answer whim innermost reduction f<Uls to terri:Jinate
tw~ ~eduction sequences illustrat~ two reduction policies, cailed inner- (consider replacing square 2 by undefined in the expression above). However,
These
if both methods terminate, then they give the same result.
most and outermost reduction, respectively. In the first sequence, each step
Outermost reduction has the important property that if an expression has a
reduces an innermost redex. The word 'redex' is short for 'reducible expres
normal form, then outermost reduction will compute it. Outer~ost reduction
sion', and an innermost redex is one that contains no other red ex. ll1 the second
is also call.ed no.rmal-order on account of this property. It would seem therefore
sequence,each step red~ces ~n ou.teonqst. redex.. An outermost. nidex is.oric
that is contruned in no other redex. ' . ' . . '.' . . . that outermostre;duction:l~ .a better choice than innermost reduction, but there
..
is a catch. As the first exanlPle show~. outermost reduction can some l.imes
Here i~ 'ru:other exap:tple.First, innc~most reduction:
require more steps than innermost reduction. The problem arise,s wlth any
~ fst ~square 4, square 2) function whose definition contai..ils repeated occw-renccs o.f an argument. By
binding such an (\rgument to a suitably large expression the difference between
. . . , {de.finitio~ of square} I

innermost at;Id o'uterrnost reduction can be made arbitrarily large.


. ' \ ,
' '

(st (4 x 4,square2} This problem can. b~ ~.olved by representing expressions as graph$ rather
- , (definition of x} than trees. Unlike rr.ee~ . g.raJ)hS can share SL\b~xpressions. for example, the
. ' graph
. . .
fst (16, squqre 2}
.
{definition of square} l.(3 .+ 4 )
..
fst .(16, zx 2) . .. represents the e-xpressi~n (~ + 4} x (3 + 4). Each occurrence of 3 + 4 is repres-
= Idefinition of x} a
.ented by an arro~v, ~ailed pointer, to a single instance of (3 +4). Now,' using
outermost graph reduction we have
rst (16.4>
{dcl'ulition of {st}
square'(3' + 4)
.. = {definitiOn 'o f square}
.....
.:. 16
clxl) \;+~;
l ..

'
This reduc.tion takes five steps. In th~ first rwo st~ps there. was a .chOice or
innermost redexes and the lefrmosr redex' is chosen. The outermost rectuction = {definiti.9!1 of tl
policy f.?rt~e s ame expression-yields . .. . .: ..
. . .
.fst (sq~'are 4, sq.uare 2)
'
.. (1~ .k ' l.:{: :: ..
= {defini tion of-{stj - !defjpj~on of ?<I
. .
49
: square4
...: . .
.... . ..
' . ..
;
...... . '

. ,..
..... .. . .' .,

.. .. .
~

,
. ',
220 . 7 I Eflicienc~
. . .
*
' / - ~ . . .
:7:i. I L-azy evaluation . . 221
' . ... ' . . . . ... ~ .. ~
..
The reduction s~quence has only three .stf;pS. The.represemat'ion ofel'Pressions .
' ' ,

is a sequence qf outermost graph redi,tction steps yielding the normal form e,..
, . ', ' ' , ' I ,,

as graphs means th.at duplicated subexpressions can be shru:edaiid reduced at Then the _time required to reduce ?o to normal forrn is d!!fined to be n andthe
ino.s t once. \Vith graph reduction, outermost r~du~tion never ~akcs mor~ steps
I d!an innermost ~edu<;tion. Hencefqrth we will refer to outermost ~:,rraph.reduc- .
tion by its colD.QlOQ nam~. lazy evaluation, and .to innermost graph reduction
as t;ager evaluatit;m. .
space required is defiried to be the size of the largest graph in' the reduction
sequence, that is, the maximum of the sizes of eo . .., e,. It is reasonable to
choose maximum expression size rather than total expression size because the
. . . . .. space. used for one rectuction step can always be -reus.ed at the ~ext step. To
Shared subexpressions in a graph may also be introduced by .local tlellni put n another way, the critical limitation is the width of the piece of paper
tlons. For instance, given the definition on which the calculation is done, not its length. With the help ofan eraser (m
roorsabc = ((-b -d)/e,(.:..b+d)/eJ'.
.. . pr9gramming terms, a gafl)agc cqllecror) space can be reclaimed for subsequent
steps. . ..
where d -
e =
sqrt (sqLiare b-:- 4 x a x c)
2 x a.
Defining tin1e and space in this fashion has its limitations: In
particular,
the number of reduction steps does not correspOf;!d exactly to the elapsed time
the first reduction step of roots l S 3 produces the graph between submitting an expression for evaluatiOn and getting the result. No
accotmt has been taken. of the time required to find an outermost redex in a
possibly complicated expression. Since expression s can get arbitrarily large,
I .
l sqrc (sqJare s-4x 1x 3.) \2 x 1) uiis search time cannot be regardeel as consmnt. . .
The space nieasure 'also has its limitations. One problem is that it takes no .
Acttially, there are three additional pointers not shown on this graph, one account of the process of printing. To illustrate, printing [1 .. 1000] da.es not
pointer for each of the variables a, b, and c. These pointers poillt to single require 1000 Wlits of space, even though reduction of the expression [1 .. 1000]
) occurrences of.the expression s 1, 5, and 3. .-. ;.: to the normal form 1 : 2 : .. . : 1000 : [) docs require this amount. Printing a
.i Arrows have no meaning except to indicate binding and 's hm:ing. Both list inv~lves printing the head of the list, throwing the head away, and printing
.. ther~st. The ~ituatlori is; however .complicate d by another aspect. Suppose we
(squarer; --1(3 + 4). - . .. defined

and sq.uare(3 + 4) are equivalent ways of writing the saine exp res~iCm.. The size numbers =; [ L._l QQ.O J:. t . ;_ .
li of an expression or graph can be measun;d by cotmting t}1c tothl number of in ascript. This time, evaluating numbers does use up 1.0 00 units of space:
!I
!
arguments involved. For example, the expressiorr above has size three becau se
,square'has one argum~nt and + has two. SimilUJly, the expresSi()~ ~quare 3 +
Th'e space carmot be tluowri away after printing because thereis pointer toa
.i ritimbers in the program. It is a consequence of lazy evaluation that no e.'q)res-
J
> square 4 has size four since each occurrence of square has one argumen t and . sj(m at the end of an arrow is evaluated more than once. Hence the fii-st eval
+ has two. The graph : uation of numbers leaves numbers boWld to an evaluated list of length 1000.
' As a result, the space.occupie9-.by a SC!iPt can grow with repeated evaluations
il .'-i".....' ... ..,.:... . ' ' '
Of the ftmctiOtlS contained in it. . ,
I

..-
.. :. . ~ . :;-~
. For such reasons, we will concenrrate almost exClusively on time efficiency .
also has size four (X and + each have two arguments).
. .
We will adopt lazy evaluation as our model of c-omputiitiO n. because it h as
. iri the analysts ci programs: Hoivever, one technique fo~ the llihited control of
space is given in Section 7.5.
two desirable properties: (i) it terminates whenever any reduction- order ter-
mmates, and (ii) it:requires no more (and possibly fewer) steps (harr~ager .eval
uarion. To be precise, tlie time and space required to evclluate an ~;.pression eo
is defined as follows. Suppose . -
. ..
.
. .
:.. -
- r
..

222
- - ': ' J .: : . . ....
.-: ' 7
. . ..... '
f. Efficiency .7.2/ A~YT.r~pto(ic
.. .
analr.sis .. .
! ' . .. . ... _.223
:
. .. . . . . ~.J
.. "":- . ... ~ ,! ,''/ : :.
is
!
" . .
_Ex~ri:ise!; .. . . . . ,. . . .. ~ .., .-: ...'i ' : , : ' : Ordernotation de.scctbed ii1 mMY books on tl1dnathenultics ofcomputing
+

7.1.1 Describe the innermost, outermost, and outermqst I:,Taph reduction se:-
' ' I
science, so >\le will cor1t~nt omselves with recaJlhtg 'the basic' d~fuutions, ai1d
giving some simple examples. .. . ' .. .
quences for eat:h of the fo_Uowlng expressions~
..

,.
. Given tWo functions (and,g on the natural nt.unbers, we say that f i1!.order a.c ..
... head.[1 :.. 1000) . g;
most and wi-ite f = O(g) if there is a. positive constant C and a natural num-
.map f [L, 3] where f n = iO x 1.0 + n . .. ber n0 such that f (n) =::: . Cg( n) for all n <:!: n0 : Ill other >vords, f is bounded above
by some constant times g for all sufficiently large argunients. 'The n~tation is.
7.1.2 One definitio~ of so~t is totake sort. ~ {oldr insert [ ), where. abused to the extent that one conventionally wtites, for example,f(t'l) == O(n 2 )
' . rather .thail the more correct:(= O(squqre). Similarly, one writes f(IJ). = 0(/1)
inserfx [ ] -'
x: ~: ys'~lse y: insert x ys
- [x]
.ratper than f = O(id).. ~ .
insert x <.Y.:ys) = if x =::: y then
The main use of o:not~ti~-n is to hide constants; for example, we can write
Give, in detail, the eager and lazy evahiation reduction sequences for the ex- II II

pressionsort [3, 4, 2, 1}. ex"J)l~ning where they diller. 'i.j "" O(n ) 2 and I/=0(n3)
J= l
Supp~sc ~e defirie. minlist. ,;, hecu( .~ort; where .sor:l,is ct~fined in. rhe ]=1
-;;:.'!.3
. . pre~iou~ gues~9n.: ~ow many
redt.tc~ion st~ps <appro:<i~nateiy) ar:e required to. , without bothe;ing ~bo~t th~ ~xact constants invol~'ecl. Howeve~:: a -notation
. evah1ate minlist-on a list of n number.s, 'vvi,tb both lazy andeager evaluation? niust be used withcare. Altl-iough.we write f' = o(g), we don:t actually mean
7.1.4 Same.question, but for maxlist = lust sort.
.
that f is equal to O(g). It is better to t.bink of O(g) startdi;f1g bY, itself on the
.. .. ~. right of an equation as denotfug the ser or'fu~ctio.ns f satis.fying the property
described above; and to interpret the equals sign in f =, O(g) as set member-
7.2 'Asymptotic anaJysis
.
.. .. ,\ , -
: . Irl general; on~ is less int~rested in 'estimating the cost of evalu~t~g a particular .
. . . ...
ship. Then orie isn~ver' tenipted to write O(g) = {, or to condude that f .;, g .
from the assertions'{= O(h).and g = O(h). ' . .
However, \ve wili .""Ti~e exj)[essi\)ns .such as the following:
'. . ... exp're'ssion"thari:.iii comparing the performance of one cfefiniliqn of a fi.mction .
.
. witl1 another:. For. example, consider the' following two progr~s for reversing .
.I ..
N
. . ' .
a list: O(n) '+ O{f,l), 0(n 2), T(n) = 2T(n/2) + O(n)
. . ....
.' ..
'.
.. . ..11='1'
. .. . .. ' . ... ...
...
.. '
~e~ers~ [~ (] .. , - Wb.en O(g) appear:dn a formiia it.stand;forsome u.pnamed function f satis-
~ ... .reverse (x: xs) =, . reversexs * [x] fying f = O(g): In parttcUiar, ..O(n) +O(n) denotes the sum oftwd anmiymous
'
... . functions {1 and {z. where {1 (n) = O(n) and (2 = O(n). Since ~t follows that
.'
. . ... \:
':

r~versf = {oldl prefix [] where prefix xs x = x ; xs .- . is


:

fJ(n) +{2(n),;, O(n), it legitimate to conclude that O(n) + O(n) =O(r.t).


- . . ..
. .' On the oth~r. hand; the 2
.. . expression l:~=l O(n ) does not mean .. . . :
.
It was clalfu~d iri Sec don 4.5 that the second P.i:og:raril is more effl~ient th~ t.h~ '
.
.
.former, talctng:at
. . most. a number:
. ofsteps.pr6p'
. . . . . . o.rtlonai
. to''i:ri:ni':a)ist
. . . ... .. of length.
. ,. .. ..
...

. ..
+

,.
.;' ~ (

n,wl~~ tlie. _fust progr~ takes n 2. steps..: 'fpe.aim .of !;his s.ec.tio'Jl is to: show:. .
' . ho~v tQ' m~k~ such,claims more precise ari,d to justify them. .. .:. Instead, i( cteriotes:th~ ~Uin 2:~='1 {( n). where f is a single function satisf}ing
2
1 O(n2 > = O~N 3 ):
. . .. ,,. ~ ....
. . . {(it)=' O(n ),1Ii tlus.case we.havc-2:~~
..
: .. . ,.
... . ' ~ ;,
. . . ,.

7.2.1 Ord~ t~otai:ion . . .


'
0 . :
. What O~notation brings out is. an i.tpper bound on the asymptoti(.groWth
. : . .. ,. .
.!
. . of flinctions. For till~ reason,::estimating. the perfom1ance of a prograin usiJ.ig
. To avoid. '~xPlcrlil.ing .
'

. some special marhetn.atical notation, the awkward phrase_ .


l

. . . . .. . o-riotation Is callecf'asyinptbtic upper-bound analysis. For-example; the time


'taking(\t most a number of steps. proportional to has appeared up to now . complexity of reverse on a list .of length n is O(n 2), and the complexity of
'i.vhenever. efficiency is discussed. It is time to replace it by son'letlting shorter.. reverse' is 0( n) . Ho\:-Vever, saying that reverse takes O(n2 ) steps ori .a listof
... . .,
...... .:.,

. . '' ' .. . . ' ,.. t : - ..


.. ; ' .
.. .
. , ''. -~
..
: t : t
.. .
'

224 .. . . .. .
. ... 7.2 I Asymptotic analysis
,.._ ~

.. . ..225 ; .
... : -~ .. ' ., .-..!_.f.E{fiCi~~C
-;'': . Y. '

:;_~.,,~ :. ::J,.. :.~~,,';:. ~ .:


.. 'x.; ~ ys is best ~E:asui-ed jn ~er.ins of ~ ~d n, where m.-= ~~~gth Xs and n =
I '' , ' I ' ' ' '' ' . .,, "

length n does not ll}e~~ thflt.il docs not take, !?ay, O( n) step~.. F.or more precision
we nee~. additional ~oration. . . . .: , ::. . . .... length ys. In fact, we have
We say tbat {is order at least g, and ~Vrite { = O.(g) if there exists a positive
constant C and natural number no such that f(n) ';:: Cg(~) for all n ;:: no. T(*)(m,n ) = El(m)
- . to be a whole number, we have .{ = D(g)
Since C is not required
.. . if and. only if
g = 0.({). Now, to say that reverse takes O.(n ) s~eps on a list of length n is O
;.
2
" ~ ' -~

~he proof is ~eft as an exercise. Next; consider concat xss. Here the measure of
put a lower bound on the number of steps required to evaluate reverse on any xss is more difficult. In the simple case that xss is a list of length .m, consisting
list of length n. of lists all of l~ngth n, w~ have
Putting the two kinds of bound together, we say f is order exactly g, and ' .
write {=~(g) iff = O(g) and f = .Q(g). In other words', { :(. EI(g) if there are t{concat).( m, n>-=
.. ' '
e(mn)
t\"10 positive cons tams cl and c2 such that

Ctg(n) ~ f(n) ~ C2g(n) We will .prove. this result below. The estimate. for T(concat) therefore refers
only to lists of lists. with a common length; though limited, such restrtctions
for all sufficiently large n. Then we can assen that the time of reverse is e(n2) make
and the time of rever,~e' is El(n). These two functions are atypic<il iri that lower
. timing . analyses
. more "tra.ctablc.
.
The third r emark is to emphasise that T(f) (n}. is an estimate of. worst-case
and upper bounds on running times do riot normally coincide. mg~ner~l. the running rune only. Tltis will be sufficient for our purposes,although best-case
time reqUired to evaluate a function f on a list of length .ri-'MU depend not and average-case analyses are also important in practice.. . .
only on nbut on the actUal elements in the lis t. For some lists the eval'uation - .. . .
The fourth and crucial remark is that T ({) (n) is determined under an eager
may be quick, while on others the evaluation may be slow. In general we can
evaluation model of reduction. The reason is simply that estimating the number
only make statements such as 'the running time off is O.(g).and-O(h)'. If we
to
want more informatio'n, then we hav'e consider the b~st-case and ~vo~st-case
of reduction steps under lazy evaluation is difficult, and is. stlll the subject of
ongoing research. To illustrate, co'nsider the ciefinirlon
p &formance (and,. perhaps, average-case performance) scpar~neiy. The~ one
can make statement.s such as 'in the worstcase , the running titne off is 0 (n 2 )' .
minlist - head sort

..
. ' . .
Under eager evaluation, the time 'to ev<Uuare minlist on a list'of length n is given
i i 7.2.2 Tiriling analysis
by
I. Give~ a function f we will write T(f) ( n) to denote an asymptoU C. estirr).ate of _
I the number of reduction steps required to evalua~e f on an argum~nt of 'size' n ..... T ( minlist}(n)
... = T(sorr}(n} + T (head)( n}.
in the worst case. Moreover, for reasons explainedin a moment, vv,e \\ill assume .
i. .
I
eager, not lazy, evah.iation as the reduction srraregy.. In particUlar, wecan ~v.ritc . . .Jn other words, to compute minlist on a list of length n, we first sort the list,
i
raking T(sorr)(n) reduction s teps, and then compute the h ead of the result
' ~ t
..... ....
., ' : ..... '

I .
I

T( reverse)(n) - E>(n2)
~
...
. . . .. ...
' '\!:
.... ... \ \.
, ;
.. (which is also a list of length n), tak:illg T(~ ead}(n) steps. This equation docs
nor hold under lazy evaluarion, 's ince the number of reduction steps required to
T (reverse')( n-} - E>( n}
,. ., fmd the head of sort xs does not necessarily mean that sort xs bas to be reduced
The definition of T requires some amplification. Firstly; T(()' does not refer to tO normal form. It all depends on the precise algorithm .used.fcir sore. Timing
i. the time complexity ofa function f butto the complexity of a givendefinition a!)alysis und~r eager reduction is simpler because it is compositional. Since
of f. Time complexity'fs a property of an express.ion, ~ot of theyaJue of.that lazy evaluarion nevcr requlres.more reduction steps than eager evaluation, any
expression. upp\!r bound for T(f)(n) will also be an upper bound under lazy evaluation.
s eqmdly, we do not formalise the notion of size, since differen t measures Furthermore, in many cases of interest, a lower bound for 1(f}( n ) will also be
are appropriat e ui different situations. For example; the c~st oT evalmiting u lower bound under lazy evaluation.
... ~
. . ... I '
..
- '" - .
.-
226 . 7. I Efficiency 7.2I Asymptotic ana~ysis
.. 227
.- .. ..
,
- . ; -=--

7.2.3 Reverse and concat .. : For the tirrting anaiysis,-let th~ argument to concat be a list of length m con-
Let us now analyse the program for reverse. We have sisting o~ lists each of length:n. The resulting list then has length.mn. Then we
have
.. ..
'r (reverse)( 0) = ,0(1)
.
T(cqncac)(o. n) = 0 ( 1)
T(P"everse)(n + i) - T(reverse)(n) + T( * )(n, 1')" T(concat)(:m_:r l,h) - T(concat)(m, n) + T( * )(n, mn)
. .
The expression O(J.)"denotes some-con;tant, the predse value of which is not Since T( * )(n, mn) = e(n), we get
of interest: Since El (l) = 0 ( 1), we could have tised .EJ{l) in the first equation.
Thesecond equation says that to rev~rse a list of length n + 1 we have to re- . ... . .: ttl ' 'r., ..
verse a list of length n and then concatenate it With a hst oJ length one. The
nconcat><m. n )_= I e<n> ,.,
k=O ..
e(mn>
equation exploits the property that. reverse docs not change the length of the
list. Program analysis depends on such facts, which is why it is not simply a The above definition of coneat is exactly what we 'would get from the clerin.ition
mechanical exerCise that can be delegated to a computer. . cot1Cat = (oldr ( *) []by eliminatll1g the foldr. Since * is associative with unit
is
The ~;ecursive eq~ation for T(reverse) simple to solve, Using the estimate [ ], we could also have defined, c.wrcat by concat = fold/ (H ) [ ). Eliminating
T( :++).(n: ~) = EJ(n), \Ve obtain . , ... . . , . . . . . . . . . . . {ole!/ as in the definition
...
of reverse'
:.. :. .. leads to the program
..
n coneat xss - accum [] xss
T( reverse)( n) = L B(k) = El(n2 ) ' accum ws [.] - WSS
. k=O
accwn ws .<xs : ~) = acctun ( ws * ~) xss
For the analysis of the second function. reverse' w.e .can proceed iil two different . .

or
ways. 'Ifle nfst is to eliminate fold! in favour a direct recursive definition: . For the analysis of accum""let tile first list have length k, and th.e second list be
a list of length m of lists each of length n. Thenwe have
reverse' xs = accum[ ]xs
.. .. .....
..
\.
'
.. .
.
... .. - 0( 1)
.. accum ws [ ] - ws T(accum)(k, m + 1, n) = T(ac;cum)(k + n, m, 11) + T( *) (k, n)
.accrlm ws (x: xs) = accum
. (x: ws). xs.
. . '
Since T( * ) (k ; n) = e(k), we ..obtain
The functi'on. accum has t\vo arguments. If we denote
. the
. ien-gths of the t wo
arguments by m and n, then _ n.r-:).
T(accum)(k, in, n ) = L EJ( k + jn) = El(k + m2 n)
T(accum)( m,O) = 0(1)
T_(accum }(m, n + 1} - 0( 1) +T(accum)(m, it) Hence for this defi.nition .of (oncat we have T(concatHm, n) EJ(m2n). The =:
conclusion is that using /oidrra.ther than {oidl iP the definition 'or coneat leads
. :The 'term O( 1 )ill the second equa.~ion accnunts for. the -~~ns operation. The to an asym:ptotically faster prbgram. . .. . . . . .
solution..is T( accu_m)(m, n) .= El'(n) and _so 'nreverse').(n) = El(n). ' .
The secbnci method is less formal.. Evaluating fold/. f e.on a list of len'gth .. .....
. n involves n comp'iltations of(. Vf.lren (is a constant time operation, such as Exercises ..
. pr:e{ix, 'we get at once that the total tirrie is EJ(n) steps. . : . . .
7.2.1 Prove .that f':" O(g) if and only if g = 0.(().
. As another example, the functloh concat can be defined directly by_ . . . .. ' .
. . . ~.
7.2.2 What, precisely, does 0(1) mean? Prove that f
.
= 0( 1). if and only if
concac [ l - [) f.= El( ~) . . . .
..
. (xs : xss) = xs * concat xss
.concal '.
.
.. . .. 7.2.3 Prove tha"r n100. = 0(2");
.-_.....

. .. . . .. .,
-... . .
'
--
. , . ;-',. .,:../ / Eiftci en cy .J /-Accumulating parameters
. .7... . 229
; 228 : ..
' . ~\ . . ...
. .
. ... For instance, we can argue .-
i,.'
Using 0 -notation, estimate 2:1:; 0 k2.k. . tio~s.
7.2.4
..-
\
. :' '
' ...
' 7.2.5 Pr~JVe that T( * )(m, n) = 8(m). reversexs
7.2.6 Use uiduction
. .to prove that if .k ~ 2 and {since [ ) is the unit of *I
.. . ..
- , 4-.t''' - . ( +i-) (reverse xs) []
T(O) - 0(1)
T( n + 1) - kT(n) + E>(k11 +1 ) - {above expression for *}
. . . .
What is the solution if k = l?
= E>( nk (foldr consdor jd (reverse xs) [ ]
then T(n) 11
).
.. . .. .~~;:-
. ' l = {third duality theo'rem}
'

7.3 Accumulating parameters . consdot) id xs [)
. . (flip
fold/

Tllis gives another linear-rime program for reverse, essentially the same as be-
By adding an extra parameter to a function we can sometimes improve the
running time. The most important use of the idea is to ~liminate possibly . using fold/
fore 'except that revcan s exJ)ressed .. . than. {oldr. ..
. rather
*
expensive operations from a program. To take a basic l!x<imple( c.onsider the
7.3.1' Flattening a binary tree.
function revcqt defined by ' . '" . .
, '. ..
.
' . '

Here is another example: the function flatten for flattening a binary tree was
revcac [a)- [a]- [a)
defined in Section 6.1 b'y . .
. revcat xs ys = reverse xs * ys
flatten .. Brree ex- [a]
Ir is clear that reverse xs = revcar xs [ ], so reverse can be deftnef'in terms of
i ;: flatten (Lea{ x) = (x] :
. .. revcat. H is a simple matter to acrive. a .directrecursive pr'9_gram for revcar.
...
.. and the result is . . .. .
flatten (Fork xt y t) - flatten xt flatten yr .*
' . revcar [) ys - ys
.. Now define
. ., \
revcat (x : xs) ys = revcr~ t xs (x: ys) flatcar .. Brree ex - [a] - [ a)
Since revc~r xs y; ,.
acazm ys xs, where accum was del'ined in the previous
. {Ia rear.xt xs - flatten xt -tt xs
~ection, it is clear from the timing analysis of accum that .thc.new program for We bave flatten xt = flatcac xr ( ]. Synthesis of a recursive program for flatcar
reverse takes linear time. give~' .
To 'appreciate what is really going on, it is instructive to wri~e down the
composition: ...... . flatcar (Lea{ x) xs
p~og'ram.for revcat interms of function
= X: XS
..
. flaccat xr (flatcar y.r xs)
. : flatcar (Fork xt yt) xs
~ . revcat ( ]. : - id
. ..
:l
revcat (x: xs) revcat xs (x :) Let us llOW compare..the_ruruling. times. of flare en .and flat cal. Let T(fla.rren )(h)
est.imare the time requi.i-ed to flatten a perfect binary tree of height h. Recall
Equivalently, revcat = foldr { id; where f x g = g (x :). By exactly the-same from, the previous <;hapter that such a tree has 2 leave? ..We have
11

.' means we obtain -


-, .. T(flatten)( O) - 0(1)
( *) ,; {oldr consdot' id, where consdor x g = (x :) g . T(flatten )( h + 1) - 2T(flallen)(h) + T( *)(21!, 2h)

It is this expression for *


that underlies rpost uses of the accumulating para The .second equation follows becal!se the tv.o subtrees of a perfect binary tree
m eter technique: concatenation is replaced by the composit-.ion of .ons..opera- of height h + 1 both have size 211
"' 4. .. . ....

.. .. ..: .. ,, .
. ... ,..._

. . ....
. . .. .
-~

Accwnulatillg.parameifrs .
..- .. '. 231
230 : : :. .> - .. . ' ......
... 7/ ffficiehcy : -7:3 I
. . .. _;., ::~~:_:.'! : ' .:.:. : . . ' -~~ . .
\
J
} . .. '.: ~ ' \

. '. . ': .': . .


'

. ' , I

.. t ) ; w~ obtain
.
1
... . ' .9(k~'
.. .. . :.~:?ksY.=
''

Sinec T(*)(m,"11) =.El(m), we obtain


, : . .
.' . : Since T(cm.i cat)((s)
. . .
_; . e{k11+1 )
~

. T(flatten)(h + 1) = 2T({la!len)(h) + 8(2 11 ) T(flacten)( h + 1, k) + kl({latten)(h, k)

An ind~ction.argument now gives that T({larten)(h) = 8(h2 ' ), so flat_tel'! takes


1 One can no~ sho~ by iild.ucti'on that T(flatten)(h, k) = S(hkh) = <;><siogs).
O(slog s) steps on a perfect binary tree of sizes. Hence fl attening a tree_by flatten takes a time that is asymptotically greater
Now let T( flatcaq ( h, n) estimate the time required to compute the expres- than the size .of the tree. .. . .
. sion fl(,l(Cat xt xs, where xt is a perfect binary tree of height h, and xs is a lis~ of Having established that the above method of flattening a tree is not the best
length IJ: Then we have poss ible, let u.s see what .<U;l ~-cumulating parameter can do. Definedf(:at by . ...
. . . . : . ~ . . '
. ..
= 0(1) . dfcat :: . Rose cc- [IX] - [IX]
T({fatcat)(O, n)
T (flatca[)( 11 + 1, n) = 0(1) + T(flatcat)( h, zh+ n) + T(flatcat)(h, n) dfcat xts xs = concat (map {fatten xts) * xs
We have flatten xt = d(cat [xt] [ ]. The aim now is to synthesise ~ r~cwstve
It is easy to show by induction that. T(flatcat)(h, n) = 8(2 ) , so the ne~~ p~o
11

gram fo1~ flatten takes.linear time iri the sizeof the tree.
. . ... .
pr:ogram for dfcat. Here ::is..the inductive case:
.. . ....... ' . ..
' . "'. ...
:. , .
. . . . ....... . ' . ~ .'' ' ,: ' I
:.
. t. . ....
.. :
:
; . .. . .. d(cat (Node XX{S: yt~) xs ., ..' ,
. . .. ~

7.3;2 ; Depthfirst order - {defiJl,itionl


. ' .
Exactly-the -~ame technique can be applied to the ftmctiori flatten for rose trees. concat.(ln ap_nR_tten (Node x xts: yts)) * >;S
Here the definition of flatten is ...
= . .{definit~on
. .
~f 'map.
. and co neat) ~

flatten .. Rose IX - [IX]. flatten (Node x-.hs)


-." ' .
* concat (map flatten yts) * xs .. ,.
= . x : co neat (map flatten xis) ~
.
flauen.(Node xxts). . = (defihition .cif
'

.,..
flaWD1)
.. ..
'
. '

l"hi; l~ne, let us analy.se the proiram fer flatten before trying to impro~e it. x' :' concat (map fla~ten xts) * concat (map flatten yts) * xs .' .
Let T(flatten)( h; k) estim11te the time to flanen a perfect k-ary tree of height (defiriition of.dfcal}
( h +-lkR~call that such a tree has siz~ ... ... . . .
' . " . ..
. .. .. x: cone~t (map flcitten xts) * d{cat yts xs
\
. .
~ .- l)/(k - 1) = e(l<
:
.. .. s<~. k> = (k
'
11 1 11 ,-
. '.
> ..
. ' of 'd(cat}.
{defillition
' ' .
' ' j,. .. . .!.: ' . .
... .'. .. ..
. Now we. have

. ' X; d{cat xts _.( dfcat yts XS)

: T(flatten)(O, k) . = 0 (1) The result is. the Tollowing pr<_?g_r~ for dfcal:
. T ( f{atte1_1)(h + ~, k) . = "0( 1) .+ T(concat ) (~_s) -t: T(r'!ap. flatt!Zr:zH~1 k )
- ?> - .. - - .
... . ' . d~-"car[] xs:,.... .: ....~.:. ... :::.:.. v~
..w .-.
.. whe~ei:~- s(h, k): the tetm T(map flateeni (h , k ) estiim:ite~\h~ nmning time:~r
. I' .- . - .
.. :
= x : dfcat xts (dfcat y ts xs)
a
d{cat (Node ?<. xts: yts) xS
map.{lattr{ri on list .o f lengtli k consisting of trees all of h~ight h. In general,
. give[\'a Ii.stonength k, consisting of elements each. of size n, .\.Ve have . .
.. . .. ' . . ... . . . . . . ' . . '
~~r the riming ~;ialysis, ~~~: 'r.(4(~~f.)(h, n) estimate the time reqtlii~d_to ~om
pute dfcat xts >;S, Jyhere xt~ is a. J~s t of length n, ead1 member of which. is a
'
. . . ..
.T(map
. f) .( k, n) = kT({)(n) +.El(k)
.. perfect k-ary tree gf height (/i + 1). We will ignore the size of xs since jt 'does
. not aff.ect the cstiillate. .
Hence, since 0(1)+ 9(k) = 8(k), we oljfain .. . . . .
-: -
' . . - \.. .. .
T((latten)(h + l, k) = T (concat)(k,s) + kT(flatferJ.)(h, k) + 9(k) ' :

.- ~: . . .;. ...
~ -- . ...
.. ' . . .. ... '' .
. ..
' '
.. . . .' .. . ;
. :
-.. ..' ' ..
.
.
.., ' '
'
. . ., .. . ' ,.
.,
232 .
......' : -::~1. I Efficienty
'' .. ... :; .. . ,";.,~ . . ; :: . . : ~ : ! 7.4 i Tupling '.
'
.
We have- . .'.. . : \ ~ :.~.; ... . . . 233
. .
' . '
. . .. ' ..
: 7.4' Tupling ' " . .. . . :
t
.. , .... .... .
T(df cat) (h, 0) - 0(1)
T(df cat)( O, n + 1) + T(d{ cat)( O, n) The technique of program optinlisation known as rupling is dual
- 0(1) .. . . .. . to that of
T(df c'at) (h t 1, n + 1) + T(d{ cat) (h, k) + T(d(C:,~{}.(h + 1, n) accumulating parameters: a function is generalised, not by including
- 0(1) an extra
. . . argumen t, burby il)clucling ah extra result. Otu aini i.n t)?.is secrio!fiS
The first estimate counts the cost of evaluating the first equation..for
' ,', . . 0

to illustrate
dfca t, (he this important technique through' a number of llisrructive. examples.
second coimts the cost of evaluating the .second equa.tion for r;ifcc~ .
t when the
first clement of the first lisr isa tree of h~ighr 1 (and so has no subt
rees), and 7.4.1 Building a tree
the third estimate coums the remaining costs..
0

. "!'- .-

. : .:.

Th~ first two equations.glvc T(df car) (0, n) = 0(n) . "An induction argument' . .. Co~sider the ft.inction ~kBtree, defined in Secdon.6.1, for bulid
gives that T(d fcat) (h, n) = E>(k 1'n), so T(d{ cat) (h,1 ) = E>(kh) .= El(s) ing a mini.muni'
. Flatten height tree with. a given {nonempty) sequence as tips: .
ing a tree using an accumulating parameter can be done in time prop
ortional
to the:size of the tree. mkBtree :: [e<] - Btree ex
.: .\ . ... . . mkB treex s
- ..
.,:. ..
7.3.3 Show
... '.
... = if m == orhe n Leaf (hea d xs) else Fork ( mkBrree.ys) (mkBtree zs) .
. .. ..
~

. . . . . .
where -ys . ~ .take m xs : :
'
. '

As a finai exam~le''of the usc of C!Q actumulating par~eter,' consider ..


zs = ..
the type m xs
drop '
class Recall from Sections.2.7 and.S.3 that the class declara,tion for Show
'
Show
.
.
contains the method . m = (length Xs) div 2
.. . . . .
., .. To analyse this progran1, "suppose xs is aJist o'flength 21<.: The time
showsPrec :: Int - ex - to compute
Strin g - Strin g length.xs, take m xs, ~d drop m xs, Yfhere m = 2k-t , is
therefore 8(2k ), so .
We can now say,what the third argument of showsPre.c: is; i~ i~an 'a~c~ulating T(mk Btre e)(O ) = 0(1)
parameter. Use of an a~cumulating parameter is necessary if ~ -~van .
t w prin t T(m kB.tree) (k + 1) ' - + 8(2k )
..-
nonlinear datarypes in linear time. l '
2 T(mk.Btree)(k )
; ... ... :

Tt1e solution is T(m kBtr ee)( k) = e(k 2k) . .Hence, to build a rilini

..
'

mtirn height
~~

. .......
Exe'r dses ... ....
_,_
.
~; ;.
of
tree from a'given list length n takes e(n log n) steps.
I ' ' . . Now consider the func.tion mk'nvo de,fined py . ..
7.3.1 The function digit s:: Int - [Dig it] can be defined by
'
, '

..' mktw o :: Tnt - ( a] - ( Btree ex, [ex])


.digit s n .; if..n < 10.then ~n] else digits (ndi v 10) ;H- [n~Qd,lO']. 'mkt wo n xs = (mkBrree (take r1 xs), drop nxs)
. ' . . . .. . . .
How long doei co~putation of digit s n take? Improve the ~g:~ .Zt is clear that mkBcree xs = fst ( ~k~o (le~grh.xs) xs), so mi<B
an accumulaun'g parameter.
~ by using tree can be com
' .. ... ~- . pute d by computing mknvo. The aim now is to give a recursi~e
progr~m for
mktwo. It is easy ro calculate
7.3.2 Consid~r the function unfo ld/ defined by : . . . :~... .. .: . : ' '
. . =
.
~: ..:- .. :- ~ mkrw o 1 xs (Lea f (hea d xs). tail xs)
unfo ld/ .. :: . (tx- Boo/). - (tx- (tx,, /3))- tx- Un: .':~ : ..
unfo ld/ p f X :0 if p X then ( ] else unfo ld/.p f y Lz * r. ;' :. .: - For the recursive cas'e, we will need the laws
. .' whe re(y ,z) =fx _:.-. . .~ :,'.
. take m take n = take m
Use an accumulating parameter to give a more efficient de~~iory . ,1 ..- .

~ . , . . drop m. take n = take (n- m). drop m


. ...: ~ --..\. .::":... . . .. drop n = drop m dr op (n -:-' i:n)

\
\'
. '... .... . .
' ... ... 4
.
....... . ~... , . ~ .- !',, 0
'
7.4 I Tupling
234 . . . 1 / :f.fficie)1cy . ~ ..._ ::;. .... 235
.. :. ' ,.. : ~ .. : . ,. . ' . : . ,.
.. :. ... \ , ~ ' .
. . .. which I:J.~ld p'rovidecl m .s n. Now, we art.rue for n > 1.that ' ' ' The ti~ne to ~val!J.~~e fib n by _these ~quations is given by T ({ib)(n), when:;
. . . ... .
mktwo nxs T(fib)(O) = ' 0(1)
T(fib)(l) = . 0(1)
- {definition of mktwoj
.. T(fib )(n + 2) - T.(fib)( n) + T ({ib )( n + 1) + 0( 1)
( mkBcree. (taken i<s), drop n xs)
. The timing function T({ib) therefore satisfies equations very like that of fib
=
'
(definition of mk.Btree, using laws above with m ::;: n div 2}
' ' : t
' itself. It Is easy to check by induction that T((ib)(11) = 8(fib n), so the time to
(Fork (mk.Btree (take m xs)} (mkBtree (take (n - m) (drop m xs)) ), compute fib is proportional to the size of the result. Since fib n = e( C/J"), where
drop n ?IS) .. <P is t)1e golden ratio <P = (1 + /5) /2, the time is therefore exponential inn.
- {se~ting (xt, ys) = mktwo m xs and using third law above} Now consider the function fibtwo defined by

(Fork xt (mkBtree .(take (n- m) ys)), drop (n - m) ys) . fibtwo n = (fib ri, fib ( n + 1))
- {sett~g (yt, zs) = mktwo (n - m) ys}
Clearly, fib n = fst (fibtwo n). Syn,thesis of a recursi~e program for {ibtlvo yields
(Fork xt y.t. zs) .. : .
' '
{ibtwo 0 - (0,1) . "
In summary: . fibovo (n + 1) = (b, a+ b), .. where
. (a, .b). = (ibtwo
. . n

mktwo nxs ' It i~ clear that tWs progr~ takes linear time. in
tWs example, the tupling
-=.. if n == 1 then (Leaf (head xs), tail xs) else (Fork -xt yt, zs) strategy leads to .a dramatic
. increase
. . ' in efficiency, from exponential. to linea,r.'
. where (xt;ys) - mktwo m xs
, ...
. 7.1.3 Filling paragraphs " '
(yt, ~s) = mktwo (n - m) ys .
. ... . . ' .
'

. ' . . m '
- ndiv 2
.
. .. . ... The examples above involved tupUrlg lWO functions. but the' same ioea can be
. . . used to good effect by tupling a list of functions. In this form, tupling is usually
The timing analysls for mktwo gives in the r~cursive case that
referred to as tabulation ..A simple example is provided by the problem of filling
. '
paragra'p hs, a probiem we.consid\!red in Section S.S. We ar~ given a list ,;,s of
T(mkl:wo)( n). = TCm1<two)(m) +n mktwo ) <n -
m) + 0( 1)
,'
.: ' . .' where m = n ruv 2 .' ' ' words <~.nd we want to find ali&t of lines wss ~uch that ws = concatwss .with the
:. additional constraints :that each l~ne in wss should be short enough to fit wifhjn.
The solutionis T(mktwo)(n) = E>(n). Using mktwo as a subsidiary function, we some given width, and that wss should minimise some notion of waste. For
have imprgved the asymptotic complexity of mkBtree by a logartthiruc factor. simplicity, we will assume that waste is determined by. some given numerical
. .. !uiu;tion.waste th~t t~es the value oo if the paragrap.h contains a line. that ~
.. - .. ' : not fit in.. the given width...The algorithm in Section 5.5 was greedy In nature: if
.
:'

.. 7.4.2 Fibonacci function . ..:. . : . . .


~
.... . at some stage the remaining list of words is ws, then the next line consists of
. ..
. . the longest initial segnientbf ws that will fit within the given width. Here, we
Another example where tupling can improve the order of .growth ot' the tin;ie ' . ' tackle the general problem of selecting a best possible next line, not necessarily'
complexi.t y of.a program.is provided by the f ibonacci function: the longest legal initial segmerit of the remaining input.
.
(ibO - 0
'
',

,_ - _...
The definition <>f tin takes the fortn .,
0

.
. fib 1 - 1 fill .. [ Word] - [ Lin.e]
fib (n + 2) = fib n + ['ib (n + 1) ,
fill = best: fills.
' '

,. . ..
' . ' ' ' '

' .
-:-. ' .-: '
. 237
-7 I Efficienc : 7.4 I Tupling
.. y
. 236
.. ,. , ... . . . .. . . , . - ""'- .
.._... . . .
. I

. of ws: The sititatiori is very similar to that of the



-

Fibonacci ft.inctio n, except that.


~ ' ,.
I '

:
be$t == [tuneJJ.~ [Line] ' : ' .. . .,,;
ins tead of having two recursive terms, there is
a list of tbem.
bes t= The solution is 'similar: define (1/ltails by ,.
(o/d/1 beuer
where better uss vss = if waste uss .s waste vss
l.hen uss else vss {illeails = map fl/1 .tails . ..
.. The function fllls gives all possible ways of filli
ng the paragraph: puted by computing filltails. It
.. We .~ave fill ==-head fl/!iqils, so fill can be com
The base case
remains to give a recursive program for fllltails.
:;. [Wo rd ]- [[L ine n.

: . .,, . . . .

fills .
l
'

fills ( ] , = (( lJ . . . } filltaiis (] . = 1liJ


.
=
'
~fills vs]
[us : vss I (us , vs) - spl its (w : ws), vs
t that ".
is e'asy, and for the ind~ctive case we argue firs
0

tha t if xs is a nonempty list,


0 '
0 0
0 0

The function spl its is specified by the condition


M 0
0 0 0

h that us * vs = Xs and us is
then split~ xs returns a list of all pairs (us, vs) suc fill ( '1-Y .: ws)
a number of ways, including
nO[ empty. The fun crion splits can be del'ined in = {definition of fill}
.. :
. ~ ' ' ' .:\:.'.: :':_'J.- .: .......
splits : :: (()(] - (([()(), (C<])J . best.[u s: fill vs I (us, vs )- splits (w : ws) ]
spli. ts ( w: ws) = Zip p (w :) (in its. }vs)) '(tails ws). . ...
.. . . .
. (ma
'
. . . . '... . . . .. = {defi nition of spli ts]
.. order of
.
of ws in increa sing
Here, in its ws returns the list of initial segments
'
(/nits ws)) (tails ws) ]
best [us : fill vs I (us , vs) - zip {map {w :)
'
reasing order of length. The
length, and tails ws returns the tail segments In dec
cti9n or~ retu rns a list of P.airs .of pos sible spli~s .iJ.~ which the = {claim}
fun lits.
sp_ the r~f
~ .
. . .
. .
firsn:omponem of each pair is a nonemply list best [(w : us) : vss I (us, vss) - zip Units
ws) (map fill (tails ws))]
How long does this program for flll take? The
re are 6(2 ") ways of. partition-
;i
a
. ~g . scquen c~ of length n into a lisr of non em
pry lists, fills re'turns 8(2 ") . so :
- {deffn.itior1 of fiilcailsl
-.
'., t 0(2 ").'... .
results and the time complexity of (ill is at leas
.. . . (fill' ta;ts ws)
] ~ '
bes. t..[( w: . ;' vss) ..- z(p (in
. {us
. .: vs.U
. us) its, ws)
~ th\1.~ .
To i~prove the progra m, we need the assumptio. .
;

- can argue
~: . . ' . Proof of the cl~ is left as an exercise. Now we
i
best inap (us :) = (us :) . 'be~t
t~ .. fllltails ( w: ws)
i.
fixed .first line , a bes ~ par agraph ~s obt ained by ra,kihg a bes t
In words , giv~ n i
ldefinilion of filltails, plus routine simplification
a
agr aph for the rem ain ing line s. Thi s con diti on is an ins tance of what is =
par
algorithm design.
known as the prin d ple of optimaliry in texts on fill ( w : vis} : (ill tails ws.
Giv en the ass um ptio n, it is easy to calculate tha t fill can.be .. defined by
. .. {above calculatio~ of {iii, sening (ts = fill tails ws}
'

. - ..
. ...
.
.
. '. ,,'. .... .r.-
'

. ,{Ill [ ) - (] '"'
bes t ( ( w : us) : vss 1 (us, vss) - zip (in its ws}
{ts)] : fts

. : .: - . ... . .
fill (w : ws) - best [us : fill vs I (m,
vs )- splits (w: ws))
..
tiril.e,'we nav:e. In summary,
Assuming that best and splits eac h takes,. .linear . '
- '
.. .

- . 0(1 ) fllltails ( ] = ([) J


T (fill)'( 0)
= + Lk-.oT(f lll)( k) fillt ai/s ( w : ws) =
T(f lll) (n+ l) 8(n ) {cs
bes t [(w : us) : vss I (us. vss )- zip (ini tsw s.{t s)]:
n} = 8(2 "), so fl// still takes
The solution of rhls recurrenc e relation is T({ ill)( wh ere Os = filltails ws
one ntial time. The reason is tha t fillv s is recomputed for ever)' tail sequen ce
exp
. - . - .. .
. .. -' ..
, ...
' .

7/.. Efficiency .l,5/ Conrrolling spate . .:':
238
'\ 't ..
" ... . ,'''
:
. . 239
. ..
, ~Ti1e ruts~e~-h~~ t~ .do ~it~ ~~~ce. There is a vety great advantag~ of ~vera~;;
. ' .
. ~or the riming analysis, we. have.. . ' . . ., .
over average when it comes .to 's'pace. Consider the evaluation of .
T((il/tail~) (0) - 0(1) . .. .. ' ' .
J(filltail~)(n + 1) = El (n) + T(fi/ltails)(n) average [ 1 ... 1000] . . .
. - ;. . ...... .,
.... . ..
Tpe solution is T(fil/tails)(n) = El(n2 ). The revised program for fill therefore
~

Since average xs ~ontains .two occurrences of xs.on the righthrutd .sid-e .of its ..
takes quadratic time.. . . definition, the list createdJ~y evaluation of (1 .. 1.000) as a result of the first.
lt is possible to .i.n1prove the program for fill still further. Once a li!le is too trav.ersal is retained for the second traversal. In other words, computing the
.long to fit _in the given width there is no point in generating any longer lines average of a very long list according to the firsr dctinition may result ln the
for they will not fit either. Tlus obvious but important fact is not explicit in the evaluator running out of a_vailable

space. With th~ second definition of


' . I " '

. average
'

..
' '

. .
program above, but.is hidden in the definition of waste. By bringing it to the we can arrange it so that the computation proceeds in constant space. This is
surface and _exploiting it, one can arrange to truncate fill tails to a list of len gth the subject of the following- section.
at most m, for some m depending on the given >vidth. The program for filltails
. take O(mn) steps,. which is linear for fixed m.
will therefore . .
Exercises

7.4.4 Average 7.4.1 .Supposc T(k + 1)


"'
~- zi(k) + El(Zk). Pr~ve that T(k) = El(2k).
I '
' ' '"' ' ' ' I

The final illustration of tupling aclueves a mor~ modest increase in efficiency. 7.4.2 Suppose T(n) = T(m )"+ T(n- m} + 0(1 ), where m = n div2. Prove that
,

Compared t o the asymptotic improvements recorded above, the example leads . . =..
. T(n) El(n).
. .
to at best a'constant factor improvement in running time.
7.4.3 Prove by induction th.\'l t (ibn=((/>,., - cj,n)/JS, where qJ = (1 + ..JS)/2 .a nd
The funcpon average is defu1ed on nonempty lists of numbers by
cP =(1 - .JS) /2 are the tvvo ioq'ts of x2 = x + 1. ' .
average :: .. [Float] - Float'
. . . . ' .
7.4A Assuming that beuer:(u~: uss) _(u~: vss) == us: better uss vss, prove that
.
average'xs = (s~mxs)/(lengthxS)' best . map
(us :) ~ (us:). best. :. . . . ' . . . .
E~aluati~n of average requires two traversals of the argument, but by !UPling ...
. .. .I
we can bring it dov.rn to one. Define sum/en by . )'.5 - Controlling.space: . i
' ., . ' .... I
. . s;m1en ~
. ::' (su.rn xs,.length xs)
.
.. . Consider reduction of the term sum [I .. 1000], where sum = fold/.( +) 0:
we -have average' = uncurry (/) -. sum/en.. The .dir~ct recurs'ive definition of '.
sum {1 .. H)OO]
I
sum/en is I'
= fo/d/ (+)0[1..1_000]
su_m!en [x ] . - (x, l) - fold/(+) (0 t 1) [2 .. 1000]
.. sunl1e'n <X- :y : xs) == (x+ Z, n + 1 ); . where (i, n) =.sumlel! (y : XS) .' = fold/ C+) ((0 + i) "'2) [3 .. 1000]
' . .~ . . . . ' . . .
The fu.nctio~ aver~ge' .involves a slngl~ tniv~rsal or'its argtun~t:~t. . : The' ~wo: . ..
versions both take El(n) steps on a list of l~ngth n, and from the pO\l'l~of vie~-v - fo/dl(+)(:( (0.+0+2)+ +1000)[]
.. .
of timing there 'maY. .be
little tq choose between them. The ti.lne .saved by not = ( .. ((0+1) '+2).+ : .. +1000) ,.
traversing a list a .~e~ond time ~ay be lost again by having to form a p:~ at each soosoo
= . . : : ... I
I
step. Exactly the same sittiation arises with splitAr (see SectiOJ:l 4.2}.and span ~~Uii~i!l
~

(see Section -5:2): . So, why bother with a program that traverses its argument The point to notice-is thar in c;omputing sum [1 .: n] by outermost reductiO!'\
only once? the expressions' grow
. ..in. size' proportional to n. On the other
. hand, if we ' use.

. ..'
. . . .. . "~

.. . .. ..... . .' .

i.;

.(. ,.......,-_ . .. .. . ~ . "t ._. j .

.-,. ~ .
240 .. . .:-: 7 ..I Efficiency
~; ~
l.S/ Controlllng spac;e . 241
l
. .. :.. . . . ....~ ~.:..?-" . .. -... ..
I' . . .. ..... =--. - ....
..a judicious mixture of outermost and innf!rmost reduction steps,. then.we can = . (40 + 1) + 1
... ....
obtain rh~ f pllowing reduction sequence: . ~ :;-; _.
= 41 + 1 '.
- 42
sum [1 .. 1000]
-
. . .. --. .. ._-:.-
._ ..
... . -~
. On the other hand,
', . . _ -.1\, I '' ' '

:- foldl(+)O[L1000] '
fold/(+) (0 + 1) [2 .. 1000] . strict succ (strict Sf.!cc {8 x 5')) .

..
- fold! (~p [2 .. 1000] .... ......... = strict succ (strict succ 40)
- fold/(+) (1 + 2) [3 .. 1000] > = strict slice .(succ 40)
- fotdt (+) 3.[3 .. iooo] - strict succ (40 + 1)
- strict succ 41
= fold/ ( +) 500500 [ ] = succ 41
- 500500 = 41 + 1
" .. .'
' .
. ' .
. -. - - 42 .). ..1'' ~.:. .. . ~
.... :
. . . . ', ,,. .
, . { .'\'f. <~:::;':.'~ .....,~.. ,.,.
'The miiximmn size of any expression m'this sequence'is b'ounciecl by~ constant.
In short, reducing sum [1 .. n] to normal form by purely outermor reduction re- .Both cases perfo~ the. s.~m~lectu<;:tion steps, but in a different order. .
quires D(n) space, while a combination of innermost and outermost reduction Currying applies to strict as to anything else. From this it follows that if f
requires Only 0( 1) space. is a functi'on of three arguments, writing strict ({ el) e2 e3 causes the second
... This-suggests that it would be useful to have a way ofcontrollinifreduction argument e2 to be reduced early, bur not the f'irst or third.
I

order, and we now introduce a spedal funct'ion, strict, tl~ar allows us to do so. Given this, we can definea function s{oldl, a strict version of fold/, as follows:
!!

'. s{oldl (e) a [ .] . .., .=(.,) . .a. . .


7.5.1 H~ad-norm~l form and the .function stric~ ... ....- ' .
' . ' I
sfoldl (e) a (x :xs) .. - strict (sfoldI (<a)) (a GJ x) xs
Re.ductiOll ordei; may be controlled by use of the special [{_mctio'il strict'. A te~m
Wirh sum = s{oldl (+) 0 we now have
of the fot:m srr.id f eis reduced by first reducul.g e to llead-norm"iiJ form, and
then applyiilg f. An expression e is in head-normal form if'e a
is.. fUnction or if
' .
~

'
.. e takes the form of a data type constru~tor applied to 'zero or ~ore' arguments.
. .
-
sum [1 .. 1000]
s{oldi (+) 0 (1 .. 1000)
Every expression in normal form is in head-normal form, but not vice versa. For
'i
!Ii exampie, e/: e2 is in l}ead-normal form but L<; 'in norma,i. forrri.oniy~hen e1 and - strict (s{oldl (t,)),(O 7 ~ ) [2 _.. 1000]
e2 are both in qormal form. similarly, Fork e 1 ~ and .(e1; e2 ) are mliead-normal -
>
S(oldl( +) l[2 .. 1000]
form but are not in normal form unless e1 and e2 are h} ti'ornial tbtm. In the = strict (s(oldl ( +)) (l _+ 2) [3 .. 1000]
expression ~trict f e, the term e wiil itself be reduced by.out~rrriost..r ed.uction, - s{oldl ( +) 3 [3 .. 1000]
except, of course, if further calls of strict appear wWlc r edudng : e.~:.:.- ' '

. a si!TIPl~ exwnple,
As .
ler. s~cc x =. x. 1- 1. Then
. . .... ...
sfoldl (+) 500500 [ J
' =
. . - 500500
succ (sui:c (8 x 5))
- SUCC (8 X 5) + 1 This reduction sequence evaluates sum in constant space.
- :((8x 5)tl)+ l .. .
:... Le( us now consider the function average' of the previous section; tbis filnc-
...
. . - .. - . --- ~

. .
. .. . . .
.. . ~ -:- . . . .. - .....:_ ....
... :7./ - 1.5 / Courrqlling space. .. .243 :.
242
. . .. _, ...
.,
~ _. ~ .... Emdency
..: .' ... . ~ - ~.
: '.
.
.. ' "\ . .
.. ~ -..': ...
~::. .. '
. ,o

. .. .. . .
I : , : ' " ; ' , '

. . - cOnSidC~ tt1C value's o(fx:~nii strict (X iil the tWO CaSeS X = 'J. ru~d >< <~> .l. 'This .
tion can be dermed by
~ .
'

t 'I explains the name strict. . . .. . '


average' = imturry (f) sum/en Furthermore, if f is sti:ict, but not everywhere .L, and e .l, then reduction *
sum/en '= fold / f (0, 0) "' off e eventually et1tails redtJ.C.tion of e. Thus, iff is a strict function, evaluation
. '
. . where( (s, n) :x = (s + x,n + 1) of f e and stricr{ e. p edorm. t~l~ same reduction steps, though possibly: it1 a :
different order. In_o'ther .worcls, when { is strict, replacing it by strict {.does,
Supp.ose w~ replace fold/ in the deftnitiC!n of sum/en by s{oldl; do we t~en ~btain . not change the meaning' or tlie asymptotic time required to apply it, altliough ..
a constant. space program for average'? To appreCiate. why the answer is no, it may change the space required by the computation. ..
consider the red4~tion sequence It is easy to show thaHf\ i iBx= .l for every x, then fold (e) .lxs ;,; .l for every .. '
finite list xs. In other words, if (Gl) is strict in its left argument, then fold/ (Gl)
sumler1b : . 1000}
is strict, and so is equivalent to strict ((old/ (e)), and hence also equivalent to
- sfoldl ( (0,0) [1 .. 1000} s{oldl (Gl). It follows that replacing (old/ by sfoldl in the definition or sum is
- strict (sf oldi f) (0 + 1,0 + 1) [2 .. 1000) valid, and the same replacement is valid whenever fold/ is applied to a binar.y
= s{oldlf(0+1 , 0+1)[2 .. 1000] . . operation that is strj~ t in .its .first argument.
' = :strict (sfold~ n
((0 + 1) + 2, (0 r 1) + 1) [3 :- 1000]
. '.
;:', . ,. '
'
. : ., l

: ..:..:' ~{Oidi{((0+1)+2,(0, +l) +1)[3.. 1000} . . . ' ' :


' - ' ' . . .' \ ..... ' ', : ' .
. . .~ ' . 7.5.2 Fold revisited .. ...,. :~ r ,

and so ~n. The problem is that an ~xpression ~uch as ( (0 + 1) + 2, ( 0 + 1 )+ 1) is in


The first duality theore~ given~ -section 4.5, states that. if (e) li associative
. head-normal form so no further evaluation is required by strict. Th~ re~ulting
with identity e, then
evaluation of sunlle~ [ 1 .. n.J v.1fi .use 6(n). units of space. The s9lution is to . -
make not only {oidl f. strict, but also to make f. strict by de lining foldr (e) exs = fold/ (Gl) exs
.. . . . , . .'
r {s, n) x. ,,:; .strict (strict tuple (s + x)) (n + 1) for all finite list~ Xs, On the other
hand, the two expressions may have different
. . . ., . . ' vhere !Uple a.b = (a, b) tim~ <llld space con1plexitfes:"which one to qse.depends on the properties of
. .. .. .
~ ~ ~ ~
The. revised n~ch.iction
' "
sequence now
(]). '

reads
' ' l '.': .. '

. ... . , ' . First, suppose that. Gl_is srri~t i.n, botl_1 arguments, and can be compu,ted in ..
0(1) .time and Oo} spae. EXamp.l~s that fall into til.is category are ( +) and
(X). rn this case It is not.:hara .to verjfy that (oldr (E9) e and {ofdl (Gl}. e both:
sumlen [L 10001
.. . S{!Jld/('.(0,0 ) [l .. lOOO}
require O(n) time. and O(n) space to compute on a list of length n. However,
- strict (s{oldl {'>'(strict (strict tup/e-(0 + 1)) (0 + 1)) [2 : 106'0]
the same argument used above for sum generalises to show that, in this case, .
- strict (s{oldl {') (strict (strict ruple (0 ~ 1)) 1) [2 .. 1000)
fold I may safely be replaced by s{old/. While s{oldl ( Gl) a still requires O(n) time
- ;t,-i~r{sfoldl {')(strict (strict tuple 1) 1) [2 :.10001 . to evaluate on a list of leirgtlf n, it only requires 0(1) space. So, in this .case, .
= .. strict.(sfo/dl {') (1,1) [2 .. 1000] ,-. .~ s{oldl ~~the clear-Wilmer..' ,: -:. .... -'
. s{oid'r t (1,1) [2 .. l .OQO] . . .. . : . . If Gl does not satisfy t:he above properties, then choosing a \vinner may not
be so easy. i-\ good-.(tile .Qf tht~mb, though, is that if ffi is nonstrict ln 'either
and iio on. It is ~iear that this sequence has the desired behaviour:: . argument, then f oldr is usually more efficient thari f oldl. We saw one example
T11e operati~~al d efinitl'on of strict can b~ re-expressc'd i:n.the foll?wirlg wa_Y::. in Section 7.2: the fiuicti_ciu concat is more efficietitly computed using (oldr . .
. ' . .- ..... .
than using {oldl. Obsenr.~;(tha,t \vhile +I is strict in its first argument, it i~ got .
strict f x : := :if x = .l then .l else f x
s~rict in its second. ~. .. '.': ::
'Recall th~t a runclion f is said to be stric't iff~ = .l. H follows from the ~bove Another example is provided by the function ahd = {oldr (/\) True. Like
. equa.tion that r =
strict f if and only iff is a strict fU?ction. .ro see this, just * tl,le operator" is stritnn irs first argument, but nonsttict in its s econd. In ..
w ~. . -. 0

. . '' . '., ;-
'
.... . ..
' '

.. -" . ~ . ..,
;I
II' il'.
tL,
'
!if~
r' ' .. ......... - .;
J/
'
.. ,__ ...,_ .:: ..! ..
.1; 24<1 7I ..... ~.<4U, j Fusion: finite differencing, and deforestation 245
't . .;/ .' . .~:~~~.~,~~E:_~. . ,

~l4' . particular:_.paise.1\ x returns False wi~thout evaluating x. ~s?.UID~ we are "'"""' .6.1 Q;,nCksbrt
! I
a list x..~ of n boolean values and k is the first value fonvliich:xs:.!! .k = . ( . . : . ' . .
:I( necall the 'function sort of.Secrion 6.2:
j "J
.>:
Then evaluation of foldr (/\) Truexs takes O(k) steps, whe~casfo!dl (/\)True
requires . n~n) steps. Again, fo/dr is a better choice. . .~;~~- sort tiatten mkScree
T
=
To summarise: for functions, such as + or x, that are strietin both
, I . . -rhe f~ncii~n m~tree buildsa. bill~ search b-ee, arid '[latien lists its labels in
ments ana can be computed in constant time and space, s{old] tw ore .............,"<
~

jl,
I;
. But for functions, such as 1\ and *,
that are nonstrict ~ some
~gument, tro1,;-.;
ascending order. The definitions were
is often more effiCient. .

-
data ( Ord tx)
"

lI. => Stre~ ex = Null Fork (Stree ex) ex (Stree <X)


111'1
i :. ' .. .. .'" . .
.. 171kStree .. (Ord ex)=> [<X)- Stree ex .'
lI : Exercises

7.5.1 Write down a definition of the function sum that does riot use strict but
mkStree [ ] -
mkScree (x: xs) -
Null
Fork (mkStrtte ys) x (mkStree zs)
i
I
nevertheless does evaluate in constant space. where (ys, zs) = partition ( ~ x) xs
i
!. 7.5.2 Ho~ should minlisc be defined? .. ;._
..... partit(on .. (ex .- Bool) - [tX) .-: .((e<], [e<])
=
' '

(filter p xs,fi/Ciir (not p) xs)


...
I parCi~ion p xs ' "

7.6 Fusion, finite differencing, and deforestation \' ..


...i:'. .
,;

.. StreetX- (tX]
:.
..
flatten
'{latriw Null = []
. .
I I {li:men (Fork xi x yt) = flatten xt * [x] +!' fla~ten yt
ll
'
I''
;'
;; .
The aim DO\~ is to fuse the computation f7atten and mkStree, thereby elim-.. of
I,
i.nating values of type Stree et from the program. The result is a function qsorc
,.; I
I'
definedby
.if . '

;
r:-.~ qsort ..
' ,.
(Ord e<) :::> (tx) - (IX]
,,.;.,. .
I
. . .. ~ .
qsort_[ ] = []
{ {oldr g a {oldr h ({a)
.0
,~~:!

,,. =
J ~
qsorl (x : xs) = qsorc ys * [xj * qsort' zs
i 'i provided f is a Stlict function and { (g x) = (h X) {. Operationally, the w4ere (ys, zs) = partition(::; x) xs
'~.. i' : . .. ..
left-hand side says that a value is assembled out of the element~ of a list, and This is a version of a famous algorithm, called quicksort.
~~:
' 1! then is consumed by a function to produce a second value. The right-hand side To time"qsqrt,xs, supp0se xs ~s a list of length n > 0. The. list filter (::;x) xs
says th'
. a r, .provided a ceitain condition holds, uti .ciiii
j I
.;' . .
theseconci:val
. . .. be produced c~ have ~Y length k. in the range 0 :S k < n, in which case filter (> x) xs has
directly t'rt;>m the elemen ts of the list. The conditiop f (9 X) '~..$x) f asserts
~

'
length n - k - 1. Since T estimates the ..yorst-case running tlple, we have to
}. that the value returned by f can be computed incrementally. The terms finite choose the ma-ximumtiming estimate taken over all possiblesplits. Hence
'
~ : differencing and formal differen tia cion have. also bee!l; lis~~'ti i' describe this
:'
'
: I situation. We have seen a paradigm application of finite differencing in tJ1e T(qsort)(n)
. '
= maxo.sk<n(T(q sort)(k)
. + T(qsort)( n - k - 1) + .8(n))
'
.' I
jl problem of the maximum segment sum, considered in Sectlo.nA.-5. Recall that The El(n) term' accounts both for the time to e,valuate ys and zs oil a list of
this reduced a El(n3) nmning rime to 0(n) . ... :~~ ,,,,.,~..
l One particular use of fusion is ro eliminate intermediate datniypes from a
lehgth n, and for the concatenation of the sorted "results. Slnccthe worst case.
~ occurs when k = 0 or k = n - 1, we obtain
: program. This particular device is called deforestacion. We saw one example ~ . .4 ' .,

J in Section 6.6, and in the rest or this section we consider one 'more~ i{qsort )(n + 1) = T(qsort)(n) + El( n)
....
. .. . ..
:: .
.. .. . .... ..
. .....

'
'
I
... - - ..
.!.....
"
'J ..,
. 246
. ..... ..
, '

71 ElTiciency_ 7.6 'I Fusion, finite dif(c;encinfi.


. ..and deforestation 247
.'. . . . ~

'

Til~. s~lu~io~ is T(qso;~)(.,.;) q~adratic~~~~- ai componen_t i~n~th zero._:;E~alci'atlon of pis trigge.re~ by evaluating th~ temi
'
= e (n2 ). Hence'quicksort is. a
gorithm in the worst case. On the other h~d, quicksort is efficient on average, qsort (fst p). However, tne n units.of space occupied by p cannot be reclaime-d
taking O(n log n ) steps. until the corresponding term qsort(sndp) is evah,tated when the pointer top can
. Can ~e improve the performance of qsort? The presence th e opera- of * be thrown away. Bet\oy~e~-~es{~vo evaluations further triples are generated. .

tions signal that the accumulating parameter technique is likely to prove bene- The fusr occupies n - 1 units of space, the second n - 2 units, and so on. -Th~
ficial.Suppose we deful~ qcat by . total space required to c~ out the computation is therefore D(n2). .
..
[ n practice, this means :thin evaluation of qsort 011 some large inputs i.vill .
qcat (Ord a) ::. [a] - [ix] - [a] abortdue to insuffident available space. The solution is somehow to force
-. : qcat xs ys = Cl~_orl xs * ys evaluation of partition ;md/~q~~liY. important, to bi.l1dys and ;s to the respect~ .
i~e components of the resulting pair, not to the pair itself.
'' Routine synthesis now yields
.

One way of bringing ahout tllis situ~tion is to fuse the computation of



qsort xs = qcat xs [ l partition into the ~ain progran1. Define the function qhelp by
= ws
qsort (vs fl. zs)
qcar [) ws
qcat (x : xs) ws = qcat ys (x : qcat zs ws)
qhelp x xs us vs = q$ort (us* ys) +f- [x) *
'.
.. . . ~ . .....
:where (ys;zs).=)Jardtion (~ x) xs~
. .. ' . : .. . ,
....
.. ' .
. . .(ys, zs) = partition( ~ x) x.s'
. wh~re
.. .. '
In particular, we have
Th~ r e's ult is aprogr'~ that is .faste~ than before, but which is still or'ciuaclratic-'
time comP.lexily. . qsort (x: xS)
There is another optimisation of qsort, one that involves space rather than . - .. . . . . .
=
'

{definition of qsort, Writing (ys, zs) partil'ion ($; x) xs}


time. In t~e computation of partition(::;; x) xs, 'the list xs is trav~rsed twice. A
similar situation arose ~th the function average in Section 7.4, so we should qsort ys * [x] * qsot czs i
combine the two traversals into one wHh an apP,eal to the tupling techn.iq~c. .
It is
- {de~tion of -qhelp} : I
. easy to rewrite the definition of partition
- ...
in the form
-
qhelp x xs [ } (.J, : . . !
I

l
._pqrtition p
= (oldr f (( ], [ ]) It follm~~ that qsort can be_defmed in terms of qhe lp by
I
where f y (ys, zs) =if p y: then (y : yS, zs) else (ys, y: zs) qsort [ ] - [] I.
,.
Ill'this version the argument list is traversed once.
Having rewritten the definition of partition,_it may be thought that the pro~
. .
qsort (x: xs) - qhe/p x xs [ ] [ J
!
!.
The final step is to synthesise a ~ecwsive derin~ti~n of qhelp. The base-cas~s ,,I''
gram for qsorl' is now as .space efficient as possible, but unforturiately it isnot'
For some inputs oflength n the space required by the program is D(n2 ) . .This = * [x) !I

a
" . situation is referred to-'as space leak. A space leak is a hidden loss ofs.pace .
.
qhelp
.
x []. us vs .
qsort
.: us
.. ..
+t- qsort vs I

an.
.. . ' .

For the recursive case qfi'e{p"x-{y: xs) us vs, observe that .


'efficiency. the space leak in the. above program for quicksort occurs with ' . I.'
' .
input which is already sorted; but in decreasing order. To explain why-it arises,

partition (s; .x) (y: xs! := : ify :S.x the.n (y : ys, zs) else (ys, y: zs) .; . .
us
' ,, ' I

.. !r
let rewrite the recursiVe Gis'e for qsort in the equival~nt form ' i
'
. . ' +

. . . I
where (ys, zs) = partitiqn ( ~ :x) xs 'I
=.. * (x] *. qsort (snd p)
'

qsorf. (x : xs~ qsort. ({sc p) '


.
For b~evity, we will calc~l~t~~the _rect~~~ive <;ase ass~~ning .y ~ x;
~he.re p = pm:titi()n (::> x) xs ..' .._.. . ' . . .
., .
qhelp x (y : 8S. ). us vs
lf (X: XS) has length (n+ 1) and is in decreasing orcier~ thert p= partition($ ~)xS '
is a pair of lists in which the first component has length n and the second
. ,;. .. . '
- {definition of q/:le[p, writing (ys, zs) = partition( ~ x) xsl
' - ~ .

- :
...
. ',.. .
~
...
248 : .. . 7 I Efficiency
7.7/ C~apter notes 249
. . . ..
. .; :-.::.;c~
.... ,;- -.
. . .- . ~!:.'"!....
(us* y: ys) * [xh+qsorc (vs 4r is).:.-; :.
. ~

'
qsort
...
-:~.
--
.. . - ~ 7.7 . cliaiJter notes
{claim: (see below)) ~~...: -~ -
For more information on lazy evaluation and graph reduction, consult the books
.,
\
qsort (y: us* ys) * [x] * qsort (vs * zs)
.
......"'.';:. ..... ..,......
".
) Peyton Jones (1987) and Peyton jones and Lester (1991). Asymptotic notation
(definition of qflelpJ and the .solution of recurrence relations usillg 0-noratlon is covered in Cor
\-
' ,_1 '
.
men et al. (1990). The subject of asymptotic tinting analyses of lazy t\mctional
- ...
..o. ';. . -

qhe/p X XS (y : tiS) VS
... .: probrrams is still a r esearch area; for various approaches to the problem, see
and
,' \ '

The claim is that if ys is any permutation of xs, then q~ort :=. qson ys. The xs Bjerner Holmstrqm (1989), Sands (1995), and w'adler (1987). .J
claim is 4l.tuitively obvious: sor ting a list depends .only Ol\ the ekments in the The idea of fusing two computations is as old as the subject of program
list, not on thefr order. A fotmal proof is omitted. This property of sorting is trahsfmmation itself; for anearly reference on the technique in a functional ..
crudal to the development of a space efficient implememation of quicksort. setting, see Burstall and Darlington (1977). The accumulating parameter tech-
The result is the following program for qsort: nique is s tudied in Bird (1984).
For more on the rupling strategy of program optimisation, see Bird (1980)
qsort () = (] and Pettorossi (1984). The principle of optimality, and its importance to dy-
. qsort (x : xs) = qhelp x xs [ ) [) . na.mic programming algoritqms (of which the paragraph problem is an ex
'qh~iJ x [ 1us vs - q~orc us*[xJH-c/so~c~~ .. . . .ample), is discussed in most books on algorithm design; see Bellman (1957)
qheipx (y: xs) us vs = .if y $X where the teclmique was first discussed, and also de Moor (1994) which presents
then qhelp x xs (y : us), vs the ideas in a categorical setting. Bird and de Moor (1 997) contains a systematic
.,.. :.. account of the usc of dynamic programming in solving oprirnlsation problems.

else qhe/p X X.S US (y : VS)
i The problem of filling a paragraph is treated in Bird (1986) and in Knuth and
. The.
. result is
. a .fairly unappealing program that, neverthel.ess: . now . has ..an O(n) .. Plass (1981). .
i space complexity. Furthermore, the acci.unulating parameter teclmique-can The idea of eliminating intermediate datatypes from a computation is stud
t again_be invoked
. to bring the runnirig time. down by a snialfconS'tant
. factor. ied in Wadler (1984: 1990b); se~ also Bird and de Moor (1997) for other ex
I.j. In functional programming there are b!=tter ways ro sortthan by using quick- . . . amples.
,...i.. sort. On.the other hand, it is fascinatingto study a single .p robletli in which the Quicksort is due to' Hoare (1962). Hughes (1984) was tile first to notice the
~~
::, teclilliques \)( dcfoiestation, accumulating parameters;'tuplitlg, and fusion, all space leak in quicksort wh~n expressed as a functional program. See Runciman
:'j'
play (r9le. .. .. : :' and R5jemo (i996) for techniques for identifying space leaks.
,,.
,!:
,.,
'
. . . ..
.... . . . ,,. ..
Exercises
~
.
. 7.6.1 _T 4e value s~lect k xs, where s.elect k = (!!k) sort;se.l.ect~ .tQ,<;_kth largest
;! element ~of a nonempty lis t. In particular, minlist = seleaO, Taking sort =- qsi:m,
J . fu~ion_to
use . .
produce a more efficient algorithm
.
for s~/ecr:-
.. . .
: . .;....
.
7.6.2 If one assumes that each possible split in the recLirsive case of quicksort
ts equiilly1ikely, and the same is true pf all subsequem :sp)its,.rh~n the average
case estimate A(qsort) of qsort satisfies ....
. . ......
,. ,.
. . . . '
1 n ' '
. .
,.

A(qsort)(n + 1)'"' - L(A(qsort)(k) + A(qsort)(n ~ /() :.f..e'(n})


n k" o . ,
' I '

! ' Prove that A(qsort)(n) = 8( n log n). ..


... .. ..
'.
.. . . -
'
., . _,:-_ ' ~i.- .

.:, :.:,.... ,' : . ~: . : J t ~....: : . ~. : :::.~ :.t:. . .! .' : . ., .


. . : ., . '.. >.:~: : .. ...... ~;-:. ~ +'' ' .'l .- < '}..:. ~- : .. .. ' . ~ '
.-. ,_. .. .::,,
, ' 1

.. ..
. ' Chapter 8. . . -.
,.. +

. . r' .

-~-__;_~'!:-"-.........~~-------...,--...;.-----.....:.;;...-
. ........
:

.
., ,' . .. :
. ...
Abstrac:t. .d atatypes
' ' ' .
. .. .
" ... ' ..
. .
.. .
.,

'. ' ...


:.: ..,.
.. .
.. .
.. .
... ..

.
~:
The aim of tills chapter is to introduce the idea ~fan abstract datarype and the
.. ... . mechanisms provided byHaskell for defirung them. Broadly speaking, abstract
.. , ' . .. ., . .. . . data types dil'ter .t'rmh ti1~s~ ~troduced by a data declaration in that on~ ~an
. .
.. .
~ : ~.

.
~. . .. .. ..
' ..
to
choose how represent tlie'ir 'values. Eachchoice of repiesei.J.tation ~eacls ro
i,.
.
a different implenientation of the data type: The main ideas are worked out
.
'

..
.
in . the study or four abstr~ct datatypes: sets, bags, arrays, and queues. In
' 1
.
ea,ch example, 'the data type is .specified formally, possible representation's are .
suggested, and the efficiency uf different implementations is cori1pared.
. - ., .
' . . - ' .. ' . " . .
. 8.1 . Basic concepts ..: '' . ', .

.. '
.. . a
The effect .of data .dedijQ.po'n-is to introduce a new data type by c~es.cribmg;,
'' how its. elements are constructed. Each clement is ~amed by an expression.
.
. - ..,
. .
.
. ..
..
built only from the consJi:\t,ctors of the data type. Moreover, different pames : .
denote different elements. By using pattern matching on the constructors, we
can define operations thatgenerate and process elements of the da.tatyPe in any
,
fashion we choose. Accordingly, there .is no rieeci to postulate the existence:of .
' .

.. : ...... ...... .. . any additional prii'nitive .oplfr<itions.. Types in which the values are described, .:
... butthe operatiorts are no't,:~e 'called concrete types. . ' ., .
,
... ..... + +

t .. .. : . ... - The situation is just tl~e reverse with abstract data[ypes. An abstract data ,.I
type is defined.not by na~ling its values,.!Jut by naming its operations. For.:
. ! .

.. . I

example, Float is an abstract:datatype in Haskell. . We are given the prirrutive


comparison and arithmetic ope'iations; and also a means for displayir).g flo<;lting .
is
point numbers, but it no~ .s~ated how. such numbers are represented.hi the ; :
Haskell evaluator, and we cannot do pattern matchmg with them. In general, . ii
the programmer who uses an abstiact datatype may not know, and ina)" eve~~ .
II
..: . . 'I

..... be prevented from knowing, how the elements of the data' type are repiesen-:.
, ..
. .. .. . .. : .. '
'
.. .... . ..
'. . ... .". , .
,.
'
.
..
. ,~.,. U+i
. ./ -~ .::.r
25 2
. .. - ./ .. .. .
. 8 ~ f\bstr,ai::t datarypes 8.1 /Basic concepts 253
. '" '*
~.... ~- . .. ..
... : . . ;'" . '1..,:-;:t~... . ..
. . .-; .. ~ - "1>: :. ~- ...
ted. .such absmi~tion bc.rriers are useful when more than oneprogrammer is fr:ont (join x e~pty) - . .' . .
on
X . ,.

\.York.ing ~project, and even when a single program.me.r is:workin~ on a non- .. front (join x (join y xq}) - front (join y xq} . '

. trivial task. In'particular, a representation can be 'changed without affecting the


I' v~clity pf' scripts
. thin n:ake use of the ciatatype~ ' :.. .
', .
back (join x empty) - empty
.\ . .
back (join x (join y xq)) "' join x. (back (join y xq) )
8.1.1 An exainp}e .

. .
. The first thing to notice is that these equations look very much like formal
' I
Let us now give an example of an abstract datatype. Suppose a programmer definitions of isEmpty, front, and back, based on a datatype with construct-
'I
I
wants tO make use of a data type QueueC< of queues over an arbitrary type IX. The Ors empty and join. Indeed, they were designed precisely with thjs idea in
basic idea of a queue is ttat one can add elements to the rear of a queue and take
' I

.... mind. However, they should be properly understood only as expressi.i:tg cer
elements off the front of a (noncinpcy} queue. A queue is thereforea species of rain relationships between the five functions. The implementor is not forced
finite list with a restricted set of operations. The programmer wants an efficient to implement queues by a data type with empty and join as constructors.
implementation of Queue C< but is not interested in providing it Instead, he or The axiomatic specification of Queue IX, together with what can be derived
she may ask another progr'ammer to provide a suitable implementation. or may from it, is the only thing that users of the datatype can rely on. In particular,
"i use an oif-the-shelf solution supplied by the system envi.:onment: H.ow'can this no value for back empty is prescribed by the specification. From the user's
situation
. be realised? . ' . - . poim of view, back empty = L, the undefined queue. Depending on how we
I'
, Fir.stly, th~ programmer wants to know what primitive oper&ti0nsare given. interpret the ci.xiOmS, it may be possible tO distingtiish betWeen J.: and'join X l.
suppose thar the queue ,)perations are
1: 1

.. . For example, the axioms for isEmpty do nor prescribe a value for is Empty J. but,
depending on the interpretation of the second cixiom for isEmpcy, we might be
.. ~mPty . .... .Queue IX - able to deduce that isEmpty (join x l.) "' False. To resolve this ambiguity, ~ve
join C< - Queue IX - Queue a add another axiom to the specification. namely that join x is a scricr function
front .... Queue ex - a for all x. Then we h~ve
. back- ..
.. Queue ex - Queue IX .. . .
isEmpty .... Qlleue ex - Boo/ '
is.Empty (join x .L} = isEmpty .L "' l.
. .. .
The list of operations, together with their types, is called the sfg~<!_rure, of the The major consequence of join x being strict is that there are no partial queues
datatY.Pe Queue.a. : . . .. .. (apar,t_ fro11 .L) or infinite qu.eues. It i~ left as an exercise to prove by induction .
' . .
Set'ondly,.~e.programmer needs to know what these operation;l!..mean. The. that if join xis str ict, then foldr ]oin empty xs = .L for all infmite lists xs. The
names and types give some clues, as does an informal descripti.on;but more : implementor of Queue ix therefore does not have to proviP,e for infinite queues.
precise information is n~eded. Users of the datatype need to know what they It follows that eveiy queue, .apart from .1, can be expressed as a finite nurn
c~n rely on, and the impleme.ntor of the datalype needs to know. wba.t has to ber 'of Joil) and back applications to the quet!e empty. Fu:t;therm(>re, by using
be provid~~ . the axioms for back. we can eliminate occurrences of back from such an ex-
. ..
-.. . _._. .. - . pression. It is aiso clear that ditferent expressionS .in terms of join and empty .
describe different queues. Hence each queue can be named by a unique expres-
8.1.2 Algebraic specifications sion in terms of join and empty. It Will not, however, be the case that elements
One way of supplying tbe. information is to give what is called -algebraic or an of eyery. abstract data type can l;>e named by unique expressions. .
axiomatic specification of Queue a . This consists of a list a.Xiems that ""' .. of
operations'should satisfy. One possible list is as follows: , . --.;. :-' 8.1.3 Representations
. . . .
'
ismpty empty . - True ...... In order to implement an abstract type. a programmer has to provide a rep-


. . (join xxq>
ismpty - False
.: -.~ ... .~> :
. . resentation of its values. define the operations of the type in terms of this
'
. ..
' ........... .
' ' ' . '

'
.-
- ...
. - ..
B.J I
. 254 8 I Abi tract daratypes
.
....:--::..'. .~ ...... . Basic c~ncepts . ..........
' . 255
. . . ., ~ :' ~~ .:~~~ ~~ .. . . :
>;.: Queue a- [a]
*

.. ; representation, and show that the implemented operations satisfy the pre- ..
reprn "
. . s.E:ribed specifi~ation. Apart froll). these obligations, the impletnentor is free .
. . ' to choo.se betw~en different representations on the grounds of ert'icicncy, sim- '
repr-ii empty . ' ' :..'[]:
plidt:y, or taste. In the following section we will describe mechan,\SJ'):lS provided repm (join x xq) ., = reprn xq * [x]
by Haskell
. for. hiding the implementation
. . ." . of an abstracuwe so ~hat r~ference . .
. ,
' '"
. .
- '

to the chosen representation is not permitted elsewhere in the script: . For example, abst-r [ 1:, 2]-;, join 2 {join 1 empty) . lr is lefr as an exercise to show
tet us now continue the exa'mple by providing two implementations of the that repm abs'tr'is the ldentity function on finite lists, and abstr reprn is the
;'lbstract type Queue a. identity function on queues.
.... .. . . .. :: : . .,-:. .: ~
First ,implementation. The first implementation makes use of finite lists to
represenr queues. The implementations of the operations are as follows: Second implementation. In the second implementation; the idea )s to repres:
ent a. queue xq by apair of lists .{xs,ys) such that tl:J.e elements of ?<q are, in
joinc .. a- [a] - [~) order, the elements. of the list xs l+ reverse ys. By breaking the list into t..-vo
joinc x xs = *
xs [x] pieces and rever~ing the second piece, we hope to make the queue operations
. . . . , .. more efficient.. We......
willalso
: .. '
impose an additional constraint.on
. . . the i'epres~lita-
. '" . ' ~

' '
. ~mptyc . :, [ocr . . ; . ... ' '\ .., .
' tion: queues will be rep1:cscnted by pairs (xs; ys) in which if xs is empty, then
emptyc = [] ' ' , ys is empty too . .Thu's not every pair of lists represents a queue; in particular;
( []. [x]) does not represent a valid queue. This constraiJlt has co be maintained
isEmptyc [a] -Boo/ by the programs that create .queues. Note also that two distinct p_airs of lists
isEmptyc~ - null xs. may represent the saine. queue. For example, . both ([1,2 ], [ J) and ([1] , [2])
.
. represent the queue join 2. (jo(n 1 empty).
frontc [a] - a For this implementation
.
we can define the fllllction abstr by ',

{ronl'c (x :. xs) . : :. . . . '

. ' . abstr ::-: Ua];[cx))- Queuea


. .. .
backc . {a]:- [Cx] ''
. ab,')(r.(xs,ys) ;,; .: ({oldr join einpty revl!rse) (xs -t+ reverse ys)
:
b~ckc (x : xsj = xs .. .. :.. ; : \~: . ':.' ~ .~.}. :. ..
,, . ,' .~ ' ;:~
~
(>
'

The function abstr is not il~ectivc, so there is no flillction reprn that is left-
The implemented ~peration~ are 1,rivcn diff~rent_ q.ames to distinguish them inverse to abstr; and so no one-to-one correspondence between queues and
from the abs~ract ones. All operatio.ns take constant time; 'except for joinc p~s of finite lists.
which takes e{~J steps, where n is the number of elements in the queue. (Actu- We also need to formalise the fact that not all representations arc valid. We
ally, this apparently obvious statem~nt requires qualification, but we will post- do this with a function. vali~ defined by
pone discussio.ti to the end of the section.) .. :

.. The next' task is to show t~at ~he ~pleinented operations 'satisf.ythe axiom~ . valid :: " : ([aJ. [ a )) -Boo/
' ' .
' ' 'of the specification. In the present case this is' easy because there is one-to ' a valid (xs, ys) .= ~not .(null xs) v null ys
one correspcm<;lehce between queues and finite lists (plus. i>.and SO each of the .. .... . "~.
.. .
'axioms holds w_hen tile.implementecl 'o pcratimis .ar~ substituted the abstract 'r6r The function valit.f fonnaiises what is known as a datatype invariapt, im idea
ones. We can fOtmalise this correspondence with .the help of two functions, that we' have aJready met in. a number of places. For example, in the dis~
absi'r and reprn, defined by ' ' . ... ..: - .. . . . cussion of rational riwi:ibers iri Section 3.5 we represented . rational ' numb~rs
.. '
only by pairs of integ~i in what was called canonical form. Similarly, bil~dry
abstr .. [a] - Queue a .
search trees were trees c~nstrained by a certafn data type invatiant. The p~
aJ?sty . .=. fo/dr join .empty reverse .
(abstr, valid ) fonnalises the representation ofqueues by pairs of list5:
... ' . ' . > '

' '' ....


' . '
....
,,
...
... .. .......>
256 8..1 I Basic. cqncepcs 257
.. .... 8/.~~$fa{:t cjatatypcs . '
. .... ~ . "
\

.' ! :~!...; . ~...


. ti~~d~. More generally, for every_ruoom of the form f ~- g, where f and. 9 return
: .. l' .i,' ~:

Here are the implemented operations: . .. .. .


.
..
queues, we require only that
~

: .. .... . .... .
emptyc = . ([ ].[ )) ..
fsEmptyc (xs, ys) null xs : . . abscr fc = abstr gc
= -. _. .. . .
. joinc x '(ys, zs) mkVa/id (ys, x: zs)
.. wher~ '{c and !Jc are: the resul,ts vih~n 'the .iJl1Plemept~d op~~:ations are substi-
. {rontc (x : xs, ys)
. . ' = x
~ .o~;:- .. . .. .
ruted for..the absrnii!t ones. .If f and 9 reruin other. values, then the func tion
backc (x': X.s,ys) = mkValid '(xs,ys) abstr is omitted i,n the equatio n above.
There is anothe r potenti al problem, though it is not .exhiQited in the way
mkValid .. ([a], [a))- ([a], [a)) ':: :;...-:- we have written the de(initions of [:he operati ons. We could have .written the
~kValid (xS, ys) = if riull xs then (reverse ys, (j) else (xs, ys) : definiti on of joi~ in the equ.ival ~rit fon'n .. ..
The functio n mkVali d maintains the datat):pe invariant, using the fact that join x([],[)) = ([x), [ ))
join x (y : ys, zs) . = (y : ys, x : zs)
[ ] ft-:-rev(!'rse ys = reverse ys * [ )
This defini tion is correct because of the datacyR e invariant on valid representa-
All operati qns now take constan t rune except for back.c. Iq p:&f.ti~i.Ifar, com- . .: .. . t' ' : . : .. '- , :: ~ .
tions. Now, assuming that ~\ie h~d ct~fin~c!jqin b (t.h~ . t.~yo cases above, conside r
'i} . : '..c,. ' .. .

putatio n of join x (ys, zs) takes constan t time because !J ys is empty, then zs
the axiom
, ' ' ' , ~ ~ ~ ~~
. ' .. ...
I' ' ' ', ' " '

is empty and reversing [ x) takes constan t time. The functio n back will take
constan t time except when the first list is a singleton. (Again, at. the end of the.
sectiop. we will. qualify these remarks on timing estimat es.) 'The seCQ!Id imple- ..
'isEmpty (join x xq) = False

mentat ion. therefore has a different efficiency than the first, andlu the end of Replacing lsEmpty and join by lsEmpryc and joinc, and xq by the pair (ys; zs),
the 's ection' we will
show that the efficiency is superior'. the ax.lom transla tes to
. The ))roof that the se.cond impie'm ent~tion satisfies the specification is also
diffcre n(fro.m the prev:~ous orie in that the axioms, as state~. do "np/ho ld for lsEmplyc Uoincx (ys, zs)) = False . .
..
the iniplemenred operations. Consider the. two axioms for back: - .. .
. . .., ~
. This -~quation. ~oes ifo'r hold fo~'all ys 'an(f zs:Tf y~~'lY~nd i~ 'a nonem pty 'zs
back.. (join x empty) = empty .... .. . list, the left-hand side reduces ro .L.by case exhaus tion in the definition of joinc.
back (join x (join y xq)) - join x (back (joincj1 x'cj)) .. Tile resolution of the problem is clear: queues should be replaced in rhe axioms
. .. oruy by vaqd represe ntations, so the equation above needs to be verified only
If tbeseaxioms hold for the implemented oper ations, then the following equa- \.vhen (ys, zs) is a valid representation.
tion should be. true: . . ' w e can summarise the situation using the following notation: if = g is an r
. (jo'incx (joinc y (joinc z emptyc) )) =
backc . axiom,
. . where
. r
and g rerum queues, then it i~ suffide nt.to. prove
.
... . ~

b~ckG (joinc x (backc (joinc y (joinc z (joinc w emptyc ))) ).).:., , ' :
7
.
. abstr
. fc = absrr
. gc (modulo vaiid)
However, ~s one can easily check, the left-hand side simpllfies to ([y, xj, [)) a!'}d
where {c and gc are the results when the implemented operations are substi-
the right-h and side to ([y], [x]). Whar we have nor taken into accoun't is that,
tuted for the absrract ones.
althoug h the two pairs of lists are differen t, they represent the siimequet'1e.
.There is another, more modular way to proceed. It is sufficie nt, to sho~~ that
The prriblem is resolved by realising that an equatronal ax:lo.~ is..Jnrended
the following equations hold (all modulo valid):
to mean that borh sides should deliver ~e same queue, nor the' .repres- same
entation. Thus, we should require only that 'the equation
'

. ... '
absrr emptyc = empry
abstr bqck(: joinc x joinc y - abstr joinc x backc :l}oirzc. y abstr joinc x = join x abscr

. .. ,,.. -~

..
' "J ~

258 . :.;\ ' .


B I Abstract datil types "'
8.1 I ~asic conc~pcs . . 259
.
/
,
... . .,~. . ' ~
-
abstr {ro.ntc = front : abstr. This:mig bt seem a sm<ill pp~t.:- after all, costs are paid in full by the end of
absl.,. backc = back abstr the computa tion - but-wecan imagine a scenario in which the dil'ferenc~ can be
i$Emplyc - isEmpty abstr importan t. Suppose we set up an interactive program to simulate queues. The
' subject ~f how to write s~c:h programs will be covered in Chapter 10, but the
Using the fac t thar, by assumption, the.absrract operations. satisfy the axioms, . followl.ng session
we cai1 now prove that the impleme nted ones do (modulo abstr and valid). Fqr ... . . . should
.. : -give
.. the'
., .general idea:
--~ '

example, : - : . . ? interact queue ' '

: backc joinc x joinc y - back join x join. ..., ..


a~str
. . y abstr Welco.m e to Queue. Type "quit': to qJ.lit.
I

abstr joinc x ~a eke joinc.y - join x ~ack join y abstr; . . . /


,
> join 1 /
and the.two tight-han d sides are equal by the second equation for back. ok ..
> join 2
8.1.4 Interacti on and amortise d costs ok
> front '
OtheJ; thirigs beihg equal, the best implem~p.tation of cia absqact.dat~type .Js l ..
one that mai<es ~e operatio ns as effident as possible. In' practice, though,._
> quit . -. . ;
there i~ usually a trade-off: one operation can be made more efficient only at j
bye
!

the eXpense of another operation. The crafting of an impl~me ntation requires , . I ;,


I

judgeme nt. as to where best to put one's eJfort .in obtainin g efficiency. There The interactive program sets up._an empty queue. We then give a sequenc eof
m~y also be reC}uirements attached to the specification or the datatype, in.tliat commands to ~dd elements to the queue, display the front element,_and so on.
one operation or another may be required to possess a certain efficiency. Each cmnman d is acknowledged, either by displaying the requesle d result, or
There is a complicating facwr when using an abstract data type with a lazy by sa.ying "ok".
functi~nal ianguage: .evaluat ion of a particula r opetatio n..may .rake place in : ' . The point about thi.s scenario is that the progranlffier who impleme nts the
stages through out the total computation. For ~ample, c~msider the first im interacti on (for a chosen representation of queues) can exercise total control
plement ation of queues. We said before that all operatio ns take con.s tant time over the point at'which eva.Juation takes place. TlTe interaction can be maP.e
except foi: Join, which takes linear ti.rrie in the 'length of" the queue. hi fact, to run eagerly, in which cas'e the .evaluation of the result of a join cori:unand
this stateci1ent is c01rect drily under a policy ci
eager e'!aluation; under lazy takes place before its acknowledgement, or it can be made to run lazily, in
evaluation the situation' is more complicated. To see why,. con'si~er.evaluatjon which case evaluation takes place when a front or isEmpty cornrt1and is given,
of : ...
or somethin g bet>veen the ~o. Depending on the policy, the user wil,l perc'eive
.' different delays between giving a command <md receiving an acknowledgemen t
(front join n join (n- 1). join 1) empty
.. Given til.is sce'nario, we can .talk about amortised costs as wei!' as ~vorsi'G"~se .
To compute front the queue has w be reduced to the form x : is. Hence the ~ costs. There are a number 'or ways of defining amortise d costs, but a simple
queue is fust reduced in EJ(n) steps ro
.. approach is the following. Suppose we can show that, for all n, a sequenc e of n
...
I'
queue conunan ds takes worst-case tirrie T(n) steps in totaJ. Then the aye~age
. ((([1] * [2]) * [3]) H- ) * [n] or amortised cost per operation is T(n) In steps. Under this s~h eme, each ' 'i
operation -receives the. same amortise d cost, so amortise d cost is a measw-c : ::"
and. the first clement is (etu:rned in a furthc.r 0(n) steps. Subsequently, a de- of the efficiency of the chosen representation as a whole. It does not depend
mand for the front of the 'back of the que~e takes anothe{ e(n) steps. In other
: I
on the speed at which the -~lterad:ion Is driven, which only controls when the
words., the total. co~t of EJ(n 2 ) steps required to build the q~teue is paid for in actual costs are paid. .. .
instalme nts when we demand informat ion about the elements. In contrast, the worst-case cost' of an individual opcratiori, thilt is, the max '.'
... \ ..
.. ...... ~

. "" ...
I. :..
'

~ II
l:..
.
'I> ' " ,. ' "

260
., .... . . a 1 Absti.aC:ca~ra!YPes . 8.'1 I Basic concepts
261
.
imuin delay that. may be
.... .. .
'
.
. .. ..
. .

betwee n giving a: commai)d ~l).d.teceiving


~xperienced
't.
. ..
;j' .,: ...~
.;
,... .

8.1.4 Using the fusion law for {oldr, show tl).at reprn. foldr join empty =reverse.
an acknow ledgem ent, depend s on both the represe ntation and the e-ag.erti ess Hence conclude that reprn abstr is the identity functio n on finite iists. Using
of the interac tion. By definition, the worst-case cost T(n) of an operati on is the
m~um n~ber of reducti on steps .require d to process the 9p~atl9n when
the charact erisatiOn that every qtieue is eirbe~ emptY or of the fo~m join X xq
for some x and some queu e xq! prove that abstr reprn is the identity function
. it appear s in any sequen ce of n comma nds. The timing estimat es--stated pre on queues. .. . - : ~ .' ~

viously for the firsf implementatio n of queues arc worst:c ase esclii1im~s\i.~der . ' ..
' ..
an eagerly-driven interaction. 8.1.5 Simplify the represe ntation of queues by pairs of lists by not imposi ng
. - .
Let us look ar amortis ed costs in the two implementa~ions of queues. In the the dataryp e invaria nt mentio ned in the text. Thus it is not require d th ar rhe
.first implem entatio n,. the worst-c ase time for n queue operati ons.is.ii3( n2 ) steps second compo nent be emptyif the first one is. How does the implem entatio n
in total. For example, this is the time require d lO execute n/2 joins followed by of the op~rations .change?. ,.
. .. .. ,
(n/2) - 1 backs, and then tO ask whethe r the result is empty. The amortis ed 8.1.6 Consid er the problem of describ ing a simple line editor. Suppose a Line is
cost per operati on is therefo re 0(n) steps. This is also the worst-case rime of a sequence of charact ers c1 c2 ... en togethe r with a positio n p, where 0 !> p $ n,
any individ ual operation. called the cursor. The following operations on lines are require d:
Compa re this to the second iinplem cntatio n of quet1es. Here, a list of length
k is reverse d only when there have been k joining operatiOl').S SUJCC the previ newline .... Line
ous list reversal, or the stru:t ~f rhe interaction. It follows that a sequen ce of moveStart .... L.i ne- Line
n queue operati ons takes O(n) steps in total, so the amortis ed .ros{ per op- moveEnd .... Line- Line
eration is 0( 1). steps. On the other hand, the worsr-case perform ance for any moveLe{t .... Line- Line
individ ual operati on in the sequen ce is El(n) steps: The second implem entatio n moveRight .... Line- Line
of queues is then;fore superio r. fn Section 8.6 we will describe two eyen better insert .... Char - Line - Line
implem entatio ns of queues . .... Line - Line
deleie

Exerci ses The inform al descrip tion of these operati ons is as follows: (i) .the constan t
... newline denotes an empty line; (ti) moveLeft mo~es the cursor one positio n to
8.1.1 Finite lists can also be conside red as an absrrac t dataryp e. For example; . the left (if possib le); similarly for moyeRight; (iii) moveStart places the cursor
consid er the operati ons : at the beginn ing of the line; similarly, moveEnd places the cursor ar the end
'. '

nil of the line; (iv) delete deletes the character at the cursor position; and finally
xat
List IX
(v) insert'x inserts a new charact er
....
null List a - Boo/ 'the cursor position. Give an algebraic
.. specification for Line. Sugges t a suitable represe mation for Line, implem ent
cons .... a - Lise a - List a
-t he.given op~rations, and show that they meet their specifications.
head .... List a - C('
tail List a - List oc .
..... ..
.. ,. . ..
~~
. ...
-- . . .
.
Give an algebraic.specification of1ists.
' . . ' ...
8.1.2 Following on from the previou s questi<;>n, an elemen t ofList- C< can be
represe nted by a pair (f. n) where { :: Nat - X and n :: /lfar. .T.,h(_value n
t
-

r
is the' length of the list and k is the elemen t at positio n k. ft?r~a~ise tllis
' .
represe ntation by providing a suitabl e abstrac tion funcrion .~n d imP.lement the
list operati ons. .'

8.1.3 Check that the first implem entatio n of queues satisfie s the algebra ic spe-
cification.
...... .
" .
' '' ' .
.. .~'

81 Abstract 8.2 I Modu~es. 263


. ....datarypcs ~
. ..
.,. . .
.. ...
~
,
.' . . ,,
.. . ... .... ..
. .. .. .
8.2 Module s . To usc the module in.:. a':'"script
'; . ..' . we have to i.mpon it with a declarat ion
.
. ' . : imp~it Q'iwue __. : _:
Hask~ll provides.'a rriechmlism,'calle d amod'uie, for defuling abs~act d~tacypes.
In fact the modUle rriecbanism.of Haskell can be used for more gene,ral p ur-
Such a dedarati(m is imide' a( ttie begimling of a script. for example, h~r~ is a
poses:b ut we will ~onfine ourselves tO explaining ho:-v 'it works fur abstr;)._Ct
script that imports' the 'datatyp~ Queue and.defines two func tion for 'convertin g
data types. H~re is <m example module: . . ... between lists an~.qul}ues_; _ :
. . . . . . .. . . ' .
module. Queue (Queue,. empty, isEmpty,
. join, front, back) where
. . import Queue
. newtype
. Queue
.. . IX= MkQ ((IX], (IX]) . . . ...
~ .~ . . . .
empty .. Queue.(X . . . ~oQ [IX] - Queue IX

empty = MkQ([], [.]) toQ = foldr join empty reverse l ,: .

{romQ Queue IX- (<X]


isEmpcy Queue e< - Boo!
isEmpty (MkQ (xs,ys)) {romQ q = if isEmpty q .then [] else {rorit q : {romQ (back q}
= null xs
. \'
' ' ., , ' ,'
....
: . ;
. It is left as a'n exercise (o sho~~{romQ c.oQ is the idcl.ltity f~ctioll on fihile "
join Queue IX -:-r Queue IX
:: IX - lists. ' ... '
join x {MkQ (ys, zs} = mkValid (ys, x: zs) . Theremaining point requir1ng cxplan.ation is why we have chosen to imple-
ment Quew! e< a new type rather than a type s~~nonym.. The reaso~1 hasto dQ
as
front .... Queue IX - IX with tlie desire lO kee p ~he im'p tementat ion hidden. Type sy'n'o nyms are si'mply
f r ont (MkQ (x: xs,ys)} - X devices for givlng aiternati ve names to e-Xisting types. A synonym apd its def-
inition are completely interchangeable. In particular, a type synonym inherits
back .... Queue IX- Queue.IX .. the class methods de'tii1ed fo1: ~he underlying type. So, if Queue IX was declared
back (MkQ (;c xs, ys)) - . mkValid (xs,ys) as a type synonym, we cowcj:.bteak the abstraction bm-rier. For example,
...
' -
mkVillid :: ((IX]! (IX]) ..:. Queue IX ? join 1 Uoin,? empty) .
' .
mkValid (xs, y's) . ((2], [1 ])
= if null xs'then MkQ ( re~er.~e ys, []).else.MkQ (xs, ys} ... "

' .
? join l Uoin 2 empty)=
. .=joii1
.... 2 {join 1 empty)
This module contains the second impleme ntation of queues describe~ ln the False
preViOUS section. ~Ot~' that Queue IX is implemented by a newtype declru.ation
rather than as a type synonym for pairs of lists. The reason for this is explaine d H was npt our intention to provide an equality test on queues, but sinc;e (==}
' .
below.
. is definedo n {(IX]. (ex]) whenever it is defined on c<, we neverthe less have one.
.
'
~. . . .
The first line of the declaration introduc es a module called Queu_e. - Modu)!! Similarly; su1ce ((<X], (1Xj},is aninstan ce of Show whenever IX is, we canreveal
!!ames begin with upper-case-letters . The deciarati on also contallis an export -how queues are represen ted. lpnoduclng Queue IX by a newtype d eclaration
list consistin g of the name of the abstract datatype (also called Queue), together means that new class instances can be declared for Queue q, and that old class
with itsope~atioris. No other types and values declared in. the modUJ.~ may be instance s defined for the ~,nd!!.rlying type no longer ap ply. hi this way, tli.e
used elsewhere. ill particular, the construc tor MkQ is not exported, so valu~s of abstraction barriers
. can, be..maintain
. ; ed without. sacrificing effiCiency.
type Queue IX cannot be created ln sc1ipts that make use of the dataryPe, except .....
with the help of the (ive named operations. In other words;th e impleme ntatio~ E.-x:ercise s
..
'

of Queue ex described in tl1e module is hidden in any sci:ipt that makes use of
. the module. 8.2.1 Prove that {ro rnQueue
.
... toQueue
. is the iden tity fwtctio~ on fini te lists. . ,.
.
.. .. ..
. .. .
. ~' j!
' .. ' ' ' .
j ,;
' ' " . .. . ..... ' ' I ',
'.
I.,:
.. I .
b,
.. .... .. ...
264 8 I Abstract a~catypes
.: -: . _: ~~:. ~j~' .; ~4 .$.3 1 sees 265
. . :
B.l Sets .. ..
... . ' .' '

-
-..
' ',
' '

.
union xs empty xs
The primary example_of an abstra~~_cl<~tatype is ~he qata-~e-' of. ~ets:set~ ar e
~

uni~n xs (insert y ys) . - insert y (union xs ys}


( t . ' .''-1
ubiquitous in mathematics md are also useful j.n many progrCUIJining tasks. :~..
Sets can be rcl?re~~ted by lis t s, lists yvith no duplicates, 6rd~r~tHi~1s.:: trees, meet xs empty = empty
boolean func tions,- and so or.. Different repr esentations eire appr opriatein ctif- . meet xs (insert y ys)
ferent circumstances, depenjing on the precise repertoire o{opflfiitions to be .
= if member xs y then inse~t y (meet xs ys) else. meet xs ys
provided and theii requi,rea :!ffidency. ' . ... . . . . ' ' . . .. .
There are.nu_J?~I'ous operations on sets, including the following: . . .
,. 'I ' : , , ,, ~ :. mimts xs empty - xs ;:'1

empty :: Set 01 minus xs (insert y ys) = minus (delecey xs) ys : "


. isEmpty .. Set 01 - Boo/
member .... Set 01 - r:x - Boo/ We will al ~o assume, as for qu eues, that all operations are srrict, so only finite
insert .... 01 - Set DC - Set X
sets can be consrructe.d.
(lelete . .. 01 - Set :x - Sec 01 ' . The first two axioms are .differe~t in ~ature from the others. The first one
states that inserting an element twice in' a set is ~he same as inserting it qnce .
.. ..'
..r,,
union .... Set X .,... Se~ r:x -. Ser 01.
'
The second equation states that it doesn't ma.trer in which oider two elements '.. ..
meet Set X - Se: r:x - Set 01 areinserted into a set. Althoughevery set can be expressed in terms of empty.
..
minus .. Set 01 .:.. Se r:x - Set 01 ' . and insert alone, such expressions are not unique. In other words, there are'no
. - canonjcal forms for sets. ..
. .
.These_eight operations may n ot all be wanted in a particular_ap~-lica.ri'on. A Two crudal operations are isEmpty and member; without them there would
type based 'o~ .the fi,rst five o perations is often called a dicrionary. O.ictionaries be no way O tell two sets apart. Unlike queues, there is no operation for extract
are.useful as a: ~eneral devic~ f or ma intaining a lis t of tasks to l?e performed. ing an element fro~ a s~ t. It is simply _n ot possible, without. further assump .-
Tasks c.<in be done iQ any order and have to be done only once. New tasl<s are tions on the type of the elements of a s er, to specify a function that returns an ~

created one by one and addd to the list; tasks are ticked off wh.err. they have element _of~ set ~'he el~ment dmnot: b.~ : ~h9sen arbiti;uily; becatts'e functfons .
been completed. rctu~n the same result given the same ~gllJ?ent. For example, the defillition
The algebraic spec~catim of Set. 01 can be forrnu jated as tli~ :r61~;~g list
of rudoms: . choose Set 01 - 01
cJ~oose (insert x xs) = x
inse'rc X (insert X xs) "' insert ''x-xs
...
insert x (insert y xs) = insert )i' (insert x xs) :.does not work because it l eads to an inconsistency:
,,
.. . ; ,' '
. ....
'
is Empty empty
' '
... .. '

= True " ~

choose (insert x (insert y xs) ) = x


.. .,, " ::: ..:.
.-
isEmpty (insert x xs) = False Choose (insert X (insert y xs))_ = choose (insert y (inse:t X XS)) = y
. . ..... . . .... :
member empty y - False . . . On the orher hand,' if lX is:i-estri<;ted to instances of the type class Ord, we could
member (insert x xs) y = (X = y) v member xs y' ' ' " always extract the minimum (or ma'<imurn) clement of a tl nite.nonempty set
'
. For a 'differem reason, it is not possible to implement metnber unless Set e<
: ... is restricted to those types lX that are 'instances of the type 'class Eq: In order
delete x el!lpty = empty
delete x (insert y xs) to determine whether a value is in a ~et, we have to be. abl~ to compare it with
- if ~ . = y then del~te x xs else inserc y (delete x xs) the elen1ents of the set I.t1 parrict.i.lar, it 'is not possible to 'imptcm'ent sets of .
.. funcrion~ and be i.lble to tell two nonempty sets apart
, ' . . ::.
. .
.....
.
~

.. ' ..
266 . '. . 8 I Abstract-dacatypes 8..3./ Sets .. 267
. '
. - .' ... . .. ~ .
" ~~ ,;' ~ _. ~

n (n ) steps. Since n ca!l J:)~ _arbitrarily larger than N, the operations.cann_o t be


~
2
8.3.1 Representation by lists ,,
'
guaranteed to be executable within any prescribed time bound. I;
;,
Assum.it).g a is an instance of Eq, we can represent sets by lists. The abstraction To be more precise still,_we should conside~ amot:tised costs. It is not too ~
func tion in this case is difficult to show that the _worst-c~e cost of demanding information: say by a I
' . member test, from a set .bull~ by n dictionary op erations is e(n 2 ) steps, so the I
abstr [ o:] - Set a
abstr - {oldr insert en_!ply
amortised cost of. the dictionary,operations is 0(n). , I
A better represeiuatiori is to adopt the second definition of valid and restrict
There are two reasonable definitions of valid represen tations: the lists to have distinct elements. Under this represcp.tatjon, the operations jl
insert CJ?d unioi1 are iillplemented as follows: . ,.
.. valid xs. = True
valid xs = nonduplicated xs insert x .-xs - x : filter (* x) xs
union xs ys = .xs +l filter (not. member xs) ys
With the first definition, all lists are allo.wed as valid representations of sets. In
such a case, we can implement the set operations quit~ simply. For example, Under this representation the length of the representing list and the size of the
. . . . . .' '.. . :!
. . ...' .. represented set are the same. Ho.:Vever, the tiine for insert increases to 0(N),
me.mber xs .'<. - ' some (.== x) xs .. ' ~ .. . .' where 'N is the size Of.thf' set, and the time for union is h(to,f2 ) h1 th~ WOl'St
insert x.xs = '< :xs
' 'I
.,
case. The aptortised cost qf the dictionary operations is 0(N) steps. .j
- filter (* x) xs
I
delete x xs To improve on the above representations we. need to assi.une that e< is an
union x:{ys - xs * ys
,

instance of the typeclass Ord. Recall that Ord is a subclass of Eq. Then we l:
minus .'<.S ys = filter (not member ys) xs can represent sets by Hsts in increasu1g order. The datatype invariant "'a /id
.
!
in this case is that valid holds for a list only if the elements of the list are !.
Tlie function some is defined by i'
in strictly increasing order. Under this representation, we can improve the

'

implernenta tion of member: _to.ieaQ.


some (a - Boo/)- [o:] - Boo/ '. 1:
some p - or .map p ... .j!
.
member xsx = if null ys then False else (x == head ys) .ji
;I
Like.the companion fimction all p = and map p, the function somep is a useful "~pere ys =dropWhile ( < x) xs
..;.., ti
,_, . pr~gradmung idiom .. No.tice, in passing, how t_h e type assigned to member is ~I
~
Though still D(N) iri the worst case, the search for x in xs is mad e more efficient
.expioited iri the de(\nition of minus. In the definition of i:he curried .function . :I~
member there is a choice as to wh,ich argument should come first, the set or the by not looking past the first y for wllich y ~ x. .,.'
element. It is moreconvenient to put the set first. In fa~t. the type sig~ature . Here is the implementation of union under this new representation: ...'!
.j,'I
member :: Se! a - (o: - Boo/) union [] ys = ys ,.1:
I
.. union (x: xs) [] :. . X!
. XS 'I
e~prcsses Oiie halt of a. corrl!sporidence betvveen sets andboolean-vali.ted func I
(y: ys) .
. '
tioris. . . tinion (x: xs) ',1
There nr.e some -advantages of tllis simple representation, but the disad 'i
(x<y) = ., x;_unionxs(y:ys)
vantages are greate~: The n-iajor advantage is that insert is a c~nstant-tim~. ~
operation. The problem, though, is that the length of the representing list can . (X == y) =: x: union xs ys , .
be mudilarger than the size of the represented set; so the implementations of (x > y) = y ::union (x : xs) ys ,.I
I

the other operntions 'are lnefqcient. To be more precise, suppose that xi and ys .. ' '
i'
b oth have length~ and both represent sets of size N. Then, in the worst case,. The function union is.like merge except that duplicated elements are removed.
evaluation of delete.x xs takes D(n) steps and evaluation of minus xs ys The implementation
.. . of minus and meet
. are similar and are left as exercises.
. . takes '
...
..

..
I
... ; . .
268 .. B./ Absiracrdararypes 8.3 I Sets . 269'
. . . :. . . . : .: r ..... . . . . :
... . ~ ~J !"~: . . .: , - ..
The ad van tag~ of rh~ new represef:ltation is that the run.r14tg ti.m es for l.!nion, . delete;: ( Ord ex) ~ ex - Stree a - Scree a
... . ... . . :

me.et, and ~inus !iJ:OP t~ S(N) step$. On the other hand, thelil!iiP.ng: times of . delete x Null = Null
the dictionary operations member, insert, and d~lete are O(N) in the worst case.. delete x (Fork xt y zt)
In the remainder of the sectioQ w~ will shOYi how the dict~onarY. 9P.~ra~ons C<lJl . (X< y) - Fork (de?ete x xt) y zt-
be implemented mor~ effidently by moving t~ trees. (x== y) - join xt zc
.. . ..
. -
(x > y) = Fork . xc y(delete
. x zt)
8.3.2 Representation by trees ..
. join Stree ex - Scree C< - Stree ex
. .We have already.suggcsted in Section 6..2 how binary sear~h r:rees .c~p. _Fe used
join xt yt - if isE17!pry yc .Pen xt else Fork xt y zt
to represent se.ts. Here are the relevant defuiltioris again, thi~ time organised ..

where (y, zt) = splitTree yt


as a module:
' . ' .
module Set (Set, empry, isEmpry, ~nember, insert, delete) where sp/itTree ::$tree ex- (C<, Stree oc)
' I

data' Stree e< = Null I Fork (Stree a) tx. (Stree a) splitTree (Fork xt y zt)
= if isEmpry xt then (y, zr) else (u, Fork vt y zt)
ernpry .. Set e< .
' t I ' ' ' ..,..

., .. where (u, vt) "' splitTree xc . .


empty "', Null
It is left as an exercise to provide the functions abstr and valid, a~d so formalise
isEmpcy .. the representation of sets by binary search trees.
lsEmp.ry Null = True Two extra functions, join and splitTree, are defined in this module but they
isEmply (fork xt y z t) = False are not listed among the exports in the module header, so they cannot be used
in scriJ?ts that import the module Siu. Note carefully that join will not serve .
mcmtber :: (Ord e<) ~ Stree oc-.e< ~ Bool .. as an implementation of the functiqn union on sets. The value of join xt yc is
defined under the assumption that every ~lement in xt is smaller- than every
elenu!nt in yt. .In' fact, this representation of sets by trees is not particularly
member Null.x ==False
. ....
-
member (Fork xt y zt) X useful if one wants to implement nondictionary operations efl;idently.
- memberxt x .. . . .
(X< y)
.. Th~ execution time of the operations member, insert, and delete depends
.. (X=~ y) = True . on the height of the tree representing the set. In the worst case, each operation
, (x > y) :: member zc x . rakes 8(height r) steps, where

. . inserc :; (Orde<) ~ e< - Stree a ~ Stree a height , .Stree ex - Int


insert x'Null = Fork Null x Null ' height Nu'II = 0
insert x (Fo,rk xt y zt) height (Fork xt y zt) - 1 + (height >o:t max heigf1t zt)
.(x < y) - Fork (in.sert x xt) y zt '
Recall that a tree of size n has a height h satisfying
(x == y.) = Fork xt y zt
( x > y) = Fork xt y (insert x zt) flog(n + lll .s h < n + 1
.. ' \

Since a set of size n may be represenre.d by a tree of height n, the dictionary .


. . operations take ,.{)(n) steps in the worst case. On 'tlie other han.d, a set of size n
may be represented by' a tree of height log(n + 1), so the dictionary operations
. . . -. take O(log n) in the best case. The way to bring these two bounds .
too-ether
0
is
.... .
... .
..
' \~
272 _8 I A.bstracc d_atarypes 8.3 I Sets,_ 273
...
.. .
J'

..
. .. . . . ...; ~ ~~:.. -
:-

between the_ l~gest V~h~~ in X( and .the smallest value, ip zt: 'then.fprk,Xt y Zl
" . : ' "' " - .

. , . course, if xt- and 'zt differ in height by at most 1, then we canimplement spoon
builds a bin.ary ~ear<;h tree ..However, the result will orily be a balanced -tree if as a fork.
xt and zt are ~oth balanced and differ ip height by at most l. . . Sillce xc has positive height, it is.not the empty tree, so suppose that
.
In order to ensure that only balanced trees are built, we \vill ne'ed a.~.ariant .. .
of fork which, for the sake ofa name, we \vill call spoon. Its typ~ is thesa'me as
that of fork:
xt = Fork n ut v wt
~ __:... - ,.
' The value of spoon depends on the relative heightsof ut and wt. There are two
- . .. ..,..;,;... :

...,: : cas~s. Firstly, suppose hi ~vt 's.' ht so cill of tlie' followillg ;elationshlps hold:
spoon AStree a - . ()( - AStree oc ~ AStree a
-;
ut,
. .
ht zt = ht xt - 2 = ht ut - 1 s ht wt ::;; ht ut
;

Apart from.uslng spoon instead of Fork; the new definitions.of inseft'aM de'iece
. - .
<;U"e exactly the same as before: .
.. ' ' '
In this case we can define
insert :: ( Ord a) ~ a - AStree ()( - AStree a
'
. ..
insert x Null = fork Null x Null spoon xt y zc = rotr (fork xt y zc)
insert x (Fork h xc y zt) where rotr rotates a tree to the right:
.. .
. ; .
!'

X <.y) . : = SpOOn (insert X ,'(t) y zt) ~

.. . ' .
rotr ' .
AStree ci .:.. AStree C<
(x .~ y) - fork h x't y zt !
~.

'.
. (x > y) - spoon xt y (insert x 'zt))
,
rocr (Fork m(Fork n uc v wl) y zt) = fork ut v (fork wt y zt)
To check that this is correct, we reason
'delete::.. (Ord a) ~ cx - AStree C< - A.Stree cx
delete. x Null. = Null
'
abs (ht ut- ht (fork wt y zt))
dele.t,e x (Fqrk h xt y zt)
{definition of height}
: (x <: y) = spoon (delete x xt) y zt)
'
nbs (ht ut -1- (ht wt max he zt))
. . (x == y) - joinxt zc
.' '<x > y) = spoon ;-.;t y (del~t~ x zt) ). = (sin<:e ht l:t :i;; ht w t}
' :
abs (ht ut - ~ - . ht wt)
join . : AStree ()( - AScree a - AStree a ' . -
join xt yt - if isEmpty yt then xt else spoon xt y zt - ' ;. ::;; . {since l1t ut - 1 ::;; frt ~t ::;; ht utl
where (y,zt) = splirTreeyt 1

In the second case, suppose he wt = 1+ he ut. In this case, we cannot be the


splitTree .. AStree cx - . (a, AStree a) .
empty tree, so suppose wt =Fork p rt s rc. In,this case. xt .takes ~he
. ' '
' '
form
'

splicf.r~~ (Fork h ~t y zt) .


- if isEmpcy xt then (y, zt) else (ll, spoon vt y zt) xt = fork n uc v wt .where wt = Fork p rt s It .
.,

where (u, vc) = splitTreexi


Furthermore, all of the following relationships hold:
--.
It remains to i.r:nplerncnt spoon. Since a single insertion or deletion. can alter
the height ofany subtree of a tree by at most l, it is sufficien t ro irilpi~ment flt Z( = ht xt - 2 = .ht ut. = ht .wt-
' 1 = ( ht yt. max ht lC) '
~

spoon xt y zc under the assumprion that xt and zt are both balanced-binary


In this case we can define
search trees whose heights can diffcr by at most 2. We will discttss only the .,
case ht xt = ht.zt + 2; the o~hcr irireresting case, he zr = ht ~t + 2, i$ d.u~. And of spoon xt y zt = rotr (fork (rorl xr) y zt)
. ..,,, .. ... ;. ..
'
... . .... .
. ... _.._
' '
;
'
274
. . . ..
.. . 8/ Abstract dacacypes 8.3/ Sers . ! . 275
. .
where rot( rorates. a tree to the left . Evaluation of spoqn. t*~s r,o)lstan't time, as one can easily check-by inspection.
To-s ummarise: usitig a baianced binary s earch tree one can implement the
roc/ .. ASrree a - AStree a !

dictionary operations so that member, insert, and delete ead1 take O(log n)
rot/ (Fork nut v. (Fork p rt' s tc) ) - fork (fork ut v r:t) s !t .. steps, where n. is. the. size
. .... of theset.
. - .
To check that this is correct, note that J ' ~- ; I .' '

spoon xt y zt =
. .
fork (fork ut v rt) s (fork tty zt)
Exercises ._. .
.

8.3.1 Implement meet and minus, asswning sets are represented by lists in
so we can argue strictly increasing order. . . ,.
abs ( ht (fork ut v rt) - hr (fork
..
t't y zl)) by.
8.3.2 .Sets can.b e represented. boolean-valued fwtc;tions. What is the abstrac
tion function in this case'? Ali of the set operations described in the text, except
{definltion of height}
one, can be implemented quite easily under this representation. Give details,
. abs((hlutmaxhrrl')-(htttmax htzt)) and isolate the difficult one.
= {since ht tl ~ hc zt} A set can also be represente~ by a pair. of values, n boolean-valued function,
and an integer that represents the size of. the-set. Show that the troubl~some
'!

a,bs ( ( ht ut ~a.X ht r.t) - ht zl')


operation ls easy to fmplenient under the new representation. Does this cause
{since ht rt s. ht ut} ,.
difficulties \o~ith any of the other operations?
abs (hi' ut - he zt) 8.3.3 Formalise the representation of sets by binary search trees by. providing
{since ht ut = 'he zt} definitions of abstr and valid.
8.3.4 lnscrt the letters of EQUATlON into .an initially empty treE! and draw the
0
result. Do this for binary sear~:h trees and balanced binary search trees.
The comple~e defini tion of spoon is as. follo~s: 8.3.5 Suppose we want' to represent sets by binary seard 1 trees, but also want
to implement union xs ys \o\'i.th"ri time complexity O(m + n), where m and n are
spoon xt'y zt
the sizes of ~. and ys. _Show how this can be done.
(hz + 1 < 11:<) A (bias xt < 0) - rotr (fork ( rot/ xr) y it)
(hz+ l< hx) - rotr ( fork_-xr y zt )' 8.3.6 Recall that S(h)-.d~J1Qte~ thesiz e of the._srp_allest b~anced ~ree ~th !1eight
(hx + 1 ~ hz) A (0 < bias zi) - rot/ (fork xt y ( rotr zt))
h, and H ( n) denotes th~ _height of the tallest tree witl1 size n. Both S and H are
monotoruc functions ;.\.ith h :s; H(~(h)) and S(H(n)) ~ n. Use these fac~s to
(hx + 1 < hz)
otherwise
-
-
rotl (fork xt'y zt)
{orkxt y zt
prove S(h) :s; n =
h .s H(n). [The functions Sand R exemplify \vhat is known
as a Galois correspondence.]
where ii'x = ht xi; hz = ht zt .
0 1
8.3.7 Why does at mos,t-~ori:~ lTee require rebalancing after an insert operation
bias into a balanced biriar.'Y ~earch tre'e?'
. ::AStree .ex - Int .
bias (Fork h xt y zt) = ht xr - ht zt 8.3.8 How many'binary 'trees of size 3 are ther~ and what is the average height?
. . , .. ! .. Now suppose a b.inary se.a rch .tree is built by inserting some permutation of ABC
rotr :: AStree ex - AStree ex . into ru,1 initially empty tree. How many different trees are possible and what is
rotr (Fork m (Fork ~ ut \<wl') y zt) the a'(erag~ height'? What' 1f t~e insertions are -balanced tree ~se rtions?
- fork . yzt)
ut v (fork. wt
...
a
8.3.9 Draw up table, labelling the rows with the variousset operations, and
rot/ :: AStree cx - AStree C( /
the columns with the Various .set representations. Using_Onotation, fill in the
rot! (Fork m ut v (Fork n r(s tt)) - fork . ut v ,.
(fork rt) s tt. table.with times taken by each operation under each representation.
. ... ... . .... .
'' .'' .. 'I I I,.: :. ! '

276 . B1 Abstract cJaratypes 8.4 I Bags. 277


.,..,
.... ::- .:r ...... ;...
: . , t' , , ; .:, ,

..
~

. . .. . . ~-.
... . . .. .
8.4 Bags . .. .. . !_ ,, axioms are " ...
. ~ . : ..' ......
Bags, unlike sets, are more commonly found in computing than in ma thematics, insert x (insert y xb) - insert y (insert x xb)
whe~e they are_usually citlled _multisets. A bag is like a set in thaube oFder of mk.Bag = {oldr insert empty
its cl~ments is immaterial, and like a list in that duplicate elemen"is:.mattcr. For union xb empty - xb
example, .- union xb (insert y yb) - insert y (union xb yb)
- - x
, I '" ":,

. . -minBag (insert x empty)


= {[3,2, 1, 2)} * {[1, 2, 3]} .
{[1, 2, 2,3 )} and {[ 1, 2, 2, 3]} . minBag
. . y xb))
(insert x (insert - x min minBag (insert y xb)
. .. . .
Suppose we want' an abstract data type Bag ()(, restricted to...th~~-; ()( that are The axioms for de/Min are left as an exercise. The hidden functions are not
instances of Ord, on which the follo\ving operarions are defined: .... .. provided as operatio~s on bags, but.serve only to aid the specification. The first
equation for insert says that il does not matter in which order two elements are
mk.Ba!? ::' ['()(] - Bag()( added to a bag; unlike the corresponding operation for sets, adding the same
isEmpty :: Bag()( - Boo/ elen1ent .twice to a bagis different from adding it once.
.. Bag
ix - Bag ()("- Bag ()( .. .. :
.. The 1:\-vo operations empty and i.nsert migl~r :well have been pt;ovided as prim
and
union
. '..
Hive operations on bags. In fact, tdge~het\vit~r minBag de/Min, th~y consti
"
- ...
min Bag Bag ()( ...:. ()(
tute a useful data type known as .a prld'rity 'queue. Elements joining a priority
de/Min .. Bag Of - Bag ix
queue possess a certain priorityrating. Queue elements ar~processed inorder
The function mk.Bag converts a finite list into a bag of its elements, isEmpty of priority. Thus, minBag replaces front and de/Min replaces back. .
determ.i.n~swhecher a bag is empty, and union takes the bag union of two bags.
It is easy to implement bags bynondecreasing lists, rather like we did for
For example, sets in the previous section. This time, the W'liqn operation is exactly like merge
. . since duplicates are not removed. The rnk.Bag operation is implemented by sort.
union {[1,2,2, 3]} {[2,4]} = ff1,2,2,2,3,4]} Under tbis representation, the runnin~ times_for rhe various operations in the
worst case are as follows:
"'":~-- : :.:-.) . . ~<': ._;_.,, ~. ' .:~...: . . . ""~i~:/tr.~::.1 .-.-;,:;- t~
The func~io11: minBag returns the sma!Jest element in .a !lO~~mpty b~g. and
: .' J. - .

mkBag xs takes 6(n log n) steps


~e./Min deletes one occurrence of the smallest element: These ~ast tw<J opera
isEmpcy xb takes 6( 1) steps
tions are meaningful only if bags are restricted to types at" are instances of
Ord. union xb yb takes 8(m + steps n)
. minBag xb takes 6 (1) steps
Let us now give an algebraic specification of Bag ()(. One possibility is _the
following list of axioms: de/Min xb takes 6(1) steps
..
In the first line: n = length xs, and in the third line, m and n are the sizes of the
.is Empty. ( mk.Bag xs) null xs
.. = ' . two bags xb and yb. .
w-iiori (mkBag xs) (mk.Bag ys) - mkBag (.xS * 'ys) In the remainder of the section we are going to implement the bag operations
minBag (mkBag xs) - min list xs so that they will have the following time complexities in the worst case:
de/i\1/in ('mkBag xs) - mkBag (deleteMin xs). .
' . mk.Bag xs takes 6(n) steps
The function qeleteMin deletes one occurrence of the sm.alii!st .elet:P~~t of a isEmpty xb takes 6(1) steps
nonempty ijst; its definition is left as an exercise. . ... ' union xb yb takes El(log m +log n) steps
Another way to specify Bag()( is to introduce two hidden constmctors, empty minBag xb takes 6(1') steps
. . .Jn
. define the other operations in terms of them
and insert, and . . this . , the
. .case
- :de/Min xb takes 6(log n) steps

-
. ' ~ ... . .. ' ..
. . ..
.. ..
..,
:; .... . :.;_ , '
278 '.
'. .. .
. 8 /.Abstract data types' . ...,; ' . ,; . .' .279
.
' 't' , : . :
.. ..
-... ,. :. . ' . :.:.- -; . ..... " - ' ... . - : .

The time for IJ1kBag drops by a logarithmic factor, ~hile the time' for deli\rfin : . de/Min . _. .. Hlree 0< - Htree 0<
increas~s-by a log~itlunic factor. The big payoff, though, is with union.wl~ose de/Min (Fork n x. yt zt} = union yt zl
tunqing
.
time ~s decreased from linear to ~-
logarithmic.
. .. ~ . union -.. - -' :: Htr~eex - -Htree ex - 'Hiree.a . .
' .
8A.l implementation by heaps union Null pt . .. . . ... = yt . ... -~

' '

union (Fork m u vt wt) Null = Fork m u vt wt


. , The impletitentation of bags is by leftist size:augineri\ed:binary h~ap trees. Bin-
ary heap .trees we..:e defined in Section 6.3, and the size-augmented version is union (Fork m u vt )vt) (Fork n xyt tt) .. . .
declared by .
. . ~ < x. ~. fork uyc (imi'on we (fork n .x yt zl))
-.
' .
. . :':.

data Htree ex - Null I Forklnt 0< (}itree ex) (Hrree O<) x<u .= fork x yt ,(union (Fork m u vt wt) zt)
.. ..
.A leftist tree has the property that the size of each left subtree is at least as The union operation is implemented by merging two heaps along their l'ight .
large as the size of tpe cor.responding right subtree.. We will construct such spines; this is the path in the heap from the topmos~ node .to t~7 . rightmost
trees witJ~ the help of a function fork, defined by. ' Null. T he cost of evaluating union is. clearly proportwnal _to the sum of tl:e
. . ~ .iength~ of the right spil).~s...o(.the two heaps, so the next task is to. ~s~ima~e this
fork Htree 0< - Htree 0< :: 0< - quantity. Define Irs (length of. right spine) by ,.
fork ; yt'zt - ..if m < ~ theQ F.OI:f<. .. .x {!t p yt else Fork p x y!' zc. Htree 0< - lnt
where m. = size yt .
.' Irs. . .. . .. ..
Irs Nul,l - 0 '
: n - size zt .
p - m+n+l
Irs (Fork n x yt zi) -. = 1 +Irs zt
-~ .

t
. !
,. a
The claim is that if ,~Hs leftist tre: ~f size n, then Irs xt :$ Llog(n+,l) J.
.. , si,Ze . .. Htree 0< - lnt ...
,
., \
size Null - o
. size (Fork n x.yt zt) - n
. -
The function' fork takes a label and two heaps and build~a Fqrk by installing the frs (.Fork n X y(zt)
necessary size information and s~vapping th~ order o~ ~he t\~o heaps if necess
ary to ensure that the left one is the larger of the two. .It isleft asan exercise to (definition of Irs}
define the functions ~bstr and valid that formalise the r~pn!seJltation of bags 1 +Irs it .
by leftist hea{1s. , . ,
- .. . {induction hypothesis} ,., ...
.. leavjilg f!S'ide mkBag f~r the moment, the other h~ap oper~tions are imple
', . ' .
: . ~

n:ente!i a.~ fo~ows: :; 1+ ll~g(q +l)j


.. ' {arithmetic}'
isEmpty Hlree ri - Boo/
.
isEmpt)INull = True . . Llrig(Zq +.2)J':_
isE'!'pty (Fork n x.yt zt) - False {since.n =p + q + 1 ~ 2q + II .

Llog(n + l)J
.
'
minBag , .. Hlree 0< - ex ; ..
minBag . . .n x. yt zt)
. .(Fork . - x ~ \ . :.. " - ': .. D

- . . . '. - . .'

' . . .
' ,
""
..;- ~., ... ~ .
...
280
_._.. BI ~bstfacr di!tarypes i
.8.5. ' Flexible arrays 281

...
- joo

:-. . .. . . ; -: !-.' ... . ..


It follows from this result that t})e.function, unfon bas the required time.com-
plexity. Since delMin involves a single call of 11nion, this function wo has the
. s:s FleXible arrays '
' ,
.
' .., .. ' ;

'
.

required time complexity.


We have seen how trees of'various kinds can be. used to i.mpl~ment sets and
It remai11s to implement mkBag. We use ~he tupling tecluqu.e from Sec
ba.gs efticiently, now we wi)l see how they can be used t9 .implement a datatype
tion 7.4:
-. .- - . called flexible airays. The type Flex a has the follovruig operations: .
-.
.... Flex a
mk.Bag :: [a) - Htree a
mk.Bagxs - {st. (mkTwo (length empty
.. . .
xs) xs) .
isEmpty .... .'Flex ex - Bool
.,, ..
, access .... Flex a - Int - a .
mkTwo ::Inc - [a]- (Htree ex, [a]) .... Flex a - Int - ex - Flex a
update
mkTwo nxs
hiext .... ex - Flex a - Flex a
( n == O) - (Null, xs)
hirem .... F{ex ex - Flex ex
(n == l) - (fork (head-xs) Null Null, tail xs) loext .... c( - Flex a - Flex a
otherwise - (union xt yt, zs) lorem .... Flex ex - Flex a
where (xt, ys) = mkTwo m xs ' '.
(yt,zs) - mkTwo(n-m )ys flexible arrays are a species of tlnire list in which one can access and change
m - ndiv2 clements identified by their position in the list, but one can add arid remove
elements only from the two ends of the list. The names hiext and hirem are
As we nave seen in Section 7.4, this implementation of mk.Bag takes linear time short for lligll-extend and bigh-remoye. Similarly, loext ~d lorem are short for
in the length of the list. low-extend and low-remove. Array indexing begins at 0, so adding an element
at the low end means that the positionsof the preVious elements illcrease by l.
Exerdse 8.5.6 d~als .with a variant da~atype in which two additional quantities,
Exercises the lmvet anct upper ,bounds, are.include.d for a more gerieral'indexing scheme.
. .. ... . ...
'~ =-~.,..~\,~ ,,~ ..
A formal specific'atiori of Flex a can be based on'the three constructor func-
8.4.1 Ruild heaps fo"r the letters in HEUO and WORLD and draw the heap of 'tions empty, hiext, and loexc. The first axiom states that
their union_

8.4.2 D~fine deleteMin :: (Ord a) - [a) - [c~] . hiext x loext y = loext y hiexc x
.
/
8.4,3 Give the axioms for de.Uv!in in terms of insert and empty. .Although 'each array can be expressed in terms of the constructors, such ex-
' . pressions are not tiniqt'le. However, by applying the. axiom above, every qrray
S.4.4 what is the adyantage of providing an operation mkBag \vbenit can'easily .
can be named by a unique.expression in which all occurrences of /oext precede'
be defined as {oldr insert empty? .. . ': . 'any occurrences of hiext. The rcmammg operations are ~haiacterised in terms
of the constructors. For 'example,
8.4.5 Install Bag a as an abstract type by giving an appropriate r~todule dec-
laration. .... .
. hirem empty = error . '

8.4.6 Why make n == 1 a special case in the definition of mkBagT . .hirem. (hiext x x{) - xr .
' '

. . .. ',
'

hire/'?1 (loext x empry) . empty


8.4.7 Write a function sortBag :: (Ord a} Bag a- [a]: This func.tion should
=>
hirem (loext x ( hiext y x{)} = loexr x_' x{ .. : ..
use only the specificdoperalions on bags. .. hirem (loext x (loext y'x{)) - loext x ( hirem(loexi y x{))
..
... ..,
.. .
.
'

. ..
282 .8 l Abstr~c( datacypes 8:5.; Flexible arrays . . >
283
.. . . ~ . : . .;.. . . .... ..'; .:.: . _,., .~ . '
' .. - sum of the sizes of xt aQd yt. That means we can~efi.ne sfie by
access empty k - error."subscript out of range"
access (loext x xf) 0 .. : . ... . .
- X
access( loe?Xt x xf) (k + 1 ) - size .::: Flex lX - Tnt
a_ccess xf k
size Nult -- - -:. ::= .: ()
size (Lea(x,l - : =: ::) :
-access (fliext x xf) k
size (Fork .nxr yt}: :::- ~:n
k< h = access x{ k
'. ._. . :._.. ~_.,;.

k n = x :
The second constraint on Flex 0< is that we will only build leaf trees. A leaf tree
k> n' -
.. . ' error is either the empty'tfee Null'~r a nonempty tree\n whichrhe empty treedoes
where n = length xf not occur as a subtree. .This ondition is formalised by
..
The last axiom for access dependson a hidden function length, defined by isLea{Tree :: Flex lX - Boo/
isLea{Tree xt = _ isEmpty xt v Is Leafy xt
length -.. Flex lX -Int ' .- . . ..
..
' . length.empry = o '
. .' :., '

..
length (hiext x xf) = length x{ + 1
= False
isLeafy Null ' :::
~ length ( loe?Xt x xf) length xf + r
I ' ' '
. isl~ea{y (Leaf x) = True
The definition of lorem is dual tQ that of hirem, and update is similar to access. . isLeafr. (Fork n xt yt) - is~ea{y xt A isLea{y yt
The specifications of these fi.mctioris, together wlth isEmpty, ar~ left as exer- .'
-
.cises. . - ..
isEmpty .... Flex 0< - Boo/
-If flexible arrays are implemented as lists, -the operations access, update,
hire~. and lorem 'will take <3(n) steps in the YfOrst case, where n is the size
isEmpty Null - True
isEmpty (Leaf x ) ... . - False
p f_the ~rray. The other openitibns take constant tiine. The amortised cost of
~he array _operations is also 9 ( n )_steps, In the remainde~; of the section we will isEmpty (Fork n xt yt). - False
describe a s~plc implementation, designed by v: Dielissen and A. Kaldewaij,
.,

which guarant~cs that all' op erations can be performe~.in O(log n) steps. ill conformity with Section 6.1 we will define the height of a leaf tree by -
. .
.
height .. Flex ex - lnt
8.5.1 Implementation
. . . height Null .- 0
.: '
heigh! (Lea{ x) . - 0
The implemt!ntatlon l~ w use quasi-perfect size:a~gn}emed binarY trees. we
a'
.. will postpone explaining wh~t quasi-perfect tree fs until
we' have descripcd "height (FOrk nxt yt) . ,;, 1 + (11eighc xt max height yl)
some of the basic operation's. 'rli.c type Flex~ is declared hy .
A leaf tree of size n has height at least rJog nl- Tl~e thiJ.d constraint, considered
below, .is that we \\ill orily bt\ild quasi-perfect trees. . . ,
data Fie-'< 0< = Null l Leaf 0< 1 Fork1nt,(Fiex O<) (Flex ex)
.' t '
... ' . ,
The static array operations -: those that do n<;>t exten(l or contract the array
The ty.pe Flex 0< is.a:.variant of binw.y trees, with dn;added constructor Null and -are implemented a.sin.~I!Ction 6.1:
.' size information in the fork nodes. ., '
empty Flex lX .
.. The datatype invariant on elements of Flex 0< consists of three conditions.
. The Orst CO{\ditioQ.is. tl?a~ ~e .will only bui!d a tree Fork~ xt_yt in which n is the empty = Nul,/
- ..

. ..
~ ...~:...
284 8 ;i.'b"soa_cc da.catypes . . 8.5/ Flexible arrays ?85
' o r~ "-': - ~ . .
' . . ' . ::~.. ~ - :, :~::-.:~ ...
. access
. '
.:: Flex. ex .- . Int
. - ix in w}Jich the size of the.left subtree of t'!ach :qode is at least as large:as the.size
.. '-.., .
~

access (Leaf x) 0 =- x .. . . o.f tbe corresponding right subtree. There is exactly one leftist left-perfect tree
access (Fork n xc yt) k (an llp-rree for short) ofany given size; moreover, it has the mininimn possible
;> :-;: . height. The proof is m1 induction argument. In the inductive case, suppose xt
4 ~ . . .

- .i (k < m then accessxt k else access yt (k- m) .::


. where m =- sizext ..... .:~.." - is a lip-tree of size n, where n ~ 2. The left subtree of xt is perfect.and has size
. .......... 2k for some k, and the right subtree has size m > 0, where
.- ' . .. '

update ::Flex ex - Int - ex - Flex ex m ~ .2k and n = 2k + ~ ''


updqte (Leafy) 0 x =- Leaf x
update (Fork n xt yt} k x ' IIence 2k < ~ < 2k+l. The left subtree of ~t .therefore, has a size that is the
k <m = Fork n ( update'xt k x) yt largest power of Z stdctly smaller than n. since the left and right ~ubtrees of xt
otherwise "" Fork n xt (updateyc k x) are also llp-tree.s, the shape of xt is de.termined uniquely. More9~er, its height
is k + 1 = flog n1. which is the minimum possible.
where m = size xt
Another immedi~te fact is. that if xt is an Up-nee, then xr is perfect if and
,The operar~ons access anct updatewke O(h) steps, where his the}l_eight of the . only if its left: and right, subtrees
.,
have
r
the same, size. Using tllis result, we can
binmy tr,ee. ~ implement hiext on Up-trees by . _ .
. . ' .
l!iext xNull = Lea(x
8.5.2 Adding one-sided flexibility hiext x(Leafy) = Fork 2 (Leafy) (Leaf ;x)

Forget for a moment the operations loext and lorem, and suppose that arrays
can be extenued and contracted oi:lly at the high end. The bask strategy is to hiext x(Fork nxt yt)
implement hiext and hirem in such a way that the resulting tree has a height size xr == size yt - Fork-(n + 1) (Fork n xt yt) (Leaf x)
that is logaritlunic in its size. For this reason,_the fo:llo'h'ing :straightforward othervvise - Fork (n + 'l) xt (hiexc x yt) .
impiementat~on of hiext is rejected: . . . :
The function hiext returns a lip-tree whenever its second argument is a Up-tree.
hiext ex - Flex ex :... Flex ex' The operation hirem is implen:ient~d as follows:
hiext x Null - Leaf x
.. Flex ex - FlexO<
x
hiext (Leafy} = Fork 2 (Lea{y) (Leaf x)
- , , I '
' hirem
hirem (Leaf x) - Null
hiexi x (Fork n xt yt) =- Fork (n + 1) (Fork n xc yt} (ie'af x).
hirem (Fork ( n + 1) xr yc) - fork nxt (hiremyt)
This implementation of hiext always. in(:reases the height of the tree by 1-; con-
sequently, building a 'tree of size nby,starting with the empty tree ?.nd.applying fork :: Inc - Flex ex - Flex ex - Flex ex
hiex,t to n values will result in a t\,ee .of height n; , . . . ~ - .... : fork n xr yt
Insteaq, tlieaim is to increase the ~eight of the tree onlY wh~n:u:is absolut'ely isEmpty xt = yt
necessary. fp particular, adding an element to a perfect tree ., a, tree with 2k isEmptyyt "' xt
leaves all at the same depth- will inevitably increase theheight ofthe tree. For ochenYise - Fork nxt yt
a perfect tree xt of size 2k, we can .defi.ne

8.5.3 Adding full flexibility

The idea can b.e extended. Say a nee is left-perf'etr Jf the left subtree of every The operations loext and lorem are dual to hiext and hirem and can be lin
. node is-perfe~t. Also, recall from the previous sectiot) that a lef'tiM tree. is one plemented by riglJtist rigl!c-perf'ect trees (rrp-trees). The problem is how ro
' . . ... '
286 8.; Abstract data types
. ' : . ' 8.6 I Queues. .
0 '

., \ ' ' . .. :. 287 . 0. 0 : 0:


. com~ine the ~o.lq.nds ..~f ~~~~- One soJution.\s -iiot to ~ombine-.tli;m, ~d'_t~
:.. 4 t. ~ 1 .. ' : ~ ' . .. j : ~ :

represent a flexibJc array by a pair of trees, the left componen t representi.i1g the
The definition of hiren/is the s~e 0
as before, and the definition of (orem Isleft ' ..,:

as an exercise.

lower balf of the arra)r.".and the right component the upper. This is a perfectly
adequate sOl\ltion, excep.t that it.leads to a case analysis in hirem a'nd lorem
. when One Of the component lTees is empty. :
' ... . ,

Exercises I

Dielissen and Kaldewaij's solution is more subtle and more beautiful: allow . ~

the four properties to co-exist in the one tree. By definition, a quasi-perfect 8.5.1 Write down the pdssiblc quasi-perfect trees of size 6.
tree is one in which.all left subtrees are i-lghtist and rlght-perfect; and all right 8.5.2 Gi~e the functions abstr and valid for the represemation .o f flexible anays
subtrees a~e leftist and left-perfect . Perfect trees are quasi,perfecr a11c,l the by quasi-perfect binary trees ..
xt
shape of a quasi-perfe Ct tree Foi:k n yt is comp!eteiy determined by th,e sizes
of' xr and yt. 'The maximum possib1e height h of a quasi-perfect tree o.f size 8.5.3 Give the impl~rrient ation or lorem:
n > 0 is given by -- 8.5.4 Flexible arrays can be used to reprcse_n t queues. Explain bow, and give
h = 1 + maxo.sm<n (flog ml max flog (n- m) ll the time complexities of the various queue operations.

More simply, 11 := i + flog n1. pne ni.oi:e than the minimum possible.. . . 8.5.5 suppose tha~ fl~xible ar~~y.s are augmented witl:'t two addit_
ionai opera-
. . A quasi-perfect tr,ee is neither an liptree nor an rrp-trec: the left subtree:of ti<ins . .. . .. .
any right subtree of the tree is perfect but the left subtreeof the tree itself is .. 0

not necessarily perfect. Accqrdingly, we have to modify t4e definition of hiex( minFlex, maxflex :: (Ord oc) ~Flex oc -:- a
. slightly. Dual,remarks apply to loeX.t and the-resulting programs take the forin Th~

operatiQn minF/ex returns th<;! minimum. dement in a nonempty array.


0

Show how, by augmenting binary trees with additional 1.)1formation, ,these op-
0

hiext x Null = Leaf x


hie:(t x (Leafy) = Fork 2 (Leafy) (Leaf x) erations can
. be implement
.. ed to. run in constant time. . ,.
hiext x (Fork n xc yt) - Fork(n+1 ) xt (hixyt)
'.
8.S.6 a
A bounded fl~;ubk arr~y ls fle~ble array with two. integer values: lower
.. '
and upper, denotilig the lowerand upper bounds of the index positions. The
hi :: oc- FJev. oc - Flex oc ' 0

lowest' element of 'the array xs is xs !I lower and the highest element is xs !!


.hi X (Leafy) = Fo.r k 2 .(Leafy} (Leaf x)' (upper- 1) . Show how l:iou.iictcd.' flexible arrays can be implemented with quasi,
0 0
hi x (For:k.n xt yt)
. perfect trees. .. ..
sizext ~= size yt . - Fork. (n +. 1) (Fork
. .n .xt y t) (Le.af
. x)
'athenvise = Fork ( n + 1) xt (hie-xt x yt)
8.6 Queues
The definition of loext is dual: . .
To complete a quarte~ 91' ~b'sr:act datatypes, let us revisit the type Que':'e ex
,loext x Null Leaf x from Section 8.1. Recallthat
=
. . . the
. . i.nlplement
. alion in terms 6f pairs of lists. >vas ..
lo-xt x (Leafy) = Fork 2 (Leaf x) (-LeafY)
loext x. (Fork n X:tyt)
. . ~ Fori< ( n + 1}. (/o x xt) yt . empty "': ([] ,
.ll! '
'
.
. '.
. isEmpty (x.;;, ys) : .. :-,.) nil/ xs. .. ''
to':.: oc - .Flex a - Ff~ 'ix ,. "

'
join x (ys, zs) . = mkValid (ys, x : zs)
Ia x (Leafy> = Fork 2 (~eaf x) (Leafy)
. (x:. xs, ys) .'!= x
front
lo x (Fork h xt yt) .. back (x : xs, ys} = mkValid (xs, ys)
~

. size.xt
' := size yt.
... . . = Fork ( n + 1) (Leaf ~) (Fork n xt yt)
. .Qtherwise .. = Fork (n + i) (lox xl) yt
. ..... mkVa/id (xs,ys) .. ':' if null xs then (reverseys, [])else (xs,ys)
.. .
~ 0 0
.. -- :
... . . ..
" '

.... ""' -
8.6 I Queues
~ ~

289
288 .. , ~;,./ Ab!tract datarypes
: ;\~ 4... . 1 ..::::..:. ... .,.,.:~ .~ p;.~~~
. -~iere is parr ~f the defm.ltion of rnkVa/id:
The f~ctions abstr i.d .va/jd, which.formalise the repres&.ir<;~ti0n.of queues by ' .
pairs of lists, were-defined by . - - . .- n1kVa/id . .. ..
" . ' .. n, XS, ys) . . . .
(m,
abstr (xs, ys)
va(id (xs,ys)
=
= not.(null xs) v nu/lys
*
((oldr join emptY r~ver~e) (x.S rf?'l(.ew~ys)
- ' . :.~
rn ~ n
rn + 1 == n
-
-
(m, n, xs, ys)

-4 ~.::~
' . To fill in the dots, we have to perform a rotation. This operation takes
Recall also that the amortised cost of the queue operationsJs 0(1) s teps, whil~
ec
the worst-case cost is n) steps on a queue of siie n. ..
(m, n,xs, ys) into (m + n,O,xs * reverseys, [ ])
For this representation of queues, the worst-case cost applies under any in-
. ' teractive scenario. If the interaction js ch:iven eagerly, th~iia bai:l/conunan d The trick behind the faster iniplemenration is t~ parcel out the computation of
. can take .e( n) steps because a list of length n has to be reversed. I{ the' inter- Xs ft. 'reverse ysarriong the other operatll)ns, ensuring:ti1at each piece prodt~ccs
action is dtivcn lazily, then executing a front. command after a backcan take 'exactly Ot~e eiemenl of' the result. i'o perform the trick, r ecall that One efficient
B(n) steps because that is the time required to produce the first element of a implementatio n of reverse is to use an accumulating parameter:
reversed list. .
The aim of tllis section is to. show that we can do better. Firstly, there is reversexs - revcat xs [ l
ari. implementati on of queues which ensures that the ~YO)st-case cost C<lJl be
' . revcac. [ ) ys = ys . . .
reduced to B{log n) steps, provided the interaction is ch'iven at acertain speed. revcac (x: xs) ys = reveal ~. (X: ys)
secondly, ther.e is an even better implementation that brings .the worst-case
The same idea is used in the computation of xs fr reversey~ . Define the function
cost down to 0(1) steps. . Both implementatio ns are due .to.. Chris Okasaki. ~
rot (short for rotate) by
....
8.6.r "FirSt implementati on . . r.oc .. [cl]- [oc)- [ex] - [ex]

a
The fu:st implementation represents queue by .four quantities, a pair .of lists
rot xs ys zs - *
xs ' revcat
'
ys zs
as before, qncl their lengths. The function abstr is defined by . .. ys
Clearly, .xs -H- reverse = 'rot Xs ys [ ].<I'his expression will be 'computed only
. ' in.the case length xs + 1 =/e11gth ys, so we can implement rot by
abstr (Inc, Inc, [oc], [oc])- Queue IX . . .:~ '~ : . . . . ~ . ~ ! '

aqstr (m, n, xs, ys)


- (oldr join empty (ys rever.kis)
. . . " * - rot [ ][y] zs = y: zs
roc (x: x.s) (y : ys) zs = x : rot xs ys (y : zs)
The function valid is defined by . ..
. '
Note that each step in the evaluation of rot produces one new element of the
valid (lnt,lnt, (ex]. [ex]) - Bool
result. Note also that the invariant length xs + 1 = le_n'g th ys is maintafued in
valid (rn, n. xs,ys) - (m ~ n) 11m = length xs 11 n = length ys
' ' .
the subsequent call of roc.
The dauitype invariant is stronger than before: prcviousiy ;ve required only The full definition of mkValid is
rhat if xs is empty, then ys is empty too; now we rei\ui!~ ~i:hnrihe]ength of xs
mkValid ( rn, n, xs, ys)
is at.leasras greatas the length of ys. .... .
m~n - (rn,n, ;~s.ys)
Excep~ for the definition of mkValid, the implementatio n iS- virrually rhe
same as before:
-
.. . m+L == n - (rn+n,O,rot xsys[],[])
.. ' . .. . . ~.. . .. .. .
~

emply - (0,0,[).[)) The interaction is .driven at a speed belween fully eager and fully lazy. In pro-
isEmpty ( m, n, xs, ys) - (m == 0) . cessirtg each join or back command, the functiorr mkValid is reduced, but only
to head-normal form; that is, <).quadruple, This teductio.n takes one evaluation
jolnx (m, n,xs,ys) = rnk~alid (rn, n + l,xs,x :'ys)
step. After processing any command, . the queue is . always in the form of a
:front (m, n, x : xs, ys) - x.
~uadruple, so processing an isErnpty or j oin coimnand takes o( l) steps.
back(rn+ l,n,x:xs,ys) = mkValid ( rn,n,xs,ys) .
. .. . . .. . "' ... , ..

' , .- I
~,.
..
, I .... ' ' , '

290 ~ : ' ~ .....


8 I AIJsiract datCJ!ypes.
; ,o

. 8,6/ Queues : ..~ ... : ' . '' . , .291


' '
...
rem~~. 'to
\,
.
{;o~/ ...:: ",: . ; .... ..
', ' " . , .,,
It esJirnate the CO{)( of..{ront and .b.ack:' Both and. back
- . . .{after process.!bg join4, join 5 andjoin 6} .,. .
are defined by patterri rnatchmg and. require ' that the 'third coi;Uponent of tbc'
.

. . quadmple be' reduced


'
to the form X: XS. Iri. general, the third component XSo Of (3, 3, rot (~ot [ J[1] ( ]) [2, 3] [ ],[4, 5, 6J)
the quadruple (m, n, X.SQ, YSo} takes the form
- (after. processing
... . . join 7}
. ;
- - ~-
,,
xso = rot xs1 ys1 zsi "
(7, 0, rot (rot (~ot [] [1] []) [2, 3] [ ]) ( 4, 5, 6, 7] [], [])
xs1 . = rot xsz )isz zs2
The patter~ sho~ld nmv be 'cl~ar:. ;he,next 7 joins resuitin
7

' '
" '
' '
X.~n-1 == . rot XSn YSnZSn (7, 7, rot (rot (rQt [] [1] []) [2, 3] []) [4, 5, 6, 7] (), [8, ... ,14])
for some ri ;:: 0, where the lists xsn and ysk (0 ~ k ~ n) .and zsk (1 ::; k ::; n) are
ftiliy evaluated. Moreover, for 1 ~. k :S we.have n: J~. ;s only when join 1S is appli~d that another rota~ion is irlvoked. Applying a
. . back command to the queue above involves three reductions of rot.
length xsk + 1 = lengl/1 YSk
' '
.
by the invariant on rot. Also, from the definition of rot we have,for 0 :S k < n, 8.6.2 secohd impleni~J?t<!Hoii. .
that ' , '

The ~arne n~w i~to ensure that n~queue operation takes mor~ than 0( 1) steps
length xsk+1 ' +length YSk+I < lengthxsk ,
' iri the woi:st case. We can do this by ensming that rot xs ys zs is appli~d only
Hence length xsk+l < (length XSk) /2 for 0 :S k < n. . .. to. evaluated lists xs; .that is, xs is ~ot itself of the form rot applied to some
arguments. ,T his is achieved by forcing cine step of the evaluatlOil;'Of x.S'during
It follows tliat reducing xso to the form x : xs involves at most a logarithmic ,
each evaluation of the other operations. Evaluation is forced by maintaining an
number of reductions of rot to the same fonn. But each rot can be reduced to
extra list in the representation; on the other han~. it,is no longer ne~es~ary to
this form in' one step. Evaluation of fr.ont and back. therefore takes O(log n)
steps.on a queue. of size n. ' maintain the lengths the lists ' of
To understand whar'fs going on, it may b~ helpful to consider evaluation of The represe~tation ~~ queu~s is by t1iples of lists. The function abstr is
' the commands defined by
;
... . . .. '
join .1; join '2; .. :; Join 14 abstr . .. . .::. : .([()(], [C<], (()(])-Queue()(
' ' ' abstr (xs, ys, zs) = (foldr join em ply reverse) (xs +f reverse yqJ
Here are the states of the queue after processing these commands bn an initially
empty queue:
' ' '

Ti1e ftinction valid is defined by


(0,0,.[ ], ( ])
:::j(lXi.laJ,[()(]).:. B~ol
.,
.. '' valid' .
- : {after processing join I}
. ' valid (xi, ys, zs). '= (ehgth xs = le119tl1 ys +length zs A. isTail xs zs
(1 , 0, rot[] [1 ) [ ], ~ )) ' ' . ' ... .
the test isTaiiX.szs'r~tUrn~ Trueil'is is a tail segment of xs. In fact, the definition
' '
- {after processing join 2}
.. of valid does not quite eX.:,ress the whole truth, because the representation ofxs
. ](1)[ 1: [2)).
:
{i, 1, rot[
'
. ~

.
' ' '
and zs is shared in the gr(!ph-reduction model of evalmitiori; zs is not a distinct
- {after processing join 3} list, but points to the unevaluated portion of xs. If tl'lis portion is n<?t empty,
. . .'
then reducing zs to head-Iionnal foim results automatically in gencratirlg one
(3,0,rot (rci't [] [1] [)) [2,3] [], [ ])
additional element of.xs.

' .
!1:
.,.
: .. . .. ::
. ,.. .....' ;~ .. "

292 . ...t
.. 8 I (\bstracc dat{ltypes
....
293
.,! -:
8.1j Cllapier notes
.. .... : ' . ' ....' ;..:?,: ~=-. ,: . '
. . . , ..
' l .

Here are the i.inplemented operations: : e Mar~in (l9B,6) ~ncl Haf.rf~ori (1989). A!hortis~d c~~plexit(is Msclibed in
~ormen a~d.
!-..' t 4' , . . - -

empty - ([]. (], []) et al. (1990) in a functional setting, in Schoenmakers (1992) and_
isEmply (xs,ys, zs) - null xs oka:saki (1996). . . . .
join X (XS, ys, ZS} ' :~. The original presentation of AVL trees can be found in Adelson-Velskiand
= mkValid (xs; x: ys, zs) Landis (1962); see also Knuth (1973b), There are many other _balanced tree
front.(x: xs,ys, zs) = - .
X ' -'
schemes; for example, Cormen et al. (1990) discusses red-black trees, a?d An
ba~k (x : xs, ys; zs) mkVa/id (xs, ys, zs}
- dersson (1993) a simple schem'e based on rwo operations, skew and spilt.
The simple ~plementation of flexible arrays is described in Dielissen and
mkValid (xs,ys, []) = (zs, (]. zs)
. . Kaldewaij (1995.);. ~e~ .also ~-Ioogerwoord (199,1). The fast queue implementa
' .

mkValid (xs, ys, z: zs}


where zs = rot X.s ys [ ]
(xs, ys, zs)
in
, . ri~ns can be forn:td Okasaki (1995). Okasaki's thesis (1996) contains a wealth
= of additional material on p~ely functional data structures.
The sharing of the first and third components is introduced by the where clause
in. the first equation for mkValid. Evaluating the second equation for mkValid
results in_one more evaluation of the first component.
The interaction is driven at the same speed as before. EValuating the test
isEmpty (xs, ys, ZS) 'involves reducing xs to head-norm~ll form.' Tllis may invoive ,, ' ..
.'

a call of rot, but rot reduces to head-normal form mone rectu'c'tion step, so ,.
.isEmpcy takes 0(1) steps: Evaluating join involves I'edi1cing mkValid (xs, x :
ys, zs). to head-normal form. Reducing zs ro head-riormal form tal<es 0( 1). steps,
so joir ~ake~ PO} steps. As a side-effect, one more element of xs is comp~ited.
whenever zs reduces .to a nonempty list. Evaluating front (x: Xs,ys, zs) takes
0(1) steps because the first component is already evaluated. Finally, back takes
oo) steps for the sarne reason thatjoin does.
. ..
'. ......
Exercises -.
:, .
8.6.1 Show the final state of the queue after exec.uting
'
join 1; . : . ; join 14; back; front
... 8.6.2 What alternative representation of queues ensures a worst-case .numlng
time of E>(log n) fOI'any operation on a queue of size n?' - - . ::
8.6.3 By definition a 'deque is..adouble-ended queue in which. orie:.cim add and
remove elements from either end. The representation of queues by patrs of
lists can be extended to deal With cieques. How can. tl~s be. done to ensure an
amortised cot;t of 0(1) steps per deque operation? ..
. . ... :.

8. 7 Chapter notes
'

The algebraic specification of abstract datatypes is described :in Guttag and


Horniilg (1978). Two useful source texts on daratypes a~d.rheif-specifica.tions
. . ' . . , . ..
, ..
~..... 40 '

...
...
~

... . ~

.. . ' : . ., ,. . ,...
' ;
. .
' .. . ... ... I
.. ..... ...
... ~

. . ' ... . " : ....'. .


... . ..
' I ,:,

.. '
' , j

Chapter 9
I ./' ,

,. . ..
~

,' .,_ .. .. '

.Infinite lists~- .
'

. . ..;- ~

. ... . ' . '


... . .. . ..
.
' ' . ~. ' '
..
...
' ...: .
'" I :
.

. ' ..... .. ' .

' . ' .'

.
... . Although infinite lists and trees have been introduced alongside their finite'
co.unterparts, the emphasis so.
far h&s mainly ~een on computing with finite .
::.st~ctures . . :i'h.e ann of. thi~ chapter is to explain in a little more detail than
... before exactly, what art j.nfinite listis, and how an infinite list c'<in be repres-
entedby a cyclic structure in a lazy functional language. We \-\-ill describe .a
l)ew technique for provitig properties of infinite lists, and discuss a nwril;er of
applications i..q which infinite and cyclic lists can be used to good effect. In par- . -
ticulai, :i.nfuiite lists can serve.to model. sequences of events ordered in time, so

; '{ ..
they provide one suitable framework i)l which to study lnteractjve
' '.,,T " I';
.. .
processes.
. .. . ..
; ' .,
9.1 Review
. . , ... '
' . ' ....
.. . '. . .. . We begin by revie,:"llg some material on infinite lists. Just as the finite l,ist of
.. integers from m ,toY! is deno.ted by.[m .. n], the in[initc list of all integers from
m upwards is denoted by [ m .. ]. Thus, in 'a session i:nie might have

... ~ ? [1.. ]
, ') 1, 2, ~.4, 5, 6,, 7,8,9, 19, 1~1 _lf!l3,14,15, 16, {lnferrupted!}
; :: .;
. . ~ .. ~ .
": ... It would take forever to print tllis list in full, so we inte~rupt it. ..
. Infinite list's can be used just like any othei lists in a program. A ftmction .
.. . :.. can take an infinite list as an
argument or relui'n an illfinite list as a result: For
. '
.. .. . .. exan1ple, the following statements about infinite lists arc all tme:
I ~ ' . . .,

..
.,
taken [1..] = ~ (i .. 'n]
. . .. {m .. ] !! n - m +n
.' . . map fact [0 .. ] . = scanf.(x) 1 [ i .. ]
.. . . .
' . .. . ~
~-... ;.. . " ~ .. . . -

296 .. 0
. /, . >

- 9/ fnfinite lists
. ... .. .......:.
0

- 0 '
9.1 j Review 297
........,
~
, ', , ol ' , ' , ,

ensions. 'F.or example, the


: . . : ' '
0
'... .
It'is also possible to use infinite lists in list compreh
0
' . .

'Th~ m~th~in~ticiari'~ kno~vledge that one can stop.lookiJtg as s~on as the fir~t
'
.. . .
expression :
.. - square greater than 10 is encountered is her~ enco'ded by the programmer s
decision to use cake While to write the expresswn. '
- .....
[squarex I x - (1 .. ], odd x]
.. :-- ....- _ .:.

denotes:.the hst of' all odd squares. It is even possible to. ha~~an infinite list
of infm.ite lists. Fot example, in Section 6.6-we made us.e of ln!i.nite list of uie 9.1.1 Itiduction
..
infinite lists of' powers of each prime: we saw in Chapter 4 how induction can be used to prove properties of infinite
.. ({Intege r]]
lists. Provided P(xs) is an equation invol.ving a list xs, we can. show that P(xs)
prps
~ holds for all infinite Lists is'l)yestablishing:
prps - map powers primes
.
Case (.L}. That P ( .L) holds.
It is important n or to assume that infinite. Hsts in computing have the same
kinds of p~operti es as infinite sets do in conventional mathematics. For ex case (x: xs). l 'hat if P(xs) holds; th~n P(x : xs) ~so holds for every X..
ample, ~ set th~ory the expression
Not~ carefully th~t th~re is a proviso in ~he statement of the induction princi~le,
{x
2
I x e {0, 1, 2: 3, ... }; x2 < 10} 0
namely that P(xs} .s~o~.d: take the form of .an equation . Without. the proVls.o,
. the n.~o cases a~ove ~e sufl'icient only to prove that P(xs) holds tor all.p~rt~aJ
denotes the _finite set_of all squares less than 10. However, if we t}.rpe the cor- lists xs. Wlth the provi~o. we then get Jar free that ~(xs) holds for (\ll ~~e
respond ing list comprehension in a session then we get lists xs . .In the following section we will expl~n the nature of the relauonship
0 0

between partial lists and infinite lists, and show why the proviso- or at ~east a
? [square
.. ...xI. x- [0 .. ], square x < 10] ... generalisation or It- is necessary.
[0,1, 4, 9 0 0 0

i. What has happened here is that the c~mpute r .deterqtines the::first three ele- Exercises
ments and then goes intO an infinite loop searching Jor some eiement in the 9.1.1 can. ~ve~y elern~!):t}~f..l?rP.~ )~..Pr~t~~. ~y}'lrs.t n,ane_Iilil~. tile list of. lists
I'
infiniteHst [4, 5, 6, .. .] whose square is less than H). Although it is reasonable . : \ Viili' conc~'ffifnot, sfi8W1ib\v'tocteilriean infinite list that does return a list of
to expect a mathematician to recog1use that there is np such .value) ir is not
l. 0
0

all powers of all primes.


reasonable to expect the same degree of s-ophistication from a compute r pro-
;j

gram. in'other words, we do nor suppose that mechanical evaluator is capable a 9.1.2 Does map ( x 3 )[0 .. } = iterat~ ( +3 ) 0? What is the value of this express.ion
of conducting proofs, however trivial they might b.:!. This.do~s- not mean that' when (=} is replaced by (==)7
the beh~viqw of the computer is unmathematical, only that set ~heory is not 9.1.3 Give conditions under which filt~r p xs = takeWhile P xs.
the right theory for describing computations. As we have seen, the value of the
0

above expression is the panialli st 0 : 1 : 4 : 9 : 1... . . . . 9.1.4 The Sieve of Eni't osthenes i~ a'method for generati?g the lis~ of all prime
. ly
. repeated
numberS. The idea is to starr vvith the infinite list 2, 3, . .. and then
.InciilerJ.tally, it is nor difficult to revvrite the expression sCi thatit does return
a finite hst of all squares less than 10. The Usr comprehension isequivalen t to apply the foll owing process: (i) mark the first elern~.nr P of t~e 1ist as prune;
and (ii) delete all multiples of p from the list. Step (u} can be Implemented by
0

. fi.~rcr (< 10) ( mqp square [0 .. ]) . the function sieve, defined by


'
..
and changing filter to take While yields the desired result:
0
0

..
'
.. sfeve(p: .xs) = [xlx-xs ,xmod p*O]
..
? take While ( < 10) (map square [0 .. ]) Using i~erare, vvrite down an expressi~n for
the Us~ .primes of p~im~s.' Henc~ an
[0,1,4, 9] define expressions for rr.<urning the first 1000 pnmes, and all the pr unes less
than 1000.
0 0

. . ". .. ~-
0

0 ,.

.-.
. ..._ . .. .- . '

298 9 I lnfUJite lists


9.2 I I1tlinite lists as..limits. . 299
'
.. ' . ' .. . t

9.2 Infinite lists as limits ... ih which ev~~ ~ie!'Il;;t.~~~.rthe first ~o is [1}. is a perfectly v~d .'sequence
with limit [!) . .Similarly: ..
' '

..
In mati1ematics. iiifi.nite objects are. defined as limits of infinite sequences of .
approximations. For example, the irrational number - l.., 1 :_1.., ,,.1 :.2 ,: ..\.., :. 1:2: l..,
.. . . . .
, ... .. .
rr =: 3;14159265358979323846 is a sequence with J.imjt i :; ;.L Finite and partial lists are limits of sequences
: ' possessing only a finite nuQi~.eF of distinct elements,
can be de'fined as the limit of the infinite sequence of rational approximations
3, . 3.1, 3.14, 3.i41, 3.1415, .. . 9.2.1 Approximation ordering . .
The first element of the sequence, 3, is a fairly crude approximation"to rr. The The way to formalise the property that an inftnite sequence of partial ~sts con
next element, 3.1, is a little belter; 3.14 is better still, and so on. ' verges to a limit is to introduce the notion of an approximatioi;J. ordering~;; on
Similarly, an infinite List can also be regarded as the limit of a sequence of the elements of. each type. The assertion x ~;; y means that x is an approxima
approximations. For example, the infinite list [1 .. l is the limit of the infi~te tion to y. The ordering ~;; "':',ill be reflexive (x ~ x), transitive (x ; y and )' ~;; z
seque'nce of partial lists implies x ; z), andantiSY!llllleJric (x ~ y andy~;; x implies x = y)., However, it
., . ' ' . '

.J..r i : J..,' 1 : 2.: J... i : 2 ': 3 : J., ... is not the case that every pair of elements have to be comparable by ~;; . Thus
' ." is what is known as. a partial or~ering. Note that c is a mathematical operator
Again, the sequence.consists or better and better approximations to the inten (like = ), and not a Hask_eU operator return.irig J?oolean results. .
ded limit. The first term, l.., is the undefi..iJ.ed element, and thus a very crude We will now give a brief sketch of how c is. defined for vario~:~s types. The
approximatiori: it tells us nothing about the lnilit. The n~xt . term, 1 : 1.., i,s subject, called Domain Theory, is a large one and full details can be foun.d in
. a slightly beher approximation: it tells us that the limit is a list whose first the references at the end of the.chapter. .
element is 1", but says nothing about the rest of the list. The following term, The approximation ordering for numbers, booleans, char~cters, and any
1 : 2 : 1.., is a little better still, and so on. Each successively better approxima other enumerated.
lion is derived by replacing l.. with a more defined value, and thu's 'gives more ' . . . by.
type, .is defined
iliformatio ~about the limit. . .. . x ~ y = (x = l..) v (x =:' y)
Here is another
. .. sequence of approxlrnations whose limit is [L ]:
.
The operatof' von the.right'should be read as a mathematical connective. Th.e
1.., l: 2: .1, 1: 2: 3: 4: .L, 1: 1: 3: 4: 5: 6 :, .L, ... first clause says that J. is an.
app'roxima tion ~0 ev~rything. Jn other .words, l..
This sequence is' ~subs.equence of the one above but it converg~s t~ th~ same . is . the bottom element of the ordering. This explains why l.. is pronounced
limit. 'bottom'. The value .L is the bottom element of ~;; for every type. The above
Here is a ~~quence of approx).malio!ls t~~ t does not converge to a limit: ordering is flat. With a flat ordering one either knows everything there is to
know about a value, or one knows absolutely nothing.
.L, 1:1:,.2:1: J. , 3:2:,1: .L, ...
The approximation orderihg on the type (ex, {3) is defined by l.. c (~, yj an~
The problem v:.ith this. sequence ,is tha.t it gives conflictillg Ltit'~rmati~n: the
(x,y) ~;; (x',y') _ <x ~,.x') "(y ~;; y ' )
SGcond term.say.S that the limit begins with 1; however, the thir~l te.rm says the
. the limit begmswith 2, and the fourth term says that it begins with~3. and so 0~1. Tl1e occurre~ces 'of 6 oti the right refer to the orderings on ex and /3, respe.ctiv~l~.
No approxi,mation tells us anytl:t.ing about the intended lin'l-i.t and t,11e seq~ence The ordering~;; on (ex; {3) is not flat, even when the component orderings on ex
does not conyerge. .
It should not be. thought that
. . . . and {3 are flat. For exruitple, in
(Boo/, Boo/) we have the following chain_?f
. the limit. of. a sequepce
. of lists is necessarily distinct elements:
infmitc.
. For example,. .the .sequence
..
1.. ~;; ( l.., J.,) ~;; (l..,False) ~;; (True, False)
1.., 1 :. .1.. . [1}, [ l ], .. .
. ...
. . . .. . . . ....
.
"
,.
I
['
;
.: ":

300 - - .9/ W'inite lists .


.... :. _.:.. .. ..~ . 9.2 / lrifinire lists as llmits 301
.. . . .. :J . : -~ .. .
The ordermg~ ot:l [.a ) is defined by .l xs and .. For n ~ 2 we have approx n [l] = [ l ]. The crudal proper ty of approx, ana one
... . we will exploit in the following section, is that
[]!;;; xs .' : XS=()
(x:. xs). (y: ys) =. (x y) A
-
(xs ys) .. ........
~ . -
~ ,..;;
limn-oo approx n xs = xs
These eqli<nlons should be read as an inductive d~i!fini.d0~ ~~f ~.mathematical . for all lists xs, finite, partial, or intmite. Theproof, ari in~uction on xs, is left as
assertion, not a~ a'Haskell definitim~. The second conditi.P!lS~S that f) approx- Exerctse 9..2.6.
imates only irs elf, and the thfrd condition says that (x: xs) is an approximation
to (y: ys) if and only if xis an approximation toy ail.d xs isan approximation to 9.2.2 Computable functions
ys..The first occurrence of on the right-hand side refers to'the approxi.rilation ' .
One can describe many functions but only some of them are computable. There
ordering on a.
are two properties of computable functions that are not shared by arbitrary
As two _examples, we have
functions. Firstly, a computable function f is monotonic wirh respect to the
[1,1., 3][1,2,3) and 1:2:1.~[ 1,2 , 3)
approximation ordering. In symbols,

x~y ~ fx r;;. {y
However, l : 2 : .l and (1, 1., 3] are not related by . . ~
The approximation ordering for eaci1 type lX iS assumed to have anothe~ x
for all and y. Roui:MY speaking, mono tonicity states that the more orma-
property in addition to those described above: each chain of approximations tion yO'u supply about 'the ar&"l.lment, the more i.niormatlon you get_as 8: result.
i' .
xo Xt ~ ... has to possess a limil which is also a member of LX. The limit, which Secoifdly, a tomputable ftmction .f is continuous; which m eans thai
we.denote by limn-oo x,h is defined by two. conditions:
.. f (limn-co Xn) . = . limn~oo f Xn
. ' '. . :
...
1. Xn ~ limn_.,. Xn for all n. This condition states that th~ limit is an upper .
..
.,
for all chains of approximations xo ~ x, ~ .. :. Roughly speaking, continuity
bound on the sequence of approximations.
states that there are no surprises on passage to the limit.
2. If Xn y for all n, then. limn-"" Xn ~ y. This condition states'that the limit For example, since [1 .. ) is the limit of the sequence
is the Jeasr upper bourid.
. .l, 1 : .l, 1 : 2 : .l, l : 2 : 3 ': i. ...
.
The defirution o.f the limit of a chain of approxiJnarions af)f)Hes to every typ~. '
I . we can compute map square [l .. ] as follows:
1:
' Partial orderings possessing this property are called compjete: Dom$ theory
is the study of complete partial orderings (CPOs for short). map square .l . = j_
.." , For lists there is a useful function approx rhat producesapproxirriarions to m..ap square (1 : .l) - 1: j_
a given list. The definition is
.- ;
map square (l : 2 : 1.) - 1:4:1.
.,
.. Integer - [a ] - [tx) map square (l: 2 : 3 : 1.} - 1: 4:9: .l
approx
- -
apprqx (n + 1) [ ] - []
approx. (n + 1) (x : xs) = x: approx n XJ' The limit of this sequ.e nce is the infinite list p, 4, 9, .. .]-of square~. Similarly,

The definiri6I?- of approx is ve1y similar to that of take except that, by case filter ( < 10) .J.. - j_ ,

exhaustion:, we h ave approx 0 xs = i. for all xs. For example, filter ( < 10) (1: 1_) - l : j_. . .'
" filter(< 10) (l : 4: .l) - 1:4 : l "

approx 0 [1) = j_
filter(< 10) (1: 4:9: L ) - 1:4:9 :' .1..
approx 1 [1 ] - 1 : .L filter ( < 10) ( l : 4 : 9 : 16 : 1.) = 1:4 :9:1_
approx_2 [ l ) = 1:[] ... . .
-.
I.J....
. ..

. . '. -.. '

302 ., -. 9 I IiJfinite lists. ; 9.3 f Properties of iufinite li$tS .


' : ' .. - . ;., , .. .: "'"~~ : .
Every elc:q1ent
' ._ .
o('.the
.. sequence.
. . . after. the third
.. is equal t.o 1 : 4 : 9.: l, ~nd so equivalent to e1 ~ .e2 . A e2 .~;,. e{, . Similarly: an assert.ioi1 .cohsisti.rig of a list of
tliat is also the limit of the ..sequence. On the other hand,
' \

- . .. equations is chain complete.


. take While ( < 10) J. - J_
Exercises
.. . .. :.
.::..... ... ~ ,

take While ( < 10). 0 : J.)


. - 1 : J_ . . ..: . . . .: .. .. ~ ,

I
. .while ( < 10) (1: 4.: J.)
cake = 1: 4 : 'j_ 9.2.1 Draw a d.ircciel:I'grap1f4epicting the approximation ordcrjng 9n t11e typ'(
j '
takeWhile ( < 10) (1 : 4 : 9: J.). - l:4:9: J.
. (Booi,Bqol) , dr~wt11g iin ed;g:~ -rtoni x toy if
x ~ y . . .
- .
-
1 .
take While ( < 10) (1: 4: 9: 16: J.) 1:4:9:[) 9.2.2 Is the function. f : Jnt -: Inl, defined by. f. J.. = 0 and (x = 1 for x
. * J.,
rake While ( < 10) 0 .: 4 : 9: 16: 25: J.) = 1:4:9:[) computable? . - ' '
9.2.3 Using the fact that all computable functions are monotonic and conl'inu
ous, argue that one !=annOt definea computable ftmct.ion sort that correctly
The. limit of this sequence is 1 : 4: 9: [] [1, 4, 9).
=
sorts an infinite list.
1 . 9.2.4 Is [2 , 4, 6, 8, ... ] the limit of the following sequence of approximations?
If- . . .. . .
9.2.3 . Chain corilple:eness
~ .
.. J., z:J., 2:.i.:6:L .' 2:J.:6:.J,. :lo.:l.., ... . ..
. Suppo~e we have establisl;ed by ioduct.ion that a mathematical property P(xs)
is true for all partial hstsxs. Under.: what conditions can we assert that P(xs).is If not, what is? .,
true for all infinite lists xs as well? ..Since ari infinite llst xs is the llm.it.of a c~ain 9.2.5 Pr~ve by induct.ion that approx n'xs ~ approx. ( ~ + 1} xs for aU.n and xs.
of approximations xs0 , xs1 ,... , all of which are partial lists, we know that P(xs;) 9.2.6 'Prove by iriduct.ion th'at approx nxs !; xs for all n, and that if approx n xs~
ho~ds for.all I. It is clear now that the property we are after is that P should hold ys for.all n, then xs ~ ys.
' . in the limit if it holds for each approxiinat.iori. This property of P is called chain
compl~teness . . Chain completeness appears sirnila~ to coritiriuity bitt .differs
9.3 Propertie~ of ~ri.it~_lists
l t;
in t\:VO ' re~pects. One is that the chaincompleteness of P does not imply the
co.nversc property that if P is false for all approximations, then P is false for
... . a
the limit, that is, that -.p is chaiii complete. Secondly, P is matheqtatic~ Unfortunately, the priri.ciple ofinduction is not always sutTicient to establish
a
I '

assertion: not functio n returning a boolean valu~. so it does not Jive in th5;! every propertY of infinite lists"we woula like. Consider, for instance, the flmc

f ... ..
i~ same universe as continuous functions.
Not all assertions ar~ chain complete. For example, ~o~sider the assertion
tion ilerate defined by
.... . .

;,,.
' that drop n xs = J. for some n. 1Jlis assertion is.clearly true for every partial
iterate
iterate (X -
.. (tx-tx)-tx -[tx]
x : iterate f ({ x}
l
.
.~:~...
~. ': list, but true of no infinite list.
Fortunately, a wide range of assertions are chain complete. rn.particuhir, an The function iterate returns an ipfitllte list. It satisfies the follo\o\ing .equation: .
assertion P(xs) of the form e1 ~ e2 , wheree1 and e2 are expressions involving
1 ,.f xs, is chain complete. Any free variables in these expressions arc assuined to iterat~ f x = x .: '?lap f (iterate f x)

Il ..-~
be universally quantified. Thus, if nand ys ~e variables-occurring in e1 ~d e2, This equation asserts that "two. .infinite lists are equal. However, we cann0t
then the .assertion means that e1 ~; e2 for all nand ys. Notice that tlJe assertion use induction to prove the result because there is no approprfate argllinent on
..
r,..
abqve is' not of this form since the variable 11 is existentially quantified: the which to clo induction.
equation. drop n.xs = J. Is asserted for some n, not for all n. . So, how do we p'rovc"suclt res'ults? One tempting possibility is to prove that
t :U. ~ :+:
' . '
If P(xs) and Q(xs) are chain complete, then so is P(xs} A Q(xsY (again; A is . elements in corresponding 1Josltidns are equal; in other words, to make use of
used here as a propositional connective, no_t as an operation on boolean values). the plausible assertion thaf two lists xs and ys ate equnl just in the case t~at
In particular, an. assertion of the. form e1 = e2 is chain complete.because it is xs!! n = ys !! n for all natur~l _riumbers n. Unfortunately, this assertion is false. .
.. .
.. ~

'
.
~

..,
. . ....
,1
i
.. ' .
I,,.:
"'
t ' .. . .... . v - .. ':':-.. . .
.
., 304 . .... . .. _ :. . . ..... . ...._9 I. Infinite lists. ;~.,
f!;j / Properties of infinite lists . 305
'. ' . ,"~ .. . " ... ~ ..' ..~-~":...,-:~;:" . . . . . . . . ., ..... . .
As one cotmterexample, take xs 7 . and ys = [ .L ]. Th~s~Jis.t~are different bur {definition of map}
indexmg with any 'uanmil number returns 1. in all cases.. ~: . :. .. . '
Another possibility is to make use of
tl;le function apptox defined in the .
. approx (n.+ 1) (f'x: map ((iterate f (f x) ))
previous section. Recall that ._ . ..~.-:-:---- - . = : {definition approxJ
. . .
of .
.,. .'
li~1;:..."" approx n xs = xs - .....- - ~ f x: approx n (map f (iterate f' (f x))) .
. ... .. .. .
'
. . . .
for allllsts xs. It.follows that if approx n xs . approx rtys foi all n, tlien xs = ys.
The two sides are the sain:e, establishing the case .and the proof.
More generally, we can prove xs !; ys by showing approx n xs !; approx n ys for . D.
all n~ ' -. ' We will give one. more example.. Consider the infi.h.ite list n~ts defuted by .
'

Let us now use tllis idea ro prove the property of iterate given above. Using
the definition of iterat~, we can formula(e _t_he folloWing equivalent statement

nats :: [Integer]
. of the desiied result: nats ~ . 0 : map ( +'i) nats
iterate r ({ x) - map f Uter.ate f X)
....... We will prove nats =.TO .. ) by showing that approx n nats = approx n [O .. ] for .
Proof. We prove
. . .all I)(ltural munbers n. To do this, we will need the subsidiary result.that
. .
approx n map f' =.
.'
map f' approx n
..
.
and
i . '
approx n (map f (iterate f x))
' . approx n (iterate { ({ x)) =
. . fO'r all f ~- ln other words, a'pprox n commutes'with 'm ~lpf. The proof is
. . left as an exercise.
.. . The induction step
.
'
for our assertion is..
'

by md4Ction onn.
,!
: approx (n + p nats
.,
{definition of nats}
:
.,,' ;' ,Caiie (0), Obvious, s.lncc a,pprox 0 xs == .L for any list xs.'
.
appr6x(n+l) (0 : map(+l) nats).
;
;;: ~;
t. i Case (n + 1). For the left-hand side, we reason:
' : -
..
.li..: ... {definition of approx}
:. . . . .
}. : approx ( n + 1) (iterate f' ({ x)) 0: approx n (map (+1). nats)
!:~ I
.
: I {definition of iterate} ...., . = {since approx imd map commutel
,..,
approx (n + l) (f x: iterate{ (f' ({ x)))
..!'i . ' . .
0: map ( + 1) (approx n nats)

. {definition of approx} {induction hypothesis}


. ..
.. f x: approxn (iterate f ({ ({ x))) ~
. . ' ... .. - 0: map ( + 1) approx n [0 .. ] .
{induction hypothesis} {since apprQx and map commute}
x:approx l'i (map f (iterate f (f x)))
.,\ ~ , , I I
.
, , ' '

f .
. . :
'
. ;
0: approx n (map ( + l) [0 .. ))
. . ' ' .
{definitioq of map)
'

For therighthand side.. we reason: . =

approx (n + 1 ).(map f' (iterate f x)) .. 0 : approx n [ 1 .. ] .. . ' .

. . {definition of approx}
= {definition of iterate}
. approx (n +l) (map f (x : iterate f' (f x))) . appro_x (n +1){0 .. J..
. ' . ..... '
....
~
.. . ~
., ..
:

306 .. _9 I lnfillltc lists ,-9A I CyClic structures : . 307


-~ '
.
E-xercises After-more has.been:evaluated, ft will be rcprcsente'd by the graph .
.. . .-
9.3.1 Prove lhat iterate (+a) b = ((i x a) + b I i - [0 : 11:
~

. .
9.3.2 Suppose we define fibs = 0 : 1 : (x + y I (x, y) - zip fibs (tail...fibs)]. Prove
.. that fibs= map fib [0 .. ), where fib is the Fibonacci ftmction. State car:efully any
'M'
.~: 'r ' ie' .:~l'a; 'n, ~ 'd' ' 'm' 'o' 'r ' 'e' ". {
0 0

subsidiary results th~t you use in the pro-of.. . . . . . which again involves a cycle. , ..

. 9.3.3 Prove that xs = ys if and only if ta_ke ~ xs = taken ys for all.n. We now con~ider three furth'er examples of the use of cyclic snuctures.
. . . . .

9.4 Cycli<; structures


r .... , '

9.4.1 Repeat

Data structut"es, like fu nctions, may be defined recursively. As a simple ex- The function repeat is such that 'repeat x is the infinite list [x, x, x, .. .], so the
ample, consider the definilion definition of _ones above is equivalem to
.. .
one ::, [fnl'] ones
.
repeap ,::
''
=. .
ones = 1 : .ones
',

One way to define repealls


We have ,.

ones = 1 :'ones .; repeat .. (x ::.. [ c<i ..


= . 1 :-1 : on~s repeat .x . - x: repeat x
...
= 1 : 1 : 1 : ones This definition is correct, but does not create a cyclic structure. U ones and
repeat are defined as above, then af~er displaying the first five clements, ones
will be represented by the giaph
The name ones is bound to the infinite list [1, 1, 1, ...].
Recall from Chapter. 7 thilt expressions
. are represented
. by graphs in the 1 : 1 : 1 : 1 : 1 : repeat 1
evaluawr. The representation of ones as ~ graph is particul~ly interesting, as .,
. .
it involves a cyclic structure: which is not cyclic. If the next_element of the list is displayed, the snbt<:.rm
repeat 1 will be replaced -by J : repeal 1. Consequently, the list ones grows
longer with each evaluation. On the other hand, if the definition of repeat is
changed to

The entire infinite list is therefore represented vvith a fixed amqunt of space. repeat x = xs wh~re xs = x : xs
As a second example, consider the deftriition - . .
..
. . .. then the definition of ones in terms of repeat will produce the same cyclic
more .. String
. .. structure as before.
.
more = "More " H and.more .. .. ~

where andmore = "and more


.,. . " * andmore
..
9.4.2 . Herate
The 'vah.i~ of more is also an infinite Jist:
Here is a new definition of th~ ftUi.ction iterate, this time using a cyclic structure:
? putStr more
More and more a,nd more and more and more and m(lnterrupted!} iterate f x - xs where.xs = x : map f xs
. .... ._ n , ,o
. : ...
.

. ... ' ' -


308 .. . . ., ..: ', ~9 I !Iihnjt~ lists .j (ydic structure$ 309
; , ) ' ' .~ ._~~~ ~ ;.:~~:-:. ' v
, ' ..
.'

Consider the,.term iterate (2x) 1. The first few st.eps ofe.valu,at,i'q.g this .term are ' thus, the requi~ed llst begins with the riumbers . .,
as follo\vs: - , -- . ..
i,2, 3,4, 5,6,8,9, 10, 12, 15~ 16, ... -
iterate (2 x) I . . . .
-...
~

. . .. n--.
the Ha.nlming pr-oblem ~s impo.r tant, as it is ~ypkal of a class of problems known
:..-:-..
. as closure problems. In
general, a ~;:losure problem specifies a collection of
., :''.. ,: . . 'f... initial elemenrs and a class of gencraioi functions. In this case, 'we are asked
.w find the dosute ofthe initial element 1 under the generating functions (2 x ),
.: '
.. ~ 1:~2 : map(2x)l (3X), and (Sx). The Hamming problem has a particularly efficient solution
becauserhe generating functions are' monotonicllilcler (<);for examp~e. (2x)
iS monotonic because X < y implies 2x < 2y; similarly for the other generators.
~ 1:.2: J4:map(2x) J The ~ey to the solution is to make use of the functil)n merge that takes two
infinite lists of numbers in increasing order, 'and merges these into a single list
In particular, if { x can be computed in 0(1) steps, 'then the first n elements of of numbers in increasing.or~er, r~moving duplicates'
iterate f x can be computed in O(n) steps, . .
.' +
If ,we eliminate the ~here clause from the above defhiition, \ve get yet an::

. merge :: [Inte'gerf"- f!nteger] - [Integer]
other definition qf iterate: merge (X: XS) ('y: ys~
- .
. x< Y - x: mergexs(y: ys) . :

' . itera'te f x = x : map f (.iterate.{ x) ..


X== y . = x : merge xs ys
We s-howed earlier in the chapter that iterate s'atisfies this equation. The new. X>. Y - y: merge (x : xs) ys
' def:lmtion does not use cyclic lists, and turns out to be much less efficient than
Giveil merge it is easy to define hamming:
I! :. the previous definition. Considering again the n!rm iterate (2x) 1, the first few . .
I: steps of evaluating tllis term are
! i. hamming [Integer ]
I :
r: iterate (2 x) 1 > hamming - 1 : merge (map (2x) lwmining) .
~ l : map (2x) (iterate (2 x ) 1) (merge .(map (3x) hamming) ...
. :
~ l: 2: map (2x) (map (2x) (iterate (2'x) l)) "' ' (map (Sx) hamming)) .
. t
;:; 1: 2:4: map (2x) (map (2x) (map (2x) (iterate -(2 x) 1))) lriftially, hamming will be represented by. the following cyclic structure:
. . ' -
It can be seen that evaluating the first n terms requires Q(n2 ) steps. In this
example, the use of cyclic stmcrures is essential in achieving cfficfency.

~ 1 :merge ('map (2x)Ir


:.

I. 9.4.3 The Hamming problem " I

(merge (map (3x) )


A well-known problem, due to the marhemahcian W. R.'Haiilining, 1s to \VJ.i tea
(map(Sx)t:_
prograni
.
that
.
produces
.
an infirure list of numbers
.
with tl1efollowing
. "
properties:
~ . '

., .. ..
(i) The list is in st1ictly increasing order.
(ii) The list begins with the number 1.
:. (ill) If the list contains the number x, then it also conrau;_s the~~mb~rs 2 x x,
'
_ ) X X, and 5 X X.
(iv) The list contains no other mnnbers. ..

_, -
"
..
.,
' ' 310 9./ [nlioite lists .9.5! EXample: .the pa;er~f~ck~s~i;~ors game ' , 3l.l
.. ... ..... . ' ' - :,. .... ....
' . .

. After the first severi elements of hamminghave been printed/the above . a list in. ascending oi:der sudi that every b in bs iS in the list, and if X iS in the ..
structure
. will 'have.reduced to. the
.
foll9W4tg: . ' Jist then 2x; 3x, and.Sx Me
iiHhe list. Write a program to solve thiS version of
the Hamming problem. .. . ..
. ...
. . :r
.. .
. i'. . . .
9.5 Example: the PC:\P~:r-rock.-sdssors game .'
. . ~~~~ .
(9 :.merge(map (3x) )
e~ample h; Instructive as well as enter~ai~ng. Not, o~y 'does it intro-
' '
Our next
(10: map (Sx) H
.' ' duce the idea of using mfin,itelists to model a sequence of iriteractions between .
~ote that fu;st n elements of the list hamming can be computed iri d(n) .steps. . processes, it aiso provides a. concrete illustnition of tne m!~essitY for formal
num-
.'
. An ~bvious generalisation of .the Ha~ng problem is to replace the analysis.
bers 2, 3, .and 5.by arbitrary
. positive ntimbers a, b, and c. We then
. have' The paper-rock-scissors game is a familiar one to children, though itis
known by differentnamesin different places. The game is played by two people
hamming:; a b c = 1: merge (map (ax) (hamming' a b 'c)) .
facihg one another. Behind their backs; each player forms a hand in. th~ shape '
- ... (n.1e,rge (map (bx) (hamming' abc)).
of either a rock (a clenched ('jst), a piece of paper (a flat palni), or a pair of .
.. ' I
.
(map (ex) (hamming'
. . abc))) scissors (two fingers ext~nded.). At a giveni.i:1stant, both players brii1g their
This solution produces the correct answer, but does not form a cyclic structure, hidden hand forward. The winner is determined by the rule 'paper wraps rock, . :
and so rquites O(n 2 ) steps to compute the fust n'elements of the. result list: It rock blunts scissors, and scis~ors c~:~t paper'. Thus, ifplayerJ .prod~ces arqcl< ,
is left as'~. ~xerci~e to modify ham:ming'
. . 'so th,a t'it
. ' does form a.cyclic stru~ture. and player 2 produces a pitir o(sdssors. tMn player 1 wi.n~ bet:a~s~ blunts : r6ck
sc.issors. If both playepfpro'dttce. the same object, thenthe.gaJ11~, i.s a t~e and
. . '
\

neither wins. The game continues .. in this fashion for a fixed- number
'
of rounds
Exerds~s
' :
, ' ' ' ;

agreed in advance. . . ,.. ,, .. '


9.4.1 Define dither by Our objective in this sect~ot1 is to write a program .to play: aM score the
game. We begin by int.ro~uc~~ the types
dither. = :yes
'
where yes . - "Yes."* no data Move .. = Paper. 1 Rock 1 Scissors
no - "No!"* maybe typ~ Round . = (Move, Mowi)
.. : ' ' "
maybe = *
"Maybe?" yes . ' ' ' . ~ ' . ...
In order to score a round, we":rieed the function
What will be printed if dither i; typed in a session? Draw the gr;;tph of the cyclic
structure that represents this value. score:: Round- (Int,Int)
9.4.2 Draw the foilr cyclic graphs that represen~ h(:lmming after the first 1, 2, score (x,y)
xb~atsy ' :: -' . :,..1 ~0)
3, and 4' elements have been printed. - ... t ~

ybe_a tsx . . =,. (o,o


9.4.3 Modify hamming' so th~t it forms,a cyclic structure. otherwise = ' ~0;0)
9.'!:4 We can generalise the Hamming proble.m by replacing the multiples 2, 3,
S ~1th .a list as of positive numbers. That is, we wish .to find a list i,n increasing. The comparison function ~e~ts ca n be defined by nine equations. Altern~tively,
order that,beginS ~~th 1 and SUCh that if X iS in the list and a iS i.n as,
then a X X we can define '
...
is in the list. Write a program to solve the generalised, Hamming prob~enl.. (beats) Move - ,~fove
- Boo/
.
9.4.5 We can also generalise the Hamming problem by replacing 1 with a list.
'

xbeatsy - (m + 1== n) v (m == n + 2)
'bs of positive nUm.bers sorted in ascending order. That is, we now\vish to find where :rn.= codex; n = code y '.
' .
. . .. '
' .'
J.
'
.
,
,.,... "
. ' ,," '.:. ,: , , , , I ..., .. I
~ , ,
312 ' .. ~ :..'. . .,~ 9 I Infinite liscs ' 9.5'/xample: the pap~r-rock-scissors game
I
. . <~ ~: ~). . ;.:, .:; 313
.. .' I, '
' ., - ~ ,.., ...... 4.,., ,,, . .
.... . .
c.ode . is and
. :--. .. . . . . . . . ,'1 . . .
...
:
.. , ..
.Move- In t <( ' . '.
..
1: ... The first mo~e arbitrary, here we have chosen Rock. The' second strat.egy
CQdriPaper = 0 .... ' smart can be implemented by ' ' . .
- 1 . .
'
codeRocJ< ..
Code Sclsso"'~
I~ ;,. 2 ' '1. ; , ~
' smart Strategy
...
:1.-

if null ms then Rock else choose (count ms )


\- -
smart ms -
1 ach player. in'the game will be represented by a cert;~~ strategy. . For' in: . .
stance,,
.. "o9e .simple strategy is, after the first ro~<;l. alw,a.ys
. . ~o produce what count :: [Move ] - (Inc, Int, Int)
the opposing player showed in tbe.previous rotmd. This strategy will be called count = fold/ (e) (0,0,0)
recipro'c ate, or recip for short. Another' strate'gy, which we will call smart is to I

determine a move by analysing the number of times the opp'o:iu!nt has produced . (e) . {Int,Inr,Inr) - Move- (Int,lnc,Int)
each of the three possible objects, and calculating an appropriate response (p, r, s) e Paper - (p + 1, r, s)
based on 'probabilities. (p, r, s) e Rock - (p, r .+l, s) . .
We will consider the details of particular strategies, and how they can be (p, r, s) e :;cissors = (p,r, s+l )
represented, later on. For the moment, suppose the type Strategy is given in
some way. The function rounds will have r'ype Again, Rock is some arbitrarily chosen first move. The ftmctio~ count counts
; /j , . .
.. the number of times each move has been made .
rou11ds :: (Strategy , Strategy) - [ Round]'
The runction choose determines a inove by analysing the three. ~~bers
This fi,Ulction takes a pair of strategies and retums the infinite list of round.s p, q, 'and r. In order to define this fimcdon, suppose' random :: lnt - I~t is a
that ensue when each player fol!o~vs his or her assigned strate!:.'Y qven roLmds a
ftmcrion that takes positive integer n 'and re.tU.rns some in~eger min the ~~ge
. we cah define a ftmction match that determines' the resultofplaying a given 0 ~ m < n. One way to implement this ftmction is to generate an infinite list
nwnber of pseudo-random integers, and then pick the nth element of this list, scaling
. ..'qf rounds of the game. The definition is
!' appropriately. We will not go into further details, but see Exerdse 9.5.1':
'

..j . mt:Jtch :: . Inc - (Srrategy,Stracegy) - (Inc, Ini) W.e can no"": define choose by
..
,

:.~4 .,:.. ~ , \ '


'l

~ ! ' triaich-ri' ':=' coral . map score .:taken . rounds .. . ..: .


..?::1il .~ .. .
..

:'
.

.. '
.

.. . .
'

.~ ;. . .. . . ..
.
.

-.
:
I 0 :lo , .. ,. . ' choose:: (Int,lnt, lnt) ....; Mqve
l ~ '. ~-.-: iori{/.~>.~;.i ~ f (Irll ,Inr) j - Uni. :Jnc) . choose(p, r, s)'
I
o

total
I

pair (sum map {st, sum map snd)


... ~- - m< p = Scissors


-. -
.'
m <p+r - Paper
9.5.1 Representing strategies . othenvise = Rock :
. .. 't. . ' i where m ~random (p + r + s)
In order to complete the model of me game, we must deci.de ori how strategies
; .

are to be represented, and so supply the necessary definition of rounds. There The function choose determines an appropriate move depending on whe!:her m
at
arc least two methods for representing strategies .and it i~ insr~uctive to falls in one of the three ranges .
compare ~hcm.in some detail. In the first, we take .. .
0 ~ m < p or p ~ m < p + ~ or p + r ~ m < p + r + s
rype _
S trategy = [Move} - Move ...... . . .
For example, if pis large, then smart will choose Scissors with a large probability
Here, a ~trategy is a function which takes the (finite) lisi n;~~es made by the oi . (because scissors cuts paper); and if r is large~ then smart will choose Paper
opponent so far and returns <m appropriate move for the subsequent round. with high probability (because paper wraps rock); and so on..
For example, the recip strategy can be implemented 6~ We Cffi1 now define the function rmmds:
recip Strategy .. . .. -. ..... . '
rounds .. (Stra tegy, Strategy) - [Round]
r ecip ms = if null ms then Rock else last ms rounds({ , g) - (map /a.st rail iterate (extend'({, g))} (]
..... . ..., ...:
.' . ... . . ..
.. .J- ..,


.. . . . .: '
' . ' .:; ~ .' ~.
. 314' 9/ Infinite lists 9.5/ Example: the paper-:roc~-::~cissors
. ...
game 315
. "" : .
' ~: ~ ::
. -
. ex.t~nd . :: . (Strategy, Strategy) - [Round] - [Round] . computes the. ~st n IT!lfves of _the game in O(n) steps, assuming that f ahd
e"<tend (f,"g).rs = rs * [({(mapsnd_rs), 9. (~~p {st rs))] g compute each new movnvith constant delay. Thus, the second !nethod Jor
mo~elling strategies leads to a more efficient progran1 than the earlier one.
The function ~tend appends a new pair of moves to the list of existing rounds,
.and rounds generates the infinite list-of rounds by repeatedly applying extend .' I
to the initially empty list. 9_.5.2 Cheating
The definition of rounds is clumsy. More importantly, it is not-very efficie~t. Unfo/tumitely, however, there is a c11,1cial fiav,. with the second representation:
Suppose a strategY takes time proportional to the length of the input to compute it offers no protection against a strategy tlwt cheats! Consider the strategy
its result It follows that extend takes D(nj steps to update a game of n rounds
.by a new...one, Therefore,
. to compute a game of N rounds requires D(N2 ). steps. cheat xs = map trumps xs

where
A second representation. For comparison, let us now consider another way
we might reasonably represent strategies; This time we take trnmps i'vfove - Move
trumps Paper - Scisors
type Strategy = [Move] - [Move] ..
: ' . . . . trumps Rock .. . Pap~r,

In th~ new representation, a sttc~tegy is ~ function that' takes 'the;infinite list . trumps Scissors : "" Rock .. .
of moves inade by the opponent 'and returns the infinite List of replies. .f or ~he first reply chiwt is 'tlie move ~laranteed to beat the opponent's' f:i~sr' .
of
example, the strategy recip is now implemented. by the equation move; similarly fQr .su\J~.eqilei).t tt1oves. To see that cheat can.n'ot be prevented
: . " ' .

recip t.ns . =
from subverting the gCl!lle, consider a match invhlch it is played against recip.
Rock : ms .
Suppose xs and ys are defined by xs = cheat ys and ys = recip xs. The values xs
This
. strategy .. returns Rock the first time, and thereafter retun~s just the move and ys are the limits of ~~e chain of approximations xso, xs1 ... and yso, ys,, ... ,
made by the opponent in the previous round. Observe that t,b.i.s version of reCiJ? respectively, where xso = YSo = 1. and
prod\).ces. each successive output with constant delay.
XSn+l - cheat ys11
.
The strategy smart can be reprogrammed as follows:
YSn+l - recip XSn
smarr xs = Rock: map choose (counts xs)
Now, we have
counts , = tail scanl (Ell) (0,0,0) .. .

. function counts computes the ~g c~unts


. The ... of the.. three possible moves.
xs1 = cheat 1. = 1.
.
The smart strategy is also efficient in that it produces each successive output ys1 "" recip 1. - Rock: 1.
with constant delay.
With our 1~ew model of strategies we can redefine the fUnction ro.L(nds to be xsz "" c~eat (Rock: .L) = Paper: 1.
. .. ..
. .. - Rock: 1.
=
'

rounds. (f, g) zip xs ys


..
. . where xs =.f ys; ys = g xs '
.. x.S3 = che~i (Roc()) . = Paper: 1.
=
;
' + ys3 = recip (Pape'r ': .,!,.) .. Rock : Paper : 1.
Here, ><s is the list 'of replies computed. by' f ill response to the list ys which, .. ..
~
.. .
.....
in turh, is th!:! list of .replies made by g in response to xs. To ehsure that
'

xs4 = cheat (Rock : Paper : 1.) = Paper : Scissors : 1.


rotmds(f, g) d.oes geneJ;ate 'an
infinite lis~ of well-defined (that is, non1.),moves,
ys4 = re~ip (Paper: .L) - Rock: Paper: 1.
we require that the pair of mutually recursive definitions, xs = f ys and ys = gxs,
generates in.finite.lists of well-defined elements: We will discuss ~his. aspect be Continuing in this:vvay, we .see that the limits of these sequences are indc~d .
low. If f and g . ~atisfy the requirement, then the new definition ..or rounds infinite lists of well-defined mov~s and, moreover, cheat al\vays trimi:Iphs.
,. ' ', ,.. -
... ., ~ . ~; <o.. ~. ,.

- ..
.. . "'"
:; f

316
.. .. ..
:. . ..!!. I Infinite liscs 9:5./. Example: the. paper-rockscis 317
I.
,. ~ ! :~ . .: . ""':":~~
. . . . sors game
.
) ~,' . . . . . . ~ ; ,.:.::.,. ~s. :.~i:. ;
The strat~gy cheaf is no.t
. the only one. that om cheat,:
th~ fi+?t. (we!Fdei'l.Qed!i element of its ourput.before it gives f thdirs( element
. . . Hete
. .-
are tl),r~e more: .,
of it~ input. Similarly for the other elements. -r:he definition is
cunriing xs = trumps (head xs) : cunning (tail X.s)
oneshot x.s = tmmps (head xs): recip (tail xs)
.. . police f xs = ys where ys = f (synch xs ys)
devious x.s - *
take 2 ( recip xs) Cheaf (drop 2 xs_} ~

synch :: [Move] - [Move] - [Move]


The cunning strategy is equal to cheat on in.l'imte lists, but whereas cheat .l = .l,
synch (x : xs) (y : ys)
we have cunning .l = .l : .l : .l : .... The strategy oneshot cheats. on the first.
== if defined y then x : synch xs ys else undefined
'~ moy~. but thereafter acts like recip .. The strategy devious plays fair for two
i . moves' and then cheats.
Can we find a way to protect against such. strategies? To answer this' ques- .
' The test detlned.y re~n~ Tru~ if y .!s a w~ll-definect move, ancll: otherwise;
a suitable definition is left as an exer~isc. The proof, due to Berend Sijtsma,
tion, we need to take a closer look arwhat constimres an honest strategy. In-
thatthis implementation meets its specification is rather invol\;'ed, so we will
formally speaking, a strategy f is honest if the first move is computed in the
relegate it to the exercises.
absence of any information about the opponent's first move, the second move
It follows from the above analysis that to prevent cheating we must rewrite
is computed without any information about the oppone~t's seco)1d move, and
the definition or rounds as follows:
' so o~. Moreover, each of these moves. should be lveJI-defined, ,give!\ that rhe . . '' : . . .. \ . .: ....... -~ <!: . : ..... . . '
...
. oppc>rie'n tismoves :are weil-del'ined. . rounds({. g) = zip Xsys '
More precisely, define open(n, xs) to be "the assertionthat the firs t n moves where xs = police f ys; ys = police g xs
in the list xs are well-defined. Then f ~s honest if

. .
. ope'J1(n,xs) : ~ open(n + 1.{ xs) ... Exercises

for all n and al!'llsts xs. 9.5.1 One way to generate an infinite list of pseudo-random numbers is by
.~
. . ..
It is easy to show that rec{p is honest. On the other hand, cheat is not honest
because open(Q,J.) holds but open(l, .l) does ~1o t, and randOrrJS :: [lnt 1 .

, .. randoms = iterate {.seed
. open(l, cheat .l) .= open(l , .l) - .
, '

,, ~ ~..
4
'l

"
I'

: '
' "~

;: 'Wneiefx;; (a x
, . ;, '! '
x+ c>' mod ~
.,.
. . ...
It is easy to check that the. other ~eating strategies arenot. hone.st. Nor, by the . The four magic numbers here are: (i) the starting value seed; (ii) the multiplier
way;- is the si:r:aregy dozy, where . -- . a; {iii) the increment c; and (iv) the modulus m. ~he method is known as the
.. - linear congruential mechod. The four numbers should not be chosen randomly;
'/ ....d.~:zy.xs : ,;, repeat undefined see Knuth (1981) for the principles of choosing the nUIIJ.bers ,appropriately. Use
'. . . this method to construct a. suitable implementation of the function random of'
Although dozy doesn't acmally cheat, it never rcrurns a well,defu:led move. .
0 ' o .. 0 A ' , ,- 0 ' \

the text.
Having identified the source of criminal. or lackadaisical, behavjou:r, can we
ensure th~t .only honest strategies are admitted to the game? The-answer is a 9.5.2 Give a suitable definition of defined:: Move - Boo/.
qualified yes: although it is not possible for a mechanical evaluatO);.tO racognise 9.5.3 Suppose in the definition 'o f police, th~ definilion of synch_ was replaced
cheating (in the same way rhat it is not possible to rccognis~. .L, ..Gr strate!,ri.es by the simpler
thatdo not rerum well-defined moves), it is possible to define a func!!on police ' .' '
so that if f .is an honest strategy and xs is an i.nflnite sequence of well-defined synch (x: xs) (y : ys) = x: syncfl xs ys
. moves," then police f xs = f xs .. On the other hand, if f is. nc:>t ho~est at some
point, then rl)egame ends at that poipt in .L. A more precise:statement is given Show .that the new version or police allows the cunning strategy to escape de-
in Exercise 9.5.8. Operationally speaking, police works by..forci.Q.g.f to return . tection.

.........
.. . ~-.

.. . '
.. 318 9 I Infinite lists ~.6 I Streilml)ased ipt,erac!iQn 319
.. . . ' -
.
. . ,
~:5:4_..-(i~e asserti9n open(n, xs) can be defmed induc~~~i; by taking open(O, xs)
~ , , ,, ~ J. " . '. " : : I

. 9.5.10 Asstlillg-,_qpep('n :1- 1.{ {approx n xs)), prove that


to 'be.true, and ' . . : - - . . . ., .. .- :.. ' ..
opcn(n + 1, zs)
open(n + 1, xs) = defirr~d(~ead xs) 1\ open(n! tai~ xs) => f (synch xs zs).~; f (approx n xs) 1\ .,opcn(n + l, f (synch xs zs))

The assertion defincd(x) is true if xis a well-defined move, and fal se otherwise. r
9.5.11 If ys = (synch x.S "ys), then ys is the limit of the sequence of approx
Prove the following facts: i.JJlatlons ysk. where yso = l. ~d YSk+t = f (synch xs ysk> Using the previo!ls
exercise, prove that
. ' opcn(n, xs) :i open(n, approx n xs)
open( n, xs) 1\ xs ~; ys =.:. approx n xs = approx n ys .,open(n t 1.{ (approx n xs)) => police( xs ~; f (app'rox n xs)
open(n,xs) 1\ xs ~; ys =.:.' open(n,ys}
. . . . Hence complete the proof of the claim in Exercise 9.5.8.
9.5.5 Using the results of the previous exercise, show that if f is honest and
open(n, xs), then approx (n + 1) (f xs) = approx (n + 1) (f (approx n X:>)}.
9.6 Stream-based interac;tion "

9.5.6 Prove that \

So far, all of our sessions ,.,'[ij1 the c'o inputer have,involvcc:l.a ui}iforhl and simple
open(n, zs} => approx 11 (synch ;xs ys) = approx
' ~ .
n xs pattern of interaction: the user types an expression to be e~aluatec\ at the key
' board, and then the value of this ex}m~ssion i~ printed:on the screen; T his style .
for all 'l.istS'Zs and all partial'<and hence infiriite) lists xs. of interaction is suited for a wide ),'ange of pu.t;poses, but sometin1es:.other fonns
9.5.7 Use the previous two exercises to show that iff is honest and open(n, xs), of interaction 'are requir~d. As a tTivial cxaJnple, we might wa11t everytlling
then : typed on the keyboard to be echoed on ~he screen, but with lower-case letters
converted to upper-case. We might also want to play gan1esinteractively with
. approx (n + 1) (police f Xs) = approx (n + l) (f xs) the computer. M01;e selious e1{_amples include a program to rw1 a 'functional
computer interactively, or ~vena. complete operating sys~em.
.Hence ~how that (police f xs) !!.k = (f xs) !! k for all k (0 5 _k 5 n).
9.5.8 Prove that
.. Our aim ilnhls section: is: to give a highly simplified view of one way in
which interactive progran~s..can be written. The method, caHed stream-based
' interaction, is -the one adopted in some functional languages, and was also
open(n, f xs) 1\ -.open(n +1, f xs) => (police f xs) !! n = l. used in early versions of Has~ell. However, Haskell now provides an alternative,
much more general appro.ach for handling interaction, ;mel we will be discussing
Explain why this fact is too weak to detect cheating. {1-iint: take xs to be an
this approach in the following chapter.
infinite list of well-defined moves, and { = cheat) The result we are after in
the r~mruni.ng exercises is ... , In the stream-based method, ~interactive program is writteri as a function
.. f with type
. open( no( (appr9x nxs)) t\ .,open(n + 1.( (approxn xs .. . f .. String -:-- Siring
=> (police f xs) !! n = l. . - . ' .. .. . ' ;-

In wq~ds, iff cheats at,some (fust) move n bY failing-to.giv.e (n + 1) well-defined .When


'. .f is run . ..... .the input to f will be the sequence of characters
. . interactively, .'
As a
~ "' ~

typed a t .the keyboard.


. . . . Th~ output. of f Will pi'inted in the normal way.
replies~ for n well~defined Inputs, then police f xs returns. l..at mo~.e number n. -. '
simple example, the fUf:!Ction
9.5.9 Prove that
'
map capitalise :: S~ring - String
open(n + 1, zs) => S)inc11_xs zs ~; approxn xs
is an interoctive program .for converting lower-case chan1cters to upper-case.
for all lists ;s and cill par~al (and hence ail infinite) lists ><s. The derinition of capicalise was given in Section 2.2.
... .
,' . '
_...... ..
~ ;
320 . 9 I Infinite lisrs .. 9.6/ Srrcam-based interac~iim 32 1
.
-
' :' . ' .. ! '
...
:, . .:. ... . .
~ . :. -...;,;..,...~:..
l
1."'' ; :
: ..
To DID an interactive program, Haskell provides a comrnap.d .remainder of the input is treated similarly., Nore'.carefully that the responsibil
-...
. '
itY for uirerlea~g input and oi.npur correctly is entirely ln the protpammer's
inte~act :: (String - String). - IO ()

hands.
. . .
The above form of interaction is called stream-based because it makes es-
We~ explain the rype 10 () in the following chapter.' Now, U:.!n a session, "We sei11ialuse of the facnh at lists are evaluated lazily. The word 'stream' is often
type intera ct (map capitaiise), then the evaluator ent~rs an intenictive mode,
used as a synonym for lazy lists. For example, the behaviour of the capitalises
waiting for input from the keyboa~d. lf'we type the st:rillg' ~'Hello, world!", then
program described above is modelled by the following sequence of partial lists:
we will see the ourpur
!
capitalise .L ...
:. ? intera ct (map capitalise) = .L . .
capicalise ('H' : 1. ) . . 'H': 1. ..
. HELLO, WORLD!
capita lise ( 'H' : 'e' : l.) - .'H': 'E' : .L
The P!ogram is fully interactive: that is, as soon as 'H' is typed on the keyboard, capitalise ('H': 'e' : 'l': .L) = 'H' : 'E' : 'L' : .t
an 'H! appears on the screen, and then when 'e' is typed an 'E' appears on th~ capitalise ('H' : 'e' : 'l' : T : .L) - 'H' : 'E' : '1' : '1' : .L
screen, and so on. The program will run uritil the .interrupt keY...iS typed or the
computer is tu,med off. . :- . . The sequence can be viewed as a l?lstory of the inu!ractive session. When noth
One can also design an interac tive .progr am
.. ~
. . ' . that
.
tennin. ates. For exc:unple, ing has been. ryped at the keyboard, nothing has' appeared' on the .screen. When
capfialises .. String - String an 'H' hqs been typed, an 'H' has appeared on the screen..When "He" has been
capitalises - takeWhile (* '.') map' capitalise
typed, "HE" has appeared on the screen. And so on. tf we type a full-stop
.;
character, then the history ends:
behavesin the same way as map capitalise, but terminates execution when a full
stop character is typed. Note thar the full:stop character will not be echoed on capitaI ise ('H. : I
e : '1' : '1' : . : .L)
I = ['H', 'E','l', 'L']
.' ' the :;cn~en. . . .
just as earlier ..L was used to denote a computation that has not yet completed,
Supp'ose we' wanted a different style of interaction, .exemplified by
here .L is used to denote input that has not yet been typed at the keybo<i!i:l., and
? in.t eract echoCap output that has not yet appeared on tl1e screen. A special case of a computation
Hello, .world! . ..... that'has not yet completed is a computation that will never complete, that is, an .
:
HELLO, WORLD! . infinite loop. Similarly, two special cases of input and output are th<: input that
.. results when the keyboard is never touched again and the ourpu qhat causes
G.oodbye, cruel world!. the screen never to be priilted on agai~. These, roo, ai-e all denoted by .L.
GOODBYE, CRUEL WORLD!
..
This tilne, each line typed by. the user is first echoed on the screen before being 9.6,1 , Discu~sion.
capitalised. Here we have to design echoCap so that it interleaves echoing an~ The model presented above is too simple for .most practical purposes. In a
the result of capitalisatioO: .. ...' .~ serious application one wants to do other things rhan reading and printing
.. . chilr.acters to a screen. For example, one also wants t'o open and read fil es, to
....echoC. apx.S = YS*" I"* ... . ..,.,'l'ite to or delete files, and in general to interact with all the mechanisms that
map capitaliseys * . * echoCap (tafT zs)'
r are -available in the world outside ~he confines of a. functional programming
* ,-n xs .
wbei'e (ys, zs) = span (
language. . ,.. .
The input xs is decomposed into the string ys of characters before the first Interaction takes place in time, and the order in which events occur has
newline, and the remaining string zs. The string ys is echoed ro the screen, fol- to be managed correctly by the prograinmer. In the stream-based approach,
lowed by a-newline, and then capitalised. Another newline is printed, and the this ordering of events is represented by the order of the elements in a list; in
''"' ~ .
..
'
322 9/lnfinire lists 9.7 I Chapter not~-~ 323
... '
.' , . . ~.- ' :.: : . ,
_other words; it is regresented in the data and not reflected primarily in.the way in Davey and..Eies_~IexJ~~9Q); see also GUI!ler (1992) for a modern treatment
the program is composed. In the following chapter we will consideranqther of domains and their importance in the semantics of programming languages.
approach to interaction, indeed, a general method for writing programs that Sijtsma's thesis (1988) studies various aspects of i.n.firute-list programs, and
. ha~~ to control an orderly sequence of events. ln this approach, the order is gives a number of techniques for reasoning about infinite lists. One chapter is
m<,lde explicit in the way the program is composed. deyoted to the proof of faimessin. th~paper-rock-sdsso,rs game_.
. Gordon'$ thesis'(I~9J) ~ontai.ns a useful history of the variou's appq)aches
E--xercises to the treatmeiirof interaction in a functional setting. . .
One of the mo~t exciting recent developments in programming .semantics
9.6.1 Wri~e an interactive program to interleave individual characters and the~ has been the use of games and strategies to provide a model (or: j.ntcr.active'
upper-case equivalents. For example, typing "Hello, world!" should prod~ce processes. See the chapters by S. Abramsky and M. Hyland in Pitts and Dyber
HHeEILlloO., wWoOrlULdD!_! (1997) for readable accounts of the basic ideas.

. : ...
9.6.2 Write a utllily'program read with type . . . . .

read :: String - (String - String - String) - String - String ,


' .. ,

The functi~n- read msg f denotes an lnteracti~~ progran1 that first prints ames-
sage . msg on the screen, then reads .the next line 'xs from the keyboard and
echoes it ~s it is read, and then evaluates the function f xs on the remai~der of
th~ input. . . iitlo!l.71J.
9.6.3 Write a similar utility program write with type
write :: String- (Siring_- String) - String- String
. .
..
The function write msg f first writes the message msg on the screen, and then
evaluates f 011 the input.
9.6.4 Write an interactive prolP:am to model a queue, as illustrated in Sec-
tion 8.1.
. . .
9.6.5 The backspace d1aracter -- when typed at the keyboard indicates that
the previously typed._character should be deleted, and when printed' on the
screen causes the cursor to be moved back one.position. Write a l,llility function
readEdit t11at is similar to read except that - can be used to-edit the input.
For e.~am!Jle, typing."goop-d" foll?wed b~ a newlineshould cause th~. string
'.'good~' to be entered..(For ~dloing, note that a character already printed on _ the
screen .c an be re.move~i by printing "..-u..-"; this backs over tlie charact~~ . WJ'ites
a sp~ce iJ;J. its piac~. 'arq ~hen moves th~ cursor bac~ over the spac~.) . . .
.. ' .
,
9. 7 Chapter notes
.. :
Domain theory grew out of the work of Dana Scott in the late 1960s, see Scott ...
(1976) and Scott (1982). An accessible account of the basic mathematics is given
. : .r- .

.'
. .... .. . - .~ ,
.
chapter 10, '- .
.: ;

.: .. ; . ... . .. .: .
..... - . ,
' . . :.
. . ,'' ;: .....,
'~
I

.'
-Monads
, .,
.'
,
. '

. ,..

'

;' I

. This chapter introduces a new style of functional prograinming, called monadic


~
. .. ,,: .
.,.
programming. Monadic programs provide a sjmple and attractive way to cope
"
iJ
..
..,,
... .
,.
..
with interactibn in a functioh_al setting: But, as we 'ivill see, monadic style of a
.. . . . .. programming is capable of much more: it provides a structUring mechanism for
. r~
''Ii!i .!: dealing with a range of problems, including exception handling, parsing, and
l;
:. .
: state-based computations. In a sense, a monadic style enables one to ,..,.Tite func- .
1: ~ . ::
tiona'! programs that mimic imperative prot,'l'ams, those programs constructed
in imperative languages such as Pascal and C.
I ~ ',
.. We begin by considering a particular monad, the input-output monad !0 oi,
. for .expressing programs that involve interaction, a topic that was introduced
. ' .
' lit t):le .e nd of the preVious .chapter. We will use this example to. motivate the
' . definitfon of a monad,~asWell as''give a immber of examples of interactive pro
t ' . ' ' :'' ~
I ' ,; ' , , : . . . ' .F ,' ' '

grams. After that, we will explore other ways in which monads can be ttSed to
.. ' good effect, and introduce the fundamental laws for reasoning about monadlc
. . programs .. . ..
"
-~ . :. ' ' . .
'!'!. :' '
..! '; . ' I

";.j, I'
.. 10.1 Monadic interaction
-' . . . . ..
t: .. .' i '

! . '
.: :~
The type of commanc.ls ~1 Haskell is denoted by 19 () .. An eJ..-pression of type
'; 'I -~
'
:,. . ';

' .... !0 0 denotes an action; when evaluated, the action is performed. The type
.,
J
TO () is an abstract type in the sense _of Chapter 8, .so we are not told how
.,.. values of the type are represented; what is important is the operations that
,. .
:' the type provides. In fact, we will be interested in the operations of the more
!" general type !0 c.:, but we start \\o'ith the simple version first
i: . One ftmdamental operation is a ftmction to print a characi:et: -
..;I
..
putChar :: Char - TO ()
326 ~ 10 1 ~tonads . i 0.1 / Monadic in tet:action . . ' 327
. .
....
' ' . '

,, ...
For
, .
instanc~.
,
' . . - putCitar '!' p~ints an exclain&tioil
evilluating . . .
'
mark: .. ' ....' 'f.h~ generalisation qf_d9n~ ~s . the command that does nothing and reli.ltns a
nameg value: . - -. ' .
.? putchar '!'
! .. rewrn :: ex - .IO. ex

Anoiher.cqmm~d is. done:: 10 (); when perfo~med done does nothing: .. . For instance, perforniing the coiiirnand return 42 returns the value 42 \Vithout
consl.!lning any input.. In.: partinuar,
? done
done :: 10 ()
? done = relurn () . '
'

Next, we need a way to combine


. . commands.
. One
. such operator is :
The generalisation of() is an operator with type
' ..
( ) :: 10 0 - IO () - 10 0 () :: tocx-I0/3-I0/3
If P and q are commands, then p q is a corrun.and that, when performed, If p and q rue commands, then p q is a command.that, when performed, first
~st d()eS p cin;ct the~ does q. Using.(>>) we. can irriplement the functiQ:Q.. write, . does p, ignores the value returned, and then does q. for example,
.'
which has the same effect as the Haskell predefined funcqon putSr.: .
t ? getChar done
'
.,., write .. String - 10 () ' ' . ' ? :. .:.:.-~:. ~:'
. . \ ' ' .'
. .
.
:
'
.'
write ['] . - do.ne . After entering the command (ended by typing a newline), tbe. user typed the
write (c: cs) - .putChcir c write c's letter 'x'. The <;:onunand ge(Char
. echoed it to the screen, and. then. the,
. conunand . .
done terminated the interaction.
One can afso express write.in terms o_f foldr: The type of. getCI-tar. done is IQ () and, as we have said, expressions of f'
: write (~ldr ()done: map putCh~r this pruticulm' type can be evaluated in a session, causi.flg conmJ<md~ to be
= .
performed. On the o~her haild,expressions of rype IO ex for ex* (}cannot be
i
The function ~vriteln is si,milar to write, except that it prillts a newline chara~ter evaluated during a session; for exan1ple,
. aft~r printing ~iie s~ring: . ... ? getChar , .. ,
' ' .
,

writeln :: String - 10 () ERROR: Cannot find slww.funcnon


. .. . .for IO Char .'
writeln cs = write cs putChar 't' Haskell provides no' mechanism for printing values of type lO Char. We will
see in a moment how the programmer can process the v.alue returned by a
111e type IO 0 is adequate for output, but needs to be. generalised for input.
conm1and of type 10 ex.
.The t~tpe 10 ex is th~ type of commands that yield a vhlue of type ex ... Thus, the
It is clear that the command p q is useful only when the value re,t urned
special case 10 0 is when ex is instanHa ted to the .ntilla.rY type () that.contains
by pis not interesting, since .there is no way that q can depend on it. What is
just one proper member, ills<;> ~itten (). Tllis l'}'Pe was discussed bri~f,ly in
wanted is a more general operator . .
Chapter 2. , ' . . : ,,"

.A'Pt:ImitiVe Cipe~ation on.the mote general lyPe reads character.:. . . a . '


(1>) :: w~-
. .<ex..... :- !Qm
~ . "
-wfJ
'
'.
....
I

gel Char .; .:: IO.Char .. ' The combination p 1> q. is ? command that, when performed, first does p, re-
tUrning a value of type. !X; then does q ~ returning a final value Y. of type /3.
x
When the user. types ~ome _characters. at the keyboard, getChar returns the We v.il.lleave has an exercise to show that() can be defined in terms of (I>). i.
~:
fi\'St character. In Haskell, the default convention is that getChar echoes the The Haskell sy'ntax fort>.ls =.
character to th~ scree~. We will see how to use getChar in a mo~ent.. . Here is an example u&ing (I>): .
,,
...
.. -
'" , ft I

328 ,_
. .. . .,\.-.~..
' ~.:.::
329
..
? getChcir'l> pucChar ..
~ t'..~~ - . ~::;.
. . .....
XX ......... . ... ~ two operations are require'd to satisfy certain laws, which we will come to
.in due course. The remaining pri.inii:ive operations purChar and getChar of JOe(
After entering this command, which has type 10 (), the user typed the letter are specific to input and output. Haskell provides a range of other primitive
'x'; the command getChar echoe~ this character to the 89'een; the function functions for input and output, some 'of which we will mention below.
putChar was then applied to the character, causing it ro oe printed once more.
Using (I>), we can define a function readn for read.irig.'a fiXed .number of .
characters from the keyboard: 10.1.1 Monads and do notation

r eadn .. lnt - 10 Scring we can de<;lare monads as ~ rype class in Haskell:


readnO = return [ ]
readn (n + 1) = getChar 1> q
, dass Monad rn where
1
; . where q c = readn n 1> r return . .. a-rna
where r cs = return (c: cs)
(1>) :: rna- (ex- m/3)- m{3

This h as a straightforward reading: to get a string of length (n + 1), first get a The class Monad is our first example of a type class in which the rest.ricted
cha.ract~ c; then get a SO'ing cs oflength n, and finally rerun'i rhe strmg (c: cs). variable rang~s over ty'pe constmctors rather than over types. To emphasise
. : .. T~1~ .u~e..~f nested where clauses is clmnsy, and we willlntroauce a sup~rlor this, we will use roman rather. than greek letters (in fact, Haskell /uses roman
notationlti. avmomem. . . .. .... .. : ".. letters for both kinds). The type constructor /O.is an example of a monad, the
Probably more useful than readn is a function readln that reads a line of corresponditig instance
'
declaratio~ being suppli~d asprimitive.
' ( '
.l. . '

... texr from the keyboard, that is, the list of characters up to buT not including For instances of the class Monad, Haskell provides a notation - called do
the.first newline character: . : notation - as an alteinative to writing combinations o(l> \"'ith nested where
. readIn .. 10 String clauses. For example, the above program for 'readn can be written in the altern
readln = getChar 1> q . . .. arive.form
where q c = if c :: ' I' readn .. 1nt - 10 String
then return [ ] readn o. - return [ ]
.. . else readln 1> r readn (n + 1) - do c - getChar
where r' cs,; rerurn~(c: cs) cs- readn n
To suminarise, the input-output monad 10 a is an abstract ty};e on which the return (c: cs)
follo~g operations, at least, are available: . .
.I .
, r
! ' I .
. . This reads: perform the command getChar and bind the result to c; then per
I
. retLlrn .. ex-lOa for!Il readn nand bind the result to cs; finally, return (c: cs).
I;..I' . ..'.
(1>) .. 10 (X - ((X - 10 /3) - 10 {3
.. similarly, readln can be written usmg do notation as rouovvs:
I;,
, I ' .
.. . ......
putChar :: Char -10 () . .., . ... . readln .. 10 String
. . getChar. .. 10 c;har .
. ... readln - do c - getChar
. . . ....
,,.,, . ... . ..
. if c == r
The tlrst, two operations are combining forms thar chara:ct.erise th.c class of then rerum {]
types called inonacls. Thus, by definition, M is a monad when .the following
operations are given: .. "
else do cs -
readIn
' . return ( c: cs)
r ewrn .. ex-Ma
- Notice the layout of the conditional expression, with the indentation of the
(I>) .. MIX- (ex- fv! /3) M {J
then and else clauses. These'are made necessary by Haskell's rules of layout.
.
' .
330 10 ( Mou~ds 10.1 I MonaC.Uc interaction 331
"
. ..
._
. ., . . ; . .
Alt~rnatively, as ;.-.ith where clauses, a do clause can be .written with bracesana palin . ~:' String - Boo/
semi-colon_s to make the separation of c:lauses e~:plicit. For example, . palin xs .;. . (ys ==reverse ys) ' " '
where ys = map toUpper (filter isL.e.tter xs)
. rGadn(n+l) . = . , do{c - g~tChar; cs-readnn; return(c:' cs)}
.t
The definition of isLeirer:is left as an exercise.

An example session mjght be

' '+
' ' '.

For a general.monad M, a do expression has the form do {C; r}, where Cis a .? palindrome .. . . ;.... .
list of one or more commands separated by semicolons, and r is an expression Enter a string: Madam, I'mAdam!
or type M /3, which is also the type of the entire do expression. Each command Yes
..
takes the form 'x- p', where x is a variable, or possibly a tuple of variables; if
p is an expression of type M ex, then the type of x is ex. In the particular case ? palindrome .
ex = (), the command () - p can be abbreviated top. Enter a string: AMari, a plan, a canal - Suez! ' .
The translation of a do expression into 1> operations and where clauses is No
governed by two rules: AS a more complicated example, here is a program to plcw the game of "hang-
man". ln this game, one p layer thinks of a word, and the other player tries to
do {r) . = r . .' deduce the word b y mal<ing.:a 'sequence of guesses. For .each guess, the- com-
puter (which acts as mediator ~etween the players) prints the secret word with
... do {x ~ p; C; r} = p 1>
'
e q x = do {C; r}
q wher_
all those letters not guessed so far replaced by a'-'. The game ends when aU
It is easy to check that the former.definitions o f readn and readln are equivalent
. might go.
letters have been guessed correctly. An exan1ple session
to the new one's by appJ,ic~tions. or these rules, a task we leave as a~ ~"e!cis.c. -?i.i:?~. hangman . -
?.
Think of a word:
10.1.2 ~amples
Now try to guess it!
Let us now look at soine simple examples of the use of IO ex. First, here is an guess: last
j.nteractive pr'o gram for reading a character and revealing its numeric value: --al
....'' ,.
reveal .. IO ()
guess : dial
reveal - do c- ge!Char --al
putChar r guess: opal
write (sl!ow (ord c)) -oal
guess: foal
When reveal is performed, the user types a character, and the computer piints -oal
its nwneric value. guess: goal
Next, here is an interactive program that prompts for a strii!g, and then says . ..
You got it!
whether'the string is a palindrome:
The progi:am takes the form . .
palindrome .. JO '() .' " !

palindrome - . . a string:u"
do write "Enter hangman .. w.o
cs- getLine
.
hangman = dowriteln
. "Think of a word:"
if palin cs word - silentReadln
then writeln "Yes" .write In "Now try to guess H!"
else writeln "No" . guess w9rd
~ ..
,, . .. ' ...
332 ... ~., " lD)Monads.i
J.'o~l I Monadic interaction 333
~~ - :~ .. -~ _.,: :.~~~-;i< :.; ._
The command si/entReadln reads a line from ~l).e keyboard, Bu~ does not ~,..h,.,
\':,ncmf\::>Lu characters, and V.rrite 'the resultto a s'e~ond file: ' .
the characters. Instead, it prints' a . for each chara'cter read. To implement Ull'~
we need another. Haskell primitive (unction, getCh, which is s~ar to getCna filterFile JOO
except that the character: is not echoed. In f~cr . . . ... _ ";. filterFi/e - do write "Enter input file:u"
.... . ..
._ I '
.
~ :._, ,
'

...:-...
"''
'
infile ~ gerLine
getChar do {c - getCh; putChar c; retumc}' -- write "Eiuer output file:u"
-- . .
=
.- outfile - getLine I

The command silentRead/n is now implemented as follows: xs - readFile inflle


writeFile outfile (filter /sAscii xs)
si/entReadln :: 10 String 'writein 1'Fii'tering si.tccessf~l"
., silentReadln "" do c - getCh
if c ;: ,-+, 11te function isAscil is defined in a Haskell library. .
then do pucChar c As the foregoing examples show, writing monadic programs using do nota
return [] tion is very similar to writing. traditional imperarive programs in a language
.....: '.'
;
else do putChar '' such.as Pascal or C. But there are differences; for example, the function readFile
cs- silentReadin' - reads a file lazily on demand. Consequently, the two commands
.. .
... ''
.. relurn (c: cs) .
. ~ . ' ~
'
"
' xs- readFile tnfi/e. .
The co.mmand guess word accepts input from the keyboard until the guess writeFile OLitfile (filter isAscii xs)
' . I
.
matches word: do not cause the entire contents of the fil e to be written inw memory before
...
being filtered and written out.'
guess String - IO () Another difference with imperative programming is th~n the monadic style
guess word = clo ~rite "guess:u"
is available in Haskell as an optional extra: for those portions of a program that
.....
cs- readln
if cs ==word
are mdependent of interaction, all of the fuiictlonal techniques have ~een in we
pfevious chapters still apply. . '
then writeln "You got it!"
... else do write/n (compaYe word cs)
guess word .Exercises
,.
.. ... 10.1.1 Define() in terms of (t>). .
' t.'
I
. ,.
. ; ~ompare
compare word cs =
Scring - String - String ,
rnap check word
. 10.i.2 What is the effect
.
or the command {old/() done .map putCha(?
where check w = if member
... cs w then w else ''

. Finally, here is a suggestive exan1ple that makesuse of avo'Haskell file-handling


... primjtives: .

readFile .. FilePath - IO Srring . . '

writeFile .. FilePath - String - IO () 10.1.5 Using e>, define an operator o with type
. ..
'
(o} ( t..'<-!0~) -(/3-JO y}-(01- IOy)
The type FilePath is a synonym for String; files are namedby strJngs using some ::
implementation-specific convention. The example is to rea_d a file, remove :all Using o, define t>.
. - . ..
.. ..
~ .. ..
"

Monaci.s
-

:r 10I
T

334 ..: : 10.2 I Variations on an evaiwltor


. :
. .... . . . ..
.. t ': ~ : ~.

.. !. ' : .....'::.

10.1.6 By expandit{g.do n~tation ;sho;.. that. The basic evalu;ilion r~cfionJs defined by . ..
. ' ' . . ... .
do {C; do {D; r}} = do {C; D; r} eva/ .. Term - Int
_..
a eva/ (Con x)... . - ...
X .
10.l.7 Rewrite the reveal program ~~ that.itre pea.tedly prompts fo~ charact~!
. . - ..' .. . ..
eva/ (Div t u)-= (eva/ C) div (eva/ u)
rev.eallrig its numcr~c value, until the user types a particular character, 'q' say,
to terminate theiriteractlon. !The func~ion 'eva/ takes a.' term :to an integer. If the term is a C~llSt~nt , tl~e .
10.1.8 The hangman game is perhaps too easy. Modify the response to a guess constant 1s returned . If the term is a quotient, its subterm s.are evaluate d and
the quotient is compute d.
so that letters are re':'ealed only if they are present in the guess in the correct .
position. . The following will be used as running examp l~s:

answer, wrong Term


10.2 Variations on an evalua tor answer - Div(Div (Conl97 2) (Con2 }) (Con2 3)
wrong - .Div(Co n2) (Div(Co n 1) (ConO))
. ln thls sectionwe are going to examine several variations on an:eyaluator for
. . simple..aritlunetic expressions. The aim is to show how a monadic.style tancap- Here's a simple tt~al of the.'eValuato r:
ttii:e the essential similarities between. the variationS; and - more importan tly._ . -
enable each variation to be installed without changing the basic structure of the ? eva/ answer
program. We will b~gin with a simple evaluator, and then add certail'l; features. 42
..Spccifically,.we.w.lll add: ' ' . ' . '. . .
?eval wrong
Error bandiing, which involves m odifying each recursive _call to check for [BOOM!)
and hancile errors appropriately. .
The problem with. th~. s~cqncf e?'ample Js th~t division by zero yields a~ un-
~ Ail.op~a ti~~ count, whi~h ~~~lve~ m~difying each recursive call t~ pas~. defU:edr esult. Undefine d operation s may be impleme nted in any way, and this
around such counts appropri a.rely.
p.aro~ul<l! computer implements division by zero with ar1 explosio n.
An execution trace, which involves modifying each recursive call to pas~
arotmd such traces ~ppropriately.
10.~:2 Exceptions '
In each case, the bookkeeping involved is straightforward, but t~dious. ~or:;e,
~ter we go out and buy a new computer, we may wish to modify our evaluat~r ,.
.. a welter
. it threatens to overwhelm the essential simplic.ity of the evaluator' with . ,
of detail. After giving thesevariation s, ~e will revisit them, showing how a. a
. Lo:h~ck for division by zero and return suitable error message. It is not appro- [,
can be usecl t.o instilll each variation with .far)ess fuss. . prtate to use t.h e primitive f,Ul;lction error for this purpose. since the evaluato r
. -.. .approach
inonadic ,, . . '

may be used interactively. The iilin is not to abort the evaluator., but merely
... il'II
.. to hCU:dle the error.an~i_d)spl~y a.,suitablc message to the user. Such ex~eption
10.2.1 The basic evaluato r
~Clfld!mg m.~Y be rni.rn,i~ked ~Y; introducing a type to reP.Feserit comp~t~tions ..
...,
<I
.
The eval~ator a~~S ~n terms, Whlch, for pw:p~ses of ID~st.ration ar~ t~.en to b~ that may ra1se an exceptio n:
:I.: '
excessively' simple: ' J.
data Exc rx = . Raise Exception 1 Return rx 'I
data Term = Con Inr 1 Div Term-Term type Exception = .String . .. 'I
A term is eith~ aconstaJit Con x, wlm:~ x is ~ i~tegcr, ~r ti.quorient, Div.:t u,
L...
A com~utation Exc rx will eithet' raise an exceptio n or return a value of tYJ)e.rx. ,,
Exceptio ns carry an error message, r epresented as a string.
f
where i and u are terms. I
l

.... '
.,.. . .... . ,.,. .
i,
'
i."'
li
." ' .
..-...~ ;.-.; :> :~: . ~ .
... . ..
:' o- . ; . ....~

336 _ . . : .. . .. ;{-_;;~> .. 10 I Monad!/ . . I . .,Variinioris. on an evaluator


' 10.2 . . 337
.J.
. '<~-":,: ~~~ i : . . . . .
: ; :,,. ,f' ' ! ": '' r. .~ ,'' ' . ' . .'
it ;iS Strc,tightforWard, but tediOUS, tQ adapt tbE! e\'alUa~bl'!Q. thls representa
.; - -~:,.

Sucha state may be mimicked by introducing a type to represent c6nil:mtations


tiorL We.write the new evaluator in a particular way to emphasise the order in . that act on state, called.a state transformer:
which the computation is to be performed: . . .
'

..
' ' .
... ...... . .
. ......... -. newtype St C< = MkSt (State .,.. ( e<; State))
'. '
. eva! :. '. Term - Exc Int :~ . type State = Inc :
e.v4l (Con x) = Return x
A stat~ transform-er of type St e<is a .function that takes ~state, and returns a
eva/ (Div cu) value of type e< paired with a new state: The state will be used to coun.t division
- h (eva/ t) steps, and so is representt:d by an iriteger.
where
. ,. .. : ' ''the constructor MkSt'makes":S't a new'cype, distin~t from the underlying
- Raisee function type. The auxiliary function apply applies a state transforrner to a
4

h (Raise e)
h (Return x) = h' ((~val u) state, yielding a value paired with a new state:
where apply St e<- State- (e<,State)
h' (Raise
. e') = Raise
. . e' apply (MkSt f) s - f s
h' (Return y) ... . ' :,

.... .
. = if y == 0 ., .
Here is the hew evhlm.itor: . : : ., /. ' . . .
~

': . . : . .. then Raise


. "division
.. by
. zero"
. . ' ~
eval :: : Term .~ stInt' .
,;

.
else Return (x div Y.)

.
I! eva! (Conx) - MkSt f ' .
At ~a~h. :':
caU.of the evaluator, the form of the. resltlt is checked where f s = (x, s)
. ....,.. . ... by
. the
. auxiliary
.. ,
. .
tiandling functions h and h'. If an excep~ion was raised it is re-raised, and if a
'

eval (Div t u) - .MkSt f


value was.returned it is processed.
where ..
We:c.a n aiso specify how to display an exception, by inst~ing Exc e< as an
. . ins'.t.an~J-bf Show (for sirriplicHy, we define the flmction show only): f s . = (x div y, s" +. 1)
. '" '
.. . where . . ,
. ~stance Show e< =>Show (J:xc e<) where .' --~:-:<;;i}:J.~~~~;:.~-~~:; .;:.,;.;; -.-*(~C~') ;' :..~ ':' "apply. (eva/ r) s
. . . show (Raise e) - "exception: " H e ,.., .- (y,s") = apply(evalLI) _s'
. show (Recurn- x)
:' = "value: " ft show x .. .
.. . .,,. . At each call of the evaluator, the resulting state transformer is applied to the
~

:.

. Here is.asession with the new evaluator: old state, and the value and new state are returned..Care must be tal<en to. pass
. .
? eva/ answer .on the-state properly- it is all too easy acciden~ally to \'Vfite s where we should
! .
. '
\vrite s'. . .
value: 42
t,
.
we can also specify how 'to display a s t~te transformer:
' '' . '
'?eva/wrong
..
"instance Show e<::;. Show (St LX) 'vhere
exceptio~:~division by zero show { = "value: " It show X# ", COUllt: " #.ShOWS
.
;., .
. where (x,s). =.apply (0 .. .
I 0;2.3 Slate
... A state transformer f is displayed by applying ino the initi~ state 'o, 'an<i then
A$ another variation, suppose we want to count the number of divisions per- _displaying the final value and count. Here is a session \"'ith the new evaluator:,
formed. during evaluation. One way is to introduce an addirional component,
called the state. The state in this instance is an integer, irii'tial1sed to zero at the ? eva/ answer
.. : value: 42, counr: 2
siart of. the computation, and incremented by one each time .
a division occurs.
. ...'
338 ' 0.2 I Variations on an evaluiltor 339 '!
.. .. ....
' .
.,
I'

19.2.4 Output .. ... . .. .


'' . ' 2.S A monadic 'evaluator.: : ' ' .. . '

Finally; say we want to display a n:ace of the executio~ steps. Output can be . The basic evaluator. is ~asiiy ~cwri~te~ to make us~ of a monad m: ,.
!

mimicked by introducing a type to represent computanons that generate out-


put: eva/ Mon~-~ ..m =:- T~rm .,.. m) nt
eva/ (Con x) - r eturn x .
newty,pe Out ex == MkOut (Output, cx) eva/ (Div t u) :. = do x - eva/t
type Output = String y- eva/ u
' . . return (x div y)
A value of type ,Out/X. consists of the genen.ited output p-aired with the cornpt.lte<:r~
valu~. . . U1e type of eval indicates that it tak~s a. term and perforrps a comp!ltation' m
Here .is the modified evaluator:
' . yielding an integer. To evaluate Co_n x, just return x. To evaluate Div t.u, first .. '
evaluate t, bind x to the res\tlt, thei1 evaluate
. . u, ' bind y to the resuft;;and then:
eva/ .. Term - Out lnt .. ' . . '
.refurn x <liv y.
eval (Con x) - MkOut (line (Con x) x, x)
eva/ (Div t .u) = MkOut (ox* oy *
line (Div t u) z, z) The new evaluator is a little more comple~ than the origi.r:ial one, but it is
where MkOLlt (ox, x) == eva/ t much more flexible. Each of the. variations discussed ab'oveUlay be achieved
MkOut(oy,y) - evalu . simply by defining m to be an appropriate instance of the Monad class, .and by
z - 'x divy making one or two local modUkaHons. . ..
Firs t of all, in the basic evaluatora computation is ~imply the value rerurned,
:;:~~~#; The Identity monad is declared by first introducing a new type Id ex, lsomorpl):ic
* show ~ * "r:
line :: Term - Inc - Output _
to cx:
line t x = "term: " ~how t * yields .. * .'
newtype ld ex == Mkid cx
At each call of the evaluator the outputs are coUected and assembled to
the output of the enclosing call: The fUitction line generates one ~e of
instance Monad Id where
output. We assume the usu(!l definition of show on l\!rtnS, and specify how return x - Mkid x
.display a computation with output (Mkid x) 1> q - qX
instance Show ex~ Show (Out IX) where
. show (MkOut (o~. x)) =; ox* "valwi: "*:show x In the identity monad, Id is isomorphic to the identity function on types, return
. . .- . is isomorphic to the. identity.function, and (1>) is isomorphic to functional ap- ..
Here is a session.with the new evaluator: . plication, except that the argument coincs before the function.
W,e can also specify how to di~play elements of type ld 01: d1:
? ella/ answer '
term: Con 1972, yie!ds 1.972 ., instance Show ex ~ Slw~v (Id ex) where
term: con 2, yields 2 . show (Mkid x) == "value: ;, *show x
. term: Div (COI11972) (Con 2) , yields 986 '
term: Con 23, yields 23 . . The evaluator evalld
. . is exactly eva/, .but. specialised
. . ' '
to m '= ld:
term: Div (Div (Conl9 72) (Con 2)) (Con 23), yields 42 evaUd .. Term - ld Int
value: 42
,

'' evaUd - eval


to install the ..:xt::Lut.Lvu
+ j

In passing,. it is worthwhile mentioning that it is easy For example:


.,

trace so tl1at it prints in reverse order: just replace


'? evaUd answer
ox tt- oy * line (Div 1 u) z by line (Div t u ) z * oy * ox value: 42

! ;:
..

340 0.:2 I Variations on an evaluutor


....:,,..... ' ::-. ...... . 341
.'' '
~.
.. . :" . .
In the ~xception monad, a computation inay either r!J.ise.an gxception _or uiitial states, yieid~g value x and -intermediate state s~; then.it ~pplies the
a value. Here we define state transformer q x to state s'.
'vVe also define operations specific to rhe monad. In this case, there is an
... .instanc~ Monad Exc where
operation to increment the stare:
.r.~turn. x = Recurn.x . .. .. '"'--
(Raise e) 1> q = Raise e tit;k ;: Sc 0
(Return x) 1> q . = qx .. ~
-- tick = MkSt f :where f s,; ((), s + l)
. The call return x simply remrns the value x. The call p 1> q examines the result ,To add executio n COUntS, ~ve.take the monadic evaluator as above, and just add
of the computation p; if it is an oxception, it 'is reraised; otherwise the function a call to tick at the right point. Rather than re\rrite the program from scratch,
q iS applied to the value returned. '(It ls a good exercise to check the types.} we onlyhav e to make a small, local change. Here is t~e result
We also define oper~rions specific to the monad. In tltis case, there is an
operatio n to 'raise an exception:
eva1St .. Term .- St Jnt
I : eva/St (Con x) - renzrnx
i' . raise .. Exception :- Exc ex eva/St (Div t u) - do x - evalSt u
raise e = Raise e y - evalSt t . :
tick
To add error handling, we take the monadic evaluator as above, and just replace retun:1 (X div y)
the term return
. (x div y) by a conditio
. nal expression: Finally, in the output monad Due tx, a computation consists of the generated
eva/Ex Term - xc Int ~
output paired with the final value. The instance declaration for Ouf ex is

eva/Ex (Con x) . - renrrn X
' ' I

instance Monad Out where


evalEx (Div t u) = do x .- eva/ t
returnx = MkOut ("'_',x) .
y- eva/ u
p 1> q - MkOut (ox* oy,y)
if y :: 0 .. ..
.. where M}<Out (ox, x) - p.
then raise "division by zero" ..
. .. '. . z.itkOuc (oy, y) - qx
else return (x div y)
The call return x returns empty output paired with x. The call p 1> q exrracrs
Rathert han rewrite the program from s~rat~h. .we onlY had to makE! a
..
..
'
an output ox and value x from computation p, then extracts an output oy and
.chan~e to the code. .. value y from compma tion q x, and returns the output formed by concatenating
. Next, in the. state monad, a .computation qCCepts an initial state and . ox and oy, paired with the value y.
a .value paired with the final state. The ins tance declaration for St ex is . .W_e also define operations specific to the monad. In this case, tl!ere is an
operabori to generate output:
instance Monad St where
return x = .MkSt l where f ~ = (x, s) oLit Ou_tpuc .:.. Our 0
our ox - lv/kOu.t (ox,())
.. . . pI> q = MkSc f
'' To .add execution traces to the monadic evaluator, we takethe mo.nadic evalu-
where
ator as above,
. and just decorate it with calls to generate output:
'
I fs = apply (q x) s' . . .
where (x, s') = apply p s
I
; HI

... . evalOut Term - Out Inc
eva lOut (Con x) = do out( line (Con x) x)
The call return x returns the state transform er that' yields valve x and leaves , return x
the state unchanged. The call p 1> q applies the state transformer p to
. ...
. '
., ~
'\ ..

342 . 1d.3 I Monad la1\;s 313..."


.. . :. -.;~ . 'ii .t.'
: ._. ' .; .

..
, .
.. e.v.aiOut (Div t u) .= do x - evalQut t . (Con G)'( Con 3)) Couni)
. . .. ,
(Div (Div Courit)
. ?-ival(Dtv .
'y - evalt;Jut u 1
.. out (line (Div t u) (x div y))
return (x div y) The answer here.is 1. bec(!use Jhe fiist instance of Count evaluates to 1 (since
the. division of 6 by 3 is :ije:ffotmed earlier) ru1d the sewnd instm1ce returns.
. To get th~ output ill the reverse order, all that is required is to change' 2 (since the divisions of 6 by 3 and 2 by 1 are performed earlier). Define a
definil'ion of i>, replacing ox * *
oy by oy ox. This is even siinpler thrui' cotrespondii1g cou.lit 'openitioii 0n tQ.e type 'St to facilitat~ the ~edification. . .
change required in the previous version of the program. .
10.2.4. Modify the evalua~qr \'\lith. output so .that it only tr4c;es selected parts of
Tne lesson to be learned from these examples is that a monadic style of
the computation. More specifically, extend the type Term ~ith two extr,a terms,
prograihming is highly suitable V.:hen the progran1 under constructiori inay re-
r~aceTerm and Unlrace Tem1. Tracing should be. turned on for all subter~ns
quire modification due tci cha;1ges in sp~cification. A~y changes are loci:llised .
sun'oundeci by Trace and turned off for all subterms surrounded by U11trace.
in the definition of the monad, and at one or two places in the prograni.. There .
To support this chm1ge, a computation should be represented by a function,
is no need for a major restructuring of the progrrun with every added bell and
the argwuent of which is a boolean that irictkates whether tracing is on. Define
whistle. ln Sectionl0.4 we return to the evalualors, and tackle the questi9n of
suitable operations on computations to set and access the tracing status.
how different features can be combined..
.' ;
Exercises 10.3 Mop.ad laws
10.2~1 Modify the evaluator with excep~ions .to specify an
alternative term to.
. .
We.have now seen a number of . i!lstanc~s of the classMonad, inCluding IO; Iq,
evaluate ill case of an exception. l.\Iore specifically, extend the t)'pe Tet:Jn to .Exc, si, and but.. 1n each cas'e,:ttie .operations return and I> have: 'satisf{a to . '
include a new term Try term Term. To evalua.te Try t u, first ev~luate t an~l, if it number of laws. In tbis section we will sta~e the monad laws in a number of
succeeds, return its value; but if evahiation raises an exception, then evaluate different but equivalent ways. First, recall the types of return an~ r>:
u. Here's a transcript of how the program should behave: ' ..
retur.n .. ()( - . m ex
? eva[ (Try (Div ( Conl) (Coli 0)) (Con 4~)). . (1>) .. m()(-(a-.m~)~m/3
42
The first 'law stat~FS tli~n return js a right unit of r>:
Define a corresponding try operation on th~. type Exc to facilitat'e the mc1UUF
..
. ..
. cation. .. :
' ' ' I
p I> return = p ..
10.2.2 I~ tl1e evah~ator that c~urits the number ~f division; the use ofstate
The second law states .that retu~n is a 'left unit' of 1> in the following sense:
is soni~what hea'l)'hailded. Instead. of keeping tratk of a current stat~. each
computation can simply retw:n a value paired with the number of operations . (return e') 1> q = qe
reqUired to compute it: . . . . ' . ' .
The third law states that r>is 'associative' in the following"sense:
data Count()( = (()(,Counter)
. . = . Jnt
type Counter
' ' . .(p 1> .q). 1> r = p r>..s where s x = (q x r> r)
' .. . . ..

Modify the ealuator to use this new computation type. We have already encountered many exrunples of operations with type ()( '- ex -
10.2;3 Modify the evaluator with state to be able to access the state in a corripu" ()( that have a left and right unit and are associative; algebt;aists call these mon-
tation {so the s,\iortcut of the previous exercise' won't. work). Mor~ specifically, oids, A.s we have introctticect them; monads differ from monoids in that, instead
extend the lype Term to-inclt,tde a new tenb.Count. The value of Count is th~ of an operation with. type ()(.- '()( - d for appropriate ()(, w~ have a binding op:
number of operations performed so fru, a qtim1.tity that is retrieved by accessing eration. . However, as we will see
below, . 1> can also be cle,fined in tenus of a
the state. Here's a trai1script of how the program should behave: monoid operation. Category theorists are infamous for stealli1g terms from
'. ,' .
. .:
' . ',,
'' .
34.4 io.3 I
...-....
... -~~;'"-: ..
Monad laws 345 .
..,.,. ..... t _-

philosophy, sia.rriilg with the theft of category itseJf fr~nrK~t. The abdluction Mkout <ox it o)i, y>
of monad from Leibniz was aided and abetted by rhe pun on monoid. . where MkOur (ox, x) - p t> q.
For each of the monads .we have considered, it is easy to prove that the' MkOut (oy, y) = rx
monad laws hold. The left unit law for the exception monacfis immediate
= {definition of 1>}
the definition of 1>. Here is a proof of the right unit law for the state uilJH<l.u.:~
Recall. that..
. -. .
. ..
- MkOut (ox * oy,y) . ..
instance Monad St where
.. where MkOu-r (ox, x) = MkOut (ou ov', v)
where MkOut (ou, u) . =
* p
return x = MkSt f where f s = (x,'s) ' .
. MkOut (ov, v) = qu

p 1>
.. .. ..
q - .MkSt {
.. ' . MkOuc (oy, y) - rx
(simplification)
where
f s = apply (q x) s' MkOuc ((ou ov) oy,y) * *
where (x. s') = apply p s where NlkOut (ou, u) = p
MkOLlt(ov,v) .= qu ,

apply ::
' ..
St ex- Stare - (Oi, State)
.MkOut (qy1 y ) . =
\.. + l . . '
;v
apply (MkSt /') s = {s Similarly, we simplii'y the\lght-hand side:
In the proof, we usc a fmm o'r extensionality: p = q if apply p s = ap!'ly q s p t> s where s x = q x t> r
all states s: ~ - {definition of 1> , twice}
apply (p 1> return) s MkOut (ou * (ov * oy),y) .
{definition of 1> (in the state monad) anct apply} where MkOut (ou, u) = p
~pp/y ( retur11 X) s'.whe~e (X, s') = apply p S' Mkbut (ov, v) qu
=
= rv
{definition of return and apply)
: ..MkOut.(oy, y)
... ''.. .. ~: .. : : ...... '; . ,; .. ...
. ~

(x, s') where (x, .s') = apply p s The result then follows from the associativity of H. Furthermore, the left and
(simplification} right unit laws for the output monad follow from the left and right uriit laws
*
I

' . for respectively.


appiy ps

Here is a proof of the associatii.e law for the ourpu t mona~.' Recall thar
10.3.1 Laws of do notation.
J 'I' ,':
. .. .
, i:l I . ins tance Monad Out where
. :'.I'
~
,, .
:. !
rerum x - MkOut (" ", x)
~ ....
We can also state the laws in tet:ms of do notation. They read:
1j. I ~ .
;! p t>q MkOut(ox*oy,y)
' j~
~l
..,.. . ..
' :
I
~ where MkOut (ox, x) - p .' do {B; x- p; return xl = do {B; pJ , . .
'I'
t. .' . J"lkOut (oy,y) - qx do (B; x- return e; C; r} = do (B; C[x :=e); r[x := e]l
~ !! ; '
=
,I': , ,' do {B; x- do {C; p]; D; r} = do {B; C; x- D; r] p;
..IJ' j' ,. '" j.lI First, we simpliJy the left-hand side: . '
;i;~ .:..:l ;i' '
:'1
'>
t Here, B. C,D range over sequences of commaJ1ds and C[x := e] means the
(p I> q) I> r
sequence C \vith all free occurrences of x replaced by e. We \villleave as an ex-
'. (definition of 1> in the output monad) ercise the proofs that these three laws are equivalent ro the ones stated earlier.
. ... .
. .
346 I Moi1ad Jaws 'I - 0 : :
347
. .
There is' also one. additional tule, called the collapse law, w4Jch is :a . Note .<:;arefully.that th.e prop{ works in any monad, provided the pi:ograril .. '

sei:tu~nce of the defii~ition of do notation:. . . . .. as above. In Section ib.2, we.modified the progra.tu by adding calls to tick
the case of. the state ~onad. However, associativity still holds; as can be
do {C; do {D; r}} do {C; D; r} demonstrated using the'.. ,,laW
. ... . .. :-
=
.

..To d~onstrate
. these
. ver~ions
. .
.
of. the monad
. . iaws,. . . a.'variari(of
- c~i1sider .. . . . do {tick; x- p; return. ..xl...=
~ . ..
do {x - p; lick; retUrn x}
e~aluator of the previq!ls section, based.on addition rather than division: ' '

This law holds provided tick is the only action on state within m. Similarly, in
data Term - Cofl Int I Add Term Term
. the case of the output monad, we modi'l'ied the prograrti by adding calls to line.
evat .. Monad m ~ Term - mInt . In this case, the .two terms .are no
longer equivalent, because the traces will be
eval (Con x) - return x ctifferent. Of course, tlie two computations will still yield the same final value.
eval (Add t u) - do {x- eva/ t; y- eva/ u'; return (x +'y)} ,'

The aim is to show that 10.3.2 Laws of monad composition


. evaluatiph of.
Perhaps the best way to remember the monad iaws is to restate them in terms
Add t (Addu v.) and Add (Add t u) v
.' . .. ~
....,. of a monad compositfon opera~or. The operator ( <> ). defined by is
both compute the same result. First, we simplify the left term:
. . (<>) (ex .-;;. t:J1/3) -:.<!3- my)- (ex - my) .
eval (Add t (Add u v)) (f <> g)x - {x.t>g
.(definition of eval} Equivalently, -using
. . a section,
..
do {x- eva/ t; w- eval (Addu v); return (x + w)} ' '
t <> g = (t> g). f
.. {definition of .eval} . ' . .:
,' .
..
dox- evalc . . . , ., The operator ( o) is l.ik..e functron composition .(), except thar the corripo.iJ.~~t
. . .
w ...:: do {y - eval u; z - eva/ v; return (y + z) }; functions each have type ~ .:.. m {3 for appropriate a and {3, and the order in
retuln(x + w) which functions are composed is ~eversed. lri fact, ( o) can be used to define.r>:
{associative law} (t> g) = id 0 {i
do x - eval't . ' . ., : '
y - evaf u . Note also that ( o) and (.',)aterela,ted by the useful law
z- evalv ({ <> g) . h = (f . h) 0 g.
iv- return (y + z)
return (x + w) .' The proof follows irnnkdiately from the definition of ( o ). We will refer to this
{left unit law} law. as the leapfrog law. . . . . '
Now, reformulated, the first 11-vo monad laws state that return is a left and
do {x - eval t; y - eva/ u; z ..:. eva/ v; return (x + (y + z))l
right unit of ( o ):
. .. ..
.. ~ .: . : . ' . ., .
Simplification of the; right term is similar: . .
. p o return = p .arid return. o q = C/
' , ' ~
. . .,...... . .
eval.(Add (Add t u) v)
. ' .; .
~ ~
And, reformulated, th\,!. third law states that ( 6 ). is associative:
{as before} ' .

-do .{x ~ evalt; y- evalu; z- eva/ v.; return ((x + y) + z}} <r o g) o h := r o <g <> n> -
). . '

The resi.U.t f<;Jllows by the associativity of addition. Proof of the equivalence Qf the two sets of laws is lef.t as an exercise.
. . .: ,. " .: ' . .
.'
' ,
.... .
..
... . .,
349
~;

348 /Monad Jaws


'~ :'
, .
. So ~ mona~ is, after all, a monoid. Ahho~gh _the..ITJ.dn~d- ~aws .are e (id o fd) ps . .
' t; '.: ~ .. !- 1 1 ..

to state in terms of (o), monadic program!! arc easier to stare in terms of


notation, which is based on C>. . . .
'HeJGCe concatm = id o id. The first id has type id :: m (m.~) - .m (m'oc'), whlle
- - ..J '.. ... -.....
- . second id has rype id :: m oc - m ex.
-
10;3.3. Map and concat
( . .... -
~
There are seven laws that characterise mapm and concatm, all of which have
... , .. fillniliar ring:
There is y'e t another, and very revealing, way we cim des~ribe the mapm id = id
laws of a monad. First of all, consider the following deJininons: mapm (f g) = mapm f mapm g
mapm .. Monad m => (oc- {)) - (m 'oc- m /3)
- do {x- p; return ({ x)} mapm f return = return f
-
mapmfp
mapm f .concarm concatm rri'apm (mapm f)
.... Mona4 m => m (m oc) - m oc
-
, : concatm
i: concatm retur:n id
- do {p - ps; p}
-
concatm ps
'I
I: , concatm mapm return id
=
' ! ..

The f.uncrion mapm applies a 'fUJi.ction to the result yielded by a coinputattio!li


' : l .
concatm mapm concatm concatm concatm

as
' ' '

To comimte mapm f p, first computep, bind X to the res)llt, 'and then r e t!IIrn
f x: Jn .the defi.illtiOll of COncCltm' ps, ~h~ variable ps 'deribtes Cj.
, I ' ' I ' ' ' ' '' ' I
The 'first two laws stat~ thatmapm is a functor, just ~ap over lists is a
a
' U\<JiUIJ.LE

' ' that, when performed, itself yi.elds computation. Thus, concatm flattens functor (see Section 4.3).. The third and fourth laws are naturality conditions
ll).indboggUng double layer of computation into a run:of-the-mill'single Javrr-i on return and concatm, just as the laws
of'computation. ... ..
map f wrap = wrap .. f
. We can also express mapm and concatin using the monad composition on-~J\\ map f concat - concat map (map f)_
crator o: First, we have
. .. - ...
: are naturality conditions on the Jist-processing functions Wrtlp 'COncat and
mapmf p (again, see Sect!on 4}). ~1d the final three laws are generalisations of sim-
- {definition} . ilar laws for wrap and concat.
... . These. seven laws are equivalent to the three monad laws. For example, we
do {x - p; return ({ x)}
{tr<U)slating do notation into C>}
.... . will prove die law

p C> (return f) . . mapm f concatm - concatm mapm (mapm f)


= {definition of o, using the identity functionid} .
We will n~ed rhe fact.tpat
(id o (return f)) p
(return h) 'o g - gh
Hence mapm f = id o (return f). Second, . ' ... . .
. The proof is
.. i . '1 '' : '

concatm ps .. . . ' . ,'..,. ..,. .' ..,..


~

. ...... _ . ' .
= {dcrlnition} . . ,., .. (return h) og
do {p- ps; p} - {leapfrog law- (f h) o g = (f og) h)
., '
= {translating do notation into C> J (return o g) h

ps C> id = {left unit}


'
{definition of o} gh
''' '
' .-
.:_1 . ..
. -
; ~

- . .
350 0.4 I Con;biningmonad; .... . .. .: , ;
.. ~.;,:.; : ..' ' , ...... . .. .
, ,~ ~

For tbe main p.roof;~e simplif~ .the left-hand side":


' '

.. outputmoiiad
. fs.a .speciar
..... case of tllis monad, .as is the counting monad
." . .: .. ' ' .
i.ril~.llat hi Exercise 10:2.2.
mapm f con~atm .
10.3.3 Prove the law.concatm . mapm concatm = (;oncal'm concatm.
= {de{in.itions of mapm and concatm ill terms of ( 0 n . . ' ,. ,...
'

(id <><return tn (id <> idl


10.4 Combining monads
{leapfrog}
(id o id) o (return f) sometimes ~e want to combine .niopads._For inst;;mce, we m?Y wanr to mo~ify
the evaluator of Sectionio.2 t9. use both exception handling and $tate: One
Similarly, we simplify the right-hand side:
possibility is to construct yet another monad, combining:aspects of both ex-
concatm mapm (mapm f) ceptions and state. But it would be preferable if, having separately done the . '
=
' ... .
{definitions of mapm and concatm in terms of ( o)} work to define exception and state monads, we could combine them simply in
some way. . .,.
(id o id). (ld o (return (id o (rewm {))))
It would be delightful if there were a singh~. uniform rule thatcould be .
(leapfrog) to
used combine any two monads. Unfortunat.ely, no such rule eXists: Indeed,.
(fd o (ret~;n. (id o(retum : f)))) o .id . as .we \~n see, there aresometii'r{es tW'o distinct ways in 1Nh.ict{ rw.q.:monads
- (associativily} can be combined. . However,)tis 4sually possible to define a uniform rule for
.' combinin'g one monad \vith anori1er.. The basic idea is to define. ari opera!ion .'
id <> ( retu ~n . (id <> (return f))) o id .. '
T, tci.ki.ng type construCtOr.S intO type COnstructors, such that if m is a monad,
' '
= {above, and id h = h} tl-ien T m is also a mo~ad. Such.an operation is called a monad transformer.
o(id <>(rerum{)) Each operation to b_e defi.ried Will be used in several different ~onacls, so we
+

id
form a lype class for ~ad1 oper~'tion, Recall that we already have a t}-pe i:>l~.ss
Tl1e two results are the sci.me since .o is assodative. We will leave the for the lwo basic monad operations:
. -'proOfs to.the ~Uigeni .reader.
,
. . . -. class Monad m where
return .. lX - m lX
10.3.4 Sunu:llary
' .'.
(1>) :: . m lX ...... (lX ~ m /3)- ni/3
We have now 'seem four different ways of expressing the laws of a mo~ad.
By definition, ali exc.eptibn rrf~ncid is one 'l'.'i.th an operation to raise an exception: '
. has itS advantages. :fhe laws of I>, and its equivalent in terms Of do UOt!l.iioq, ..
' . . most useful when reasoning about programs wri~ten in do no.tation. T-!J.e la class Monad m ~ ExMonacf m where ...,
of ( 0) are the suhplest to remember, and show that monads are examples raise :: Exception -: m lX
monoids. The laws of mapm and concatm;.which arethe way category theoris
introduce monads; are the most revealing in'that they suggest ~at monads may Similarly,
. . . a state
. monad is one
"
with an operation to increment the state:
. . '. \

befound in aU kiiids of places.- . class Monad m => Stlvfondd 'm where


. . . ,.
. . .. .". . tick :: m 0 ..... ..::. . .. ,. .
an appropriate value:
;!. ' ~.

EXercises
Finally, a show moilad is Qiie~vitli an operation to display
10.3,1 Writing List ex fod X), .install _Li~t as a member of Monad., .... . .
class Monad i'n => Show/;,[onad m where
be
10.3.2 Let M a mohoid with unH e and operation ED.[n~tall .Mon as amember showMonad .: :: m St1:!11g .<..+ String
of (>'Ionad, where
Whereas the usual Show c,lass:htkes a type as its argument, tllis version takes. ,
data Mon lX - MkMon (M,lX) a type constructor.
':
. .
'
.. .. ..
.. ~ '' . .
1'
PAGES MISSING
sorry:-(
.
- -.
.. . ) .
354 . fa/. Monad~ 10.4 I Combilling monads ..
~ ...,.i
, ,
.355.
,+ .; ,. :. ' ,

'Mkixc (reco~eF ):it> rei~rn> . . - ' 1,.-


10:4.2 Comb in.iPg state .: -~ . _
!
..
... . ., r

= {right unitlaw for monad m} . .


Our secon d monad transfo rn'ler combines an arbitrar.y monad m with the state
MkEXC (recover p) monad:
= {definition of recover)_ .. -
newty pe SIT m Cl "" . MkSTT (State~- m (Cl, Stare) ),
- -. type State
' .
p -. ' ' = Int

The other two proofs are similar. . . . Note this foUows a slightly different patter n than the previo us deftcit ion. The
We have :now installed f!,.YC"' as ~monad, and the next step 1s to mst(lll EXC .. underlying monad m is \vrapped arotind the pair formed from the value and
'as a mo~ad trar1sformer: the final state. Compare this with other possib le variations, sticK asm .(State .:..
(Cl, Stare) ) or State - (m oc, State) . Agam, this. definition is chose n' Ge~aus
. instan ce Transforme r EXC where e it.....
promoteg = MkEXC (do tx- g; retu rn (Return x)})
. works.. 'It appears impossible to .write a suitable definition' 1> for other . . of the
variants.
~his is similar.~0 t11e definition of return on Exc, with an added bind and return . We need an auxiliary functi on to apply a compu tation to an iJutial state: .
.' . . . ,. . . . . .
on m to get the types right.
,. ' . ' .
. . ..
The mo~adEXC m is_an exception monad for ~Y monad m: apply :: SIT m Cl - Stale - m (Cl, State)
apply .(MkSTT f) .= f
instan ce Monad m => ExMonad (E..'(( m)wh ere
The next step is to install SIT m <\$ a monad, using the assum ption that m is a
r~ise e = MkEXC (return (Raise e.))
i:nonad:
The m~nad EX~ m is .a state monad, when~ v~r m is a state monad: . .
instance Monad m ~ Ji,fona{i (STT m). where
instm ce' StMonad m => StJ'4onad (EXC m) where return x - MkS[ r {' ~here f = return (x,. s) s
pr>q =~f .
tick =: promote tick
where. . .
Here tick in the monad EXC m (on the left) is defined in terms of tick in the fs = do (x,s') -appl yp s
. . ..
monad m (on the right). . apply {q x) s'
The. monad XC m is a show monad, w~enever 11] is a show n:onad:
Again it is useful to check'the types, a task we leave as an exerds e. . .

instance ShowMonad m => ShowMonad (EXC m) where .- It is also nccess ~ry to show that if return arid 1> in the underl ying. monad
sho\vMonad p = showMonad (recover P t> q) m satisfy the three monad laws, then so do r~rurn and t> In the new monad
where S'IT m. Here is the proof of the right unit law:
. . q (Raise e) = rewrn ("exception: "*.e)
apply (pI> retum)"s . . "
q (Return cs) - retur~ cs
= {definition of r> for monad SIT m}
..
On the left. showMonad :: EXC m String - StrinfJ. On the right, showMonad ::
do {(x .f)- applY in; 'apply (ret;lrn x) s'}
m sti'ing ..,.'String. We can ~se showMonad to install EXC m _Cl as a memb er ' = {definition of''return and apply}
Show:
. . . do {(x, s')- apply ps; retUrn (x,s' )J
..
instan ce .(ShowJvfonad m, Show Cl) '=> Show (Exc m Cl) where .
{right unit law for mon,ad m} '.1
show I '
showMonad . mapMonad show
;=
. apply ps . .'
The runctio n mapMonadis as defined in Section 10.3.. where it W!).S called
. .
.'
I :
I
'!'
..
. .... ... . 359 .
358 . '. iol Monat!$ 1o.s I Clwpter . . notes ..
. .... ...
. . ...
~
' " .'.
.. ' .~ . ..
We have : -: . ~ .. ~
10.4.3 The function promo(e'.should be a moiJad rirorpllism, in that it should
preserve. the rn(in~d st~~hire~- . .
? eva1Stx wrong - . .. :-

exception: division by zero promote (.return x) = retum x


p~omote (p 1> qf ;,:. .(promote p) 1> (promote q)

on
~

-? evalExSt wrong ,
value: exception: division by zero, count: 1 Here, return and 'I> ~the h~f~ ..ill'e in t11e: monad m, and on t~e right are in .
the monad T m. Show that the promote operations defined on ST and EXC are
. In the fir~t case, evaluation yielded the computation indeed monad morphisms .
..
MkSIT f where f s "' MkEXC (Mkfd (Raise wdivide by 'zero"))
10.5 Chapter notes '.
indicating only that an error occw-ied, 'wberea~ in the second case, ~valuation
yielded the computation Moggi(l989,.1991) iri'troduced monads to computing science as a way of stmc-
turing denotational semantics. Independently, .Spivey (1990) 'noted that m.on
MkEXC (MkSIT f) where f s = (Mkfd (Raise. ."divide by zero") s + 1) . .ads provideq a useful W?Y of s'tructuring exception handli.ng in ftmctlona~ pro-
ifidicaUng that one
tlck was counted before the exception was raised. . . grams. Subsequently, Waqler (1990a, 1995) proposed monads as a general ~ech
.The seconP. of the.se two combinations corresponds moie closely to the way nj.que for structuring fw1ctional programs. . .
state is normal~y implemented, n~ely with a global variable... With global a Monads are used to sm1ct(.ire 'the Glasgow Haskell compiler, ">;Vhich itself :
variable, the value .of the state can 'always be recovered. from the variable, even is written in Haskell;
' - -. Hall, Hammond, Partain, .Jones,. and Wadler (1992)~
see .

after an exception israised. 'The first combination is ak)n t9 the case vyhere rais Each phase of the compiler uses a monad for bookkeeping information. For
ing an exception causes a state to be 'rolled back' to its value at the point y.rhere instance, the type checkeruses a monad that combines state (to maintain a
the ex!=eption h<l?9Jer is inv~ked, and can be considerably more expensive .to ' cwrent substitution},' a name supply (for fresh rype variable names), and ex-
... . .. . ceptions. Monads for interaGtion 'have been extended to include concimency;
implement.. . . . .. . .
. see Jones, Gordon; and Finne (1996). Monad nansformers are discussed in
}

The moral is d~ar: complex features may interact in complex ways. There is
no fixed rule for combining tnonads because there is no fixed rule for combining Uang, Hudak, and Jones (1995).
features. But mo_nads do offer some help in structuring this complexity, ~s here, The program for the game of Hangman was adapted from a similar program
.. where they-reveal two alternative ways of combining state with exceptions. in Hutton and Meijer (1996). . . .
.. .. ' . . . The special cto notation was s:uggested by Launchbury (1993) and was first .
.
implemented by Jones (1993)in a version of Gofer. Subseq~ently, it was adop .
Exercises
ted in Haskell.
10.4.l A ~an~former OUT that.adds output to a:given mon~d is given by
data OUT: m o: = m (ex, Output) . ~ .....
! ' ... . ' ' '

Define swtable instances of the classes Moriad, ShowMonad, and Transformer, .


,: ' ' ; , I '

. ...
.and define_ a class .O~tMonac,l with.a suitable instance. Also, defme in:itances to .. . ,, .' '

ensttre that if m is an exception o~ state monad .then s.o is our m,' and that if
)'_' ,

,. . . .-
m is an O'Utput m9nad then so are ST m and EXC in.
aq
+,

. : 10~4.2. Build evah.l(ltor that uses both ~Cand OUT (fromExerdse 10.4.1), .. . ..
an~ show that the two ways of composing the transformers yield .diff~rent res :
ults. Which composition corresponds best to the usual implementation of out
put? Repeat for ST and OUT.

.. .. .
'~ ' :. ~ 'I: ' ,

' ' ' . ;. .,..


'

. : ;.~.:... . .
:; ~:-:.. ~ ::~. .
chapterll, ' .. .' ' .
.. . .
.' I " ,

.., '. ~ . :. ... ..'..-.' . '


......... \ ' :. ' ' . '
' '
'' . : ' . . ..
' ' ~ .
:~' . . . '

. . ... . . ..' -. ' '


. .'. ~

:
..... . . . ;

- -....-.
.. - .Parsing '

... .. - ..'
. ;.. . . .
. . '
'
.
..
-
-. .. .. .. .
, .. ".:.:

. ' ' .. .

A parser is a program that aricilyses a piece of text to determine its logical struc-
ture. For example, the text may describe an arithmetic expression, a computer
' . pi-oi,-am, or a da~al:i~se of informatlo~. . The output a .parser is usually a of
tree ofsoine klnd; for instance, a parser for arithmetic expressions might re-
.' till:na nee \\ith coristiuifs in the leaves, and operators at internal nodes. In
this chapter we
will des'cribe a monadic approach to designmg parsers. The
material will
be used in the following..chaprer.
' .
.' ,, . ... .
. .. .. 11.1 Seq1,1encing . .:. ... ' .....
. ' ' , . . . . .
' .' ', ' ' .
" . ' '

'' Let us start by thihking 'of a parser as a fimction that takes a strfug as input
", .. ' . and returns a tree as ourput
. ..-.
.,
newrype Parser "" MkP (Str_ing - Tree)
'
'. The type Parser is declared as a-new type, dist~ct from but isomorphic to the
\ffiderlying type of.......
flmc!ions
. . ..
from strings to trees. . . . .
What i$ imidequate 'about this definition is that it provides no obvious way
~- -

for sequencing parsers. For instance, .i n a parser for arithme.ric expressions


one may want to look for, in Sequence, a numeral, an operatdr, and another
' - .. . .. "' numeral. The first pa:rser for a numeral. will consume some initial portion of
an
~ ..
.
: ! :.
. ,~
l the inputstring,_the parser for op~rator some inore of the input, and the
second parser.for a numeral the remaining porlion. H follows that a better idea
' ., .
'- .
::
'
is to refine the type Parser to return the unconsumed suffi.x of the input string
as part of the result:
.'

''I'' .
.. newtype Parser - MkP (String - (Tree, String))
.. . .
..
'' '' .....
362 .1 / SequenCing
.. , . .. ' . 363
.:
... . .... ' . . . : ... .
Be.fore cqnsidering.h9w to combi~e two parsers in s.equence, let us' .riis
another aspect of parsing. It can happen that a p.arser may fail on some
It. is not a mistake to construct pa:sers that may fail. For example, jn.a
for .aritlunetic expressions, we may want to look for e ither ari operiltoi ----L
or an opening bracket. One or either of these subsidiary parsers will r Pr't<>i,JN ..
fail. More -gen~y, a parser may firid a number of different ways that son1e.
initial portion of the input can be structured as a tree. Failure then co1-re~;po:nds
to the particular case that there are no.parses. In order to handle these v::. oin ~
posslbllitics, we refine the type Parser to return a list of pairs:
..
item .. Parser Char ,
newtype Parser .,; MkP (String - [(Tree, String)])
item = MkP f
Under this scheme a parser fails by returning the empty sequence. By ClCIUlllion, where {[ ] . = (]

a parser is detenninjstic if it retums an empty or slngleton list ln all P.misible f (c: cs.) = [ (c, cs)J
cases. . The parser irem relurn$ the firs~: ~haracter of the. input, and fails if the input is
. The flnal .~efinement comes f:rbni the observation that different parseis exhausted. Thus item plays the same role for parsers as gelChar does for tl~e
likelY. to return. diffcr~nt kinds of trees: To d~al with this poitit, we abstra< . input-output monad of tP,e previous chapter. . ' . :
t:rom a\lY specific datatype Tree and define aParser as ~ element
' ' ' ' . . t'ype '
o(
~
The second basic parser is one that always .(ails: ' .. ,'' ..
..
. new't ype Parser ex = MkP {String - [ (ex, String)]) zero :: Parser ci
zero = MkP f where f s = [ 1
At this point, it begins to look like a parser is equivalent to SIT List, where
is. the s tate transfori)1e-r of the previous chapter, with the 'state being c t ..in< a The parser. is called zero bec.au se it re t1lrns z.ero parses. Also, we have
rather than anLnteget. As in the previous chapter, we define ftmctfoi'i' nnl1tl" a zero r> p .- .:. =? zero ' : ' .
.. for applying a pars.er:. p r> (canst zero) = zero

apply Parser ex - String - [ (ex; String)] . Hence zero is the zero elem~t oJ r> , just as 0 is the zero e~ement of X:
a
.. .
apply (M_kP f) s = fs . To illustra,te the use of _item and zero, here is a parser for recognislng
character that satisfies a given property:
llsing apply, we can define a functio~ applyParse~ 'for rerurn.ing on~ result o
a parse: sat ::
. ....
(Char- Boo/) - Parser Char
sat p = do {c- item; if p c thcq rerum c else zero}
applyParser Parse r ix - Stririg - ex Uslng_ sat we ca:n define a number of other parsers:
applyPa.rser p = (st head . apply p
char Char - Parser ()
lpt; f!mction applyP,at:ser returns the first component of the first element ln a
list of parses.
char x - ic.:.
do... -: . , <== x);
sar r et.urn ()) ..

,:

'!Jslrig apply, we can now ins.tall Parser as an instance of a n'ioiiad: string :: . String - Parser ()
: , , 't
string [] = . .retur1,1 .(.)' .
instanc~ Mona.d Parser wh~re string (x : xs) = . do {char x; string xs; return())
return x = MkP f' where f s = [ (x, s)]
P r> q = : MkP f lower :: Parser Char
where f s = [ (y, s" ) I (x, s' ) -apply p s, (y, s" ) - apply (q x) s' 1 lower = sat isLower .

. ..
... ..
' . ..
. .. ..
364
-
. '. .Jl.2/ Altemation 365
. , ~: ..; :, ...
.... . : . .~:.~~1 '"'J'~
digit .. Parser Int . ., " To illustrate the use of plus, here is a: parser for recogms~g a sequence of
.digit - do {d- sat .isDigit; return (ord d:.... orc,f!O')[ . lower-case letters: . .
- . . . . . . .. . . .. . . .
The parser char.x looks for the specific character x as the. ~-ext item in lowers .. Parser String
input String; while string xs looks for a specific string xs; 'bof}lparsers lowers = do (c- lower; cs -lowers; rerum (c: csH plus return""
0 If successful. The parser lower 1ooks for a lowei.'case letter., and digit looks
for a digit, returning the associated numeric value if successful . .. In order to see how this parser works, suppo~e the ~put is t~e string "Upper".
In this case the parser on the left of plus fails, because 'U' is not a lower~case.
Exercises
... letter. However, the parser on the right succeeds, so

lowers "Upper" = [('"',"Upper")]


11.1.1 Show that the monad laws hold for the monad Parser .
.
11.1.2 Modify applyParser to return a suitable error message on parsers that With input string "sUpper", the left-hand par.ser succeeds, and so does the right-
fail. hand parser. Hence '
1i.1;3 Prove th~H zero is ~the 'z ero element of' o, where o is_,j:he compositi.o n lowers "sUpper" = [ ("s", "Upper), ('"',"sUpper")) .
opdaror
. associated
. with the monad
.'
Parser.
. ' .:~ '
Fi~ally, applied to the input string "isUpper", lowers returns three pars~s:
'

u:1.4 Define a parser Lipper that recognises anuppercas.e letter.


.
. .
. .
11.1.5 Define a parser that recognises an. uppercaseletter folfowed by a lower [("is", "Upper), ("i", "sUppe'r), ('"';"1sUpper".))
case letter. . . . .. . . .
.
. . . '. ...
Each parse in this. list consumes a smaller portion of tl1e input string than its
,

- .. predecessors.
. .
~

.11.2
. . Alternation Normally, we are interested only in that parse which consumes the longesr
.. . .. . . ...' ...."'( . ..,, .. initial portion of the input. One solution is to rettirn only the first parse in
In order w be able to build more .s ophisticated parsers, we need an operator a list of possible results, talqng care to ensure that parses are produced in
for combining alternative parses. One such operator is an appropriate ord~r. ; A superior alternative is to introduce another choice
..- - combir!ator orelse, defined by
(plus) .. Parser a - Parser a - Parser LX
pplus q - MkP f where f s =apply p s * cpv12 q.s (orelse) Parser ex - Parser a - Parser a
The par~er p plus q takes an input string s and returns all 'parses of P. "IJ~J""''..:.: p orelse q - MkP ( .
to s, followed by all parses of q applied to s. where f s = if null ps then apply q s else ps
The operator plus satisfies a number of useful laws. .Firstly, it forms a mnn. ps = apply'p s
: .
oid with zero as the unit .element: In words, p orelse q returns the same parses as p unless p fails, iii which case
zero plus p p . . . .. the parses of q are returned. If p and q are determini~tic parsers, then so is
p plus zero - p . . . ( p orelse q: The operatoi orelse satisfies the same .laws as plus, -as the reader
pplus (qplus r) - . (p plus q) plus r .. .. can check. .
' : . To illustrate the use of orelse, suppose that plus is replaced by orelse in
Secondly, .we have the distributive law .. . the definition of lowers. Then we have
:: ' .
(p plus q) e> r = (p e> r) plus (q c;; 'r)
. .,
... . . .. lowers "is Upper" = [ C'is", "Upper")]
. ..
This. law, like the others, is.an easy consequence of the defi.ni~ions. Only the longest parse is returned, so lowers is a deterministic parser.
. . ..... .... . . .
.
. .
...
.... . .

366
.. 11.3/ Repetiiion
.. ' :-,...
....
.~ ' 367 ..
. .. : . :_... :
.. . .; " ;''
.:._ ~ .. . . :;:" . . . ' . . . : ..i
. . ... .. . . .... ..
, consi der a very .. ExerCises .... ' ... .
.. Use of orelse rathei: tl'lari. plus' requires care. For example 1. .,

simple form of arithm etic expre ssion that consists of eithe r a single digit or
, ,, I ' ''

o 11.2.1 Is the opera tor pius co~utative?


a digit followed by a plus sign followed by anoth er digit. Consi der the-tw
parsers: l1.2.2 . Define~ vari~t of.
lo~e,:~ that pr.odu~es a list of parse s ~ which each .
p~rse consu mes ~.lm,g.cr por twn, of the input string than its.pred ecess ors.
rig,h.t Parser Inc . .
righ( - dig it plus addition . 11.2.3 Sho~ that orels e saiisftes :thc smne foti.r ta\vs as pi~s:
. -.
' '

.:..
wrong Parser Int 11.3 . Repe tition .
wrong - digit orelse addit ion '.

Gener~Using ~o~ tl~e definition of l~wer:s in theorprevio us. sccti~ri. w~ can define
additi on :: Parser Inc
a parse r comb mator tha t repea ts a parse r zero more times:
.. addirion = do {m - digit; char' +'; n ~ digit; return (m + n)}
f!lany . .:: Parse r O< .- Parser [O<] . . . .
Applied to the input st~ing "1 + 2", the parser right yields t\vo parses: many P = do {x- p; ;'!s :""' m any p; return (x .: xs)} or~lse i-etur~ [ j
((1, "+2'!) , (3, "") ) For exam ple, we now have lowers:= many lower. . .
The followin_g _P arser.recognises an i9.entificr, whi_ch by.definiti~ii is a'st~in

H~we ver, ~rong yic.lds only the. first .of these parse s.The pai'se1 digit'succeeds, . of letters and d1g1ts beguming with a: lower-case letter : g
so the parse r addition is no~ invoke.d, .
One way to corre ct w~ong is to rewri te it in the form ident :: Parser String' .

better ::: Parser Int ' '


ident = ~0- {c ~ ~ower.~.. . c/.,. . .~any alphanum; re'turn ( c : cs)}
. '
.: beiter . addit ion orels e digit The definition of alpfra num is left'as an eiercise.
Applieq to the input "1 + 2", the p~ser better yields [ (3, "") ]. What is . Some~es we ~ant to repe~ t a .p arser pone or more times, rathe r than zero
with better ls that it is in~[ficient appli ed to the input "1 ", it parse s.the digit or more. ttmes.. This can. bed on~ I?.Y .a combinator some, defined by
' "" .
fails to find a subse quent plus sign, so the left-h and argument to ~relse l<.lll'
.
some Parse r c:t - Parse r ( 0< J.
::
As a resclt , 'the. input is repar sed from scratc h ~o fin4 a digit. This is. not s somep = ' do
{x '- p; :;_ many p; return (x: xs)) xs
mUCh a prObl em with thiS iittle example, but itWOuld be if digit were u:~na l.<O'-'>
by a parser that recognised a seque nce of. digits. Such a seque nce would For exam ple, here is a parse r for natt,rral numb ers:
parsed again when the left-h and parser failed. .
Th.e best solut ion is to facro r the parse r for digits out of the two coJ:noonent:f.;
nat :: Parser Int
nar retum ((oldl1 (CD) ds)} .
parse rs, writin !( = . do {ds- some digit;
wher e m Ell n = 10 x.m -t n .'
best :: Pwser Int . . .. ~

The parser digit was define d in Secti; n 11.1.


I

best . - do (m.,.. digit; rest m} . ....


restm = do {char '+'; n-digit; return (m + n)} ot:~lse return m . . ~on~i der now how t_o ~~tine ~~p~s~r for an intege r numerai~ which by def-
. '
UUtlon 1s ~ nonempty stnng_ of ~hg1t~ possibly prefixed by a minu s sign. One
:;rhc parse r ha.nclles the res't 'or the input , if any. . It takes an argument '
rest appro ach IS to define . ,.. . ~.. ~.
whose vcilue is .the digit parse d so far. We will retur n. to the subject of eu!''-! t:l''-
int :: Parse r Int ..
jn Sectio n,l l.4\?u t the Jesso n to be learned here is that it is sensible
to fac
parse rs to avoid repea tin.g unnec essar y work. int = do {char '<'r- nat~ return ( -11)} orels c nat
..
0- \" ._

.
' ' .
. .'. .. : ..
PAGES MISSING
sorry:-(
,.
370 ;. ~ ...
11.4 I ffldency 371

Such:a~gramm~ p~~~des a 'nattiral s\ructural descri~_tio.n ' of wh~t.is will find the first factor~ b.ut then go i.ti.to an infinite loop tiying to complt~te the
Each identifier m:this grammar describes a syntactic category, while svrn~)ls remaining parses. The problem is called the leJ't recursion problem and is a
enclosed in quotation marks denote termjnal symbols, symbolsthat "'-'"-'"~r difficulty with aJl .rec~sive par~ers; functional or otheiwise. .
ap~ear in the text. It is implicitly understood in the desc!ipt_ i on that whiite-, The solution is to rewrite' the gramma~ for.. ~pr in the following equivale nt
space is ignored between termin~ symbols where approprfatc. The u'-. ' utU form:
grammar hr expr states 'thatan expression is either an (integer) const~t expr ::= (actol" rest .
else a compound expression consisUng of an opening parenthesis, followed rest addop factor rest nothing
an expression, followed by either a plus or minus sign, foll owed by ~other . . ...
pression, an~ finally .followed by a closing p arenthesis. The grammar uw"""'"'"'.::i The new syntactic category rest handles t!1e rest of an expression, !f 'any, ~d
directly into a parser for expressions: noth~ng denotes the category rtiat. describes the t;mpty sequence of term.ina( .'
symbols. Th.e new parser for expr takes the form
.. expr
expr
.. 'Parser Expr
= token canst orelse
,.

expr . = do {t- f actor; r.esr t}


"
.
do {symbol "("; r - term; .!>ymbol ")"; r ettlrn t} rest t = do {op - 'addop; u - factor; rest (Bin_op 1'. u) l

orelse re(urn t ' .. ' ... ,,
'' ,.
canst - .do {n - int; return (Con n)} ,
. term - do {t- expr; op - addop; u- expr; return (Bil1 opt u')J The parser rest takes ari _argttmer:t corresponding to the expressfon.parse9 so.. :
addop - dQ{zymbol "~'; . ,return Plus} orelse far, and acts as an accum.ulating parameter.
.do {symboi " -"; retUrn Minu~~~
. ~ . ~

...
, :.

. . ' 11.4.2 lmpro~g Iaiiriess


Now suppose we want a parser that also works for e:xpressions that are
'fully pare.nthesfsed. Jn such a case, ( +) and (-) should associate tot~~ left A typical lazy func.tional program from lists to list works by reading its input
expressions. The usual way to express sucl1 a grammar in BNF. is to .write on demand, computing the:'fi'rst part of the output after only a portionof the
input is read. For examp1e; the standard func tions map and fi/~er havnhis
. ~ 0 .. + ' ' ! 0 0 ' M: ,''

expr :::: . expr addop factor I factor


.' behaviour. lt is unreasonable to expect sirlar behaviqurfrom a parser since, ..
I'
factor ::= . c~nst 1 . '(' expr ')' in general, it cannot be knowri that the fuput will .be.parsed. successfully'until .
l
This gra~~m~~ also translate~ directly 'illtQ a parser: all of it is read. However, in some cases one may hope to do b.etter. j.

Consider, for example, the parser many . p, whose . definition


.
was
expr - term orelse factor
term - do [t- expr; op- addop; u- factor; r eturh (Bin opt many p = some p or else return ( ]
- token canst orels e some p = do {x - p; xs- many p; return (x: xs)}
factor
do {symbol"("; e .:. expr; S)'f1!bo( ")"; reCUI?l e) Applying as == many (chC!r 'a') t o the input "aab" gives .the output [ ("aa", ~:b") ].
However, this parser is inefficient - so inefficient, in fact, that i.t fa.l,ls to Under lazy evaluation, ohe might might hope that each letter 'a' in the output . 'i
any result. The p~oi:Hern is that the first action of the parser expr is to inv""'- becomes available after .each corresponding letter in the i nput is processed.
the parser term, .whose firs t action is to 'invoke the parser expr a&aili., ....u ...,.1,.,, After all, as is guaranteed to succeed, producing the longest possible sequence : . I
to an infinite loop. 'furthermore, as we have seen in Section 11.2, it isn t
1
of 'a~s.. But this is .n ot wh.a.t happens: as reads. the entire input before~}' output
to re"'~itc expr as is generated. One can. v.erify tha.t '.
..
expr = (actor orelse e;-<pr apply as .L = .L :
'
apply as ('~': i '>.,.'. = .L
.
oecause the result parses .only a factor, ignoring the rest of the ex~>re:ssi<m.:~.lf .L
_,
apply as ('a' : 'a' : .L) - ..
apply as ('a' : i: 'b.' : .L) ~ = .,
Replacing orelse in the definition of expr by plus doesn't work either: ,the [ ("aa", 'b': .L)] .. -~
I'
.-.

:
.,;

'
'
II
I',I
.. -. ;j
' .
0

..
I
.. .
..
. ..
373
0

I 1.5 I ChaprerrJotes
.
372 11
;,~~ ~- ,, -~; '~:i::~-~~,.~:~: ~ . .. . .. .. . . . ' .
ma};
. <.... \' ! ':
' .
. ' . " .

Only :--vhen th.e letter 'b' is read is the output produce~. Wha'qs wante~ is . The reader ~vmider why a function hrst was defilled,.when it.iS'Clearly
0

way to encode the fact.rhat, for any p, the parser. many p always succeeds. to take l. The.answer hils to do with space effiCiency. We have
of the combinat?r (orce;dcfi.ned by
., the purpose
'is take 1 (r: rs) = r: take Ors
force Parser oc - Parser oc
Although take 0 rs evaluates ro [ ], this evaluation is not performed until the
00

forcep = MkP f
where f cs = (fst (head rs), snd (head rs)) : rail rs value is achlally required. The effect is that a pointer to the remaining results
where rs = apply p cs . rs is retained, thereby causing a potenrial space leak. 13y defining first explicitly,
. the problem. .
we avoid .
Here is the new definition of many with added force:
many p = force (some p orelse return [])
somep .= do '(x - p; xs- manyp; return <x.: xs)} 11.4.1 Prove that p orelse q = limit (p plus 'q).

Now one_ c~. verjfy t)lat with as= many (~har 'a') we have
11.5 Cl;mpter notes
0. applyas J. = (,.L,J.): ..L
a pply' as ('a': J.) = ('a' : J., J.) : J. . for a general introduction to practical parsing techniques, and.theirapplicatlon .
: apply a$ ('a': 'a': .l) = ("a': 'a': J., J.) : l : . in compiler design, con~ult Aho, Sethi, and Ullman (1986). The design of func-
apply as ('a' : 'a': 'b': J.) = .f:C "aa", 'b': J.)] :.. . tiona! parsers has been a favourite application of functional programm.iiJg for
many years, e.g. Burge (1975), Wadler (i985). Modern treatments include Fok-
Otl-ie~ p~rsers can also benefi.t f~om judicious use of {ore ker (1995), Hutton (1992), and Hutton an~l MeUer (1996), on which this t,hapter
~ .
0 . . ~.
is d.osely based.
The converse p~oblem to parsing is pre cry printing, the la}ring our of a struc-
, 0

11.4.3. Limiting the number of results


' . . . - : ~~ . ..:~~ ... .. :
.
rured docum~nt in a~ aesthetically lJieas!n~ manner. See Hughes ~1995) for a
One ~rudal.dif'.(erence betwee~ rhe choice combinators plus and orelse is design for a prcttypr.inting library: . . .
if and q are deterministic, then so is p orelse q, wh.iie .p plus q:iS detenninis
p' .
. - ~~ .

only if either p or q is zero. There is a more general way to limit the number
.. results. Th~ idea is to provide a way of making explicit ~~at ~e are in teres
o~ly ~ the first result returned by certain parsers. The com.bina tor limit
0

defined by . '

limit 00

00Parser oc - Parser oc . .:; . -.'


limit p = M~ (first apply 'p) .. . .
... . .
., . ' .. .. . .. .e
0

0'
'
!' '

, '
.first [a]- [oc] .. 00
. . .. ..... ... ..
. _..,
' - ~
00

first [] - [ ] . ~ . . ..

first ( r : rs) - [r)


.. . .
Now, for deterministic parsers p and q we have
... -
. 'p orelse q = limic (p plus q)
- 0

.'

On the other hand, limit (p plus q) is deterministic ev~n.if pari~ q are not.
~ .. .. ~ . ...
.. .. '
.... -.
.'.
.
.., ,
/ ,f . , >
'.
: 7 .. . ' " :. . . :: .
.. . An autom~tic calculator

The final chapter is devoted to a single programming project: the design and
. . implementa lion of a functional calci.datoi for .doing certain kinds of p~oof au.to~
.
matically. It is based fairly "closely on a theorem prover W.it.ten by M~e Spivey.
Although the calculator provides only a small subset of the facilities one rilight
. want in an automatic proof. assiStant,
. . and is restricti~e in. a numberof 'other
' . .
ways, it ~vill nevertheless be powerful enough to prove many of the .point-free
.

. l
laws described in previous chapte:.rs.. . .
' .
''

.. . .... . . .. . ..
.. 12.1 Basic considerations .. ,

. . 'a ft4'lctiort
' .
ide~ is.to const'rud
'

. The ... . calculate With type


, : ' .
. . . ..
calculate . _::. [La w ~ ; . Ex.pr - Calculation
. .
The first argument to calculate is a list of la';VS that may be appli~d. Each ,law
'
.. has a name <md takes the. forirt of an equation. The second argument 'is .the
starting expression, and the result
. . is. a calculat1on. A calculation consists of a
sequence of s teps; each step is g~nerated by applying the left-hand side of one
of the given laws to the current expr~ssion. The calculation ends when no more .
.. laws can be .applied. The.entire process is automatic, requiring no intervention
on the part of the human theorem prover. Example calculations produced by
ca/culale are given below and in_.Section 12.5. .
Laws, expressions, and c.aicu!ations are each elements of appropriate data
types to be defined in the follo~r1g section. In order to. be able to describe
and print clements of these data types in a readable form . we will need four
......

.... 376 <


; ..~ ... ...
~
12.1 I Basic considerations
~.':;
377
;, ~
..
,. :. rl . .; -..
. The steps of the calculation are displayed in the conventional format; the name
conversion functions:
~ ,..

0 '
- ... \"~t...:.: ..
., , .. . of the law used at' each step is printed in curly brackets betwe'en the two ex-
parseLaw Stri'ng - La\v '
pressions.to which it applies.
parseExpr String - Expr At each step of a calculation some subexpression of the current expression
printExpr Expr - String is marched agrui1st the left-h~d side of some law. The process results in a
printCalc Calculation - String substi_tution for the variables occurring in the law.' For example, in the second
step of the calculation above, the expression
For example, we can use parseLaw. to set up a list of-laws ab~ut pairs:
. ......-F~I.tJf .-.,fs~.9.;.H'9! .:.J:!q.ir..Ch~ k)
pairs ' ,'''I . ' .

= map parselaw [ is successfully matched against the left-hand side of the pair absorption law,
"definition fs t: fst. pair(f, g) "' f" , resulting in a substimtlon in which the variable f of the pair absorption law is
"definition snd: snd. pai r(f, g)= g",, . bound to the expression f fst, variable g is bound tog snd, and 'his bound
"def inition cross: cross(f, g) = pai r (f .fst, g.snd)", to pair (h, k). The result of the step is the instance. 9f tbe right-hand side of
''pair absorption:. pair(f, g).h = pair(f. h, g.h)") the pair absorption law in which each variable is replaced by the expression to
whiCh (t i~'boi.md. No tic~ that, ~thot1gh th~ exi>ressions being manipulated also
Each law consists of a name and an equation. The naine of the law is contain vari~blcs, s:~c~{vai.iables iu:e m)t changed by the.steps of a calculation.
by a colon sign, and the equation consists of two :expressions separa.ted Substitutipns are perfc)rmed OnJY for the variables appear~g in laws.
an equals sign. Expressions are built from constants, like fst. and.. pair~ A crucial aspect in the design of calculate is tharlaws are appliec:l only from
variables,' like f and g. The precise syntax. allowed f~r ~xpresstons ts gwen left to right. This is to prevent calculations from looping. lf laws could be
the fo Uowi.Iig section. ...,:.;;;.~l!ffl< applied in both directions, then an automatic calculator could always oscillate
Using parseExpr and printCa/c, we can define a command simplify that by applying a law in on e direction and then immediat!:!ly applying it .in the
ries out a calculation: . .- . reverse direction. A related ar.gument holds for a law such as
,
.. [Law] - string - IO 0
,. -
.:r . ..
simplify
simp_lify laws = putStr . printCalc calculate laws parse.Ex.pr
. .: .. This is the definition of iterate expressed in point-free form. The appearance
The command simplify uses parseExpr to interpret th!'! given stri?g as an of.t!le term iterate f on both sides of the law means that it is possible for an
pression, then uses caln 1late to prod,uce a calculation, 'then uses p~intCalc 'Xi!f~~~1 . automatic calculamr to apply the law infinitely often, and
so never reach a
~ .. ,' .. .. . turn the result into a string, and finaily causes the string to be prmt~d. .. conclusion.
~xample,
~.

'
Sometimes we do want w apply lawsin both directions, and sometimes we
. . .use' qf..laws like ttwr of iterate. Potential infinite loops are
do wain to...make
?: simp.l i f y pairs "cross(f, g).pair(h, k~ : .
'

avoided either by phrasing a law in a more generalised form than necessary, or


by prioritising the application of laws in some way:
cross(f, g) .pai r (h, k) ..
{defi nition cross} ..._. ~.

pair(f.fst:', g.snd).pair(h , k) 12.1.1 Proofs


{pair absorption}
..
= Sometimes we want to prove equations rather than just ca'tcu.late' alternative
pai r(f. fs'I;,.P<;Iir (h, k), g.,snd.pai r~h.
{definition f st} "'"" forms for expressions. one method is toconsider .each sicie_ of the equation
=
pair(f. h, g.snd.pair(h, k)) separately and to simplify them to the same result The two calculations can
{defi ni tion snd} then be pasted together by reversing the steps of the second one. To illustrate,
pai r(f. h, _g.k) ,,_..,.,,.... suppose we set up the following list of laws:
. . .. . ..
... -
.
'
. ..
,. .. . ~ ..
378 12 I An automafic. ca~cu 2.1 I Basic consideracioris . . 379
.' ' . ,._,

i avis = fi lte i-s -++' ifs ++ others.. , . ' ~ . . ,


. ' con cat ,map(map.'f ) .map(box(p. f))
.{con.c at natural} _' : ~ ...
. . .
map f.concat .map(box( p. f))
f i lters
{definition f i lte r} ,.
. = map parsel aw [
"definition f ilter : fi 1 t e r p. = con cat . map(box p)", map f. fi lter(p . f )
"definition box: bo~ P = if(p, wrap, ni l ) "]
,.,AtUilJu~;u the calculatfon.iS laid Ot,lt as a single sequence of steps, it proceeds in
ifs two distinct phases. First, the lefthand expression {ill'er p : inap.f is simplified,
: = map parse l aw [ yielding the r'esult concat :::map U( (p {,wrap{, nil)). Second, the righ.thand
"if over composition: if{p. f . g) 'h = i f(p_. h' f . h. g :h) ... . expression map { filter (p f) is simplified, yielding the same result. The two
"compo.si t i on over i f: h i f (p ' f ' g) = 1' f( p ' h ' f ' h . g) " ] parts of the calculation are
then pasted together by reversing the steps of the
second half. The main advant.agc of this scheme is simplicity; we do not h<~-ve
othe'rs ', to inven t another pr~of fotmat, and we do not have to apply. laws from right to
= map parse~aw ( left in order to reach the desired goal.
"nil cons t ant: nil. f = nil",
.map f. . n1' 1 = n1' 1" ,
Ther.e are two obvious disadvantages.. One is s tylis tic, in thatone half of
''ni.l nat ural: .
:'"wrap natu ral: ' map f ' w rap = wrap. f"' the calculation has to be read backwards. The other is that the method may
\ . .,

. fail. u is 110t always the case that an equa:tion hold:s beeause both sides can be
t

"cciricat natural : map f.concat = concat. map(map f ) ";


"map fun<:: t or : map f .map g = map(f. g) "] simplified to the same result (see Exercise 12.1.3).
. ... . The function prove.can be defined as follows:
Given a function prove; described beJow, we have prove [Law ] -String - IO ()
prove laws = putStr p,rii.11Calc proveEqn laws parseEqn .
? prove laws "filter p.map f = map f. fil'ter(p: f)" , .. '
., .
'
'

' ' proveEqn ::[Law] - {Exw. Expr) - Calcularion


fi lter p.map f p roveqn laws (lhs, rhs)
= {defi nition fi lter} = pasre (calculate laws lhs) (ca /culace laws rhs)
... concat .map(box p) .map f .. ...
.
{map f unctor }
;

=
The remaini.ng fw1ctions
concat .'map(box p . f)
= {definiti on box}
..
parseEqn .. Slririg - (Expr, Expr)
. concat.map(if (p, wrap, nil ) . f) paste .. Calculation - Calculat:on ~ Calculaeion
= {if over composition}
concat. map(i f(p . f , wrap . f , ni1.f)) will be defined in the following section. ' .
= {ni l constant}
concat .mapCi f Cp. f, wrap . f, nil)) 1 .
12.1.2 Further consideration s
= {wrap nat ur.a1} ' '
concat.map(if (p.f, map f.wrap, nil)) It is unlikely that any autorrtatic calculator can match the skill of a human one.
= {nil natural}
OVer a range of examples, a humancalculato'r is Likely to find shorter calcu
.concat . map(if(p.f, map f.wrap, map f.nil))
.' ~ations , or calculations involving smaller intermediate expressions, than a ma-
{c'om~osi :i:i on civ~ r 1f}' ' . '
chine could hope to achieve. Unlike a madline, a human calculator will happily
=
cone'at : map(map f ._j f ( p. f' wrap. 'ni 1)) .
apply laws in either direction without falling into a black hole.
= {defi niti on box}
concat.map(map f .box(p. f)) In the scheme of automatic calculation that we are' envisaging, there are
= {map f unctor} only two degrees of freedom: the choice of law to apply; and the choice of

' ,
.. ' ' ! '

- ......
..
380 12 j. An auwmatic
I -

'2.2 I EYpress1ons, laivs, and cal~ulacions 381


. . . ..
.,
~ '. :-: f:'.i ~ :~~ ..:-
subexp~ession to be changed. The first degree. of .freedgpl ~an be reMJIVI'r1 12.1.2 Suggest an appropriate description of a basic la\v.
by the order in which laws are presented to the calcUlator: u two auterer
laws are applicable, then the one earlier in the list can be'cbosen. The .,._,_ uuy
12.1.3 Can the law zipp pair (map{, map g) = m~p (pair (f,.g)) be proved
silnplifying both sides to the'Same result? It can be proved by simplifying
degree of freedom is represented by the orderin which the subexpressions
the expression zipp unzip map (pair({, g)) .in essentially two different ways;
a given expression are presented as candidates:for instcm~es of laws: if
one is to use th e law zipp unzip = id, and the other is to use the definition of
are applicable to two different sub~xessions, then tlie subexpression C01nil1:~~
unzip. Give details.
earlier in the enumeration can'be chosen. Thi~ still~ lea~es open the ........~..U.VJ
whether to give preference to laws or subexpressidns'in proofs. In other 'Wnrrr;~: 12.1.4 The two functor laws for map are important in many proofs. ~Vhich
tsa e,alcularion dominated at each step by .the de.siie to apply ap articular orientation of these laws is likely to be the most useful? Using the zipp law of
or. to change a particular subexpression? . the pwiiouse~ercise, prove zipp pair ( id, map g) "" map. (pair (id, g)). Did
In the main, the focus of a step in a calculation is usually at a yow- proof use the functor laws in the preferr~d direction?
place in the expression, rather than in a law one might want to apply. Howe\,cr 12.1.5 There are many ways ill which the design of the calculator can be im-
certain kinds of law are often applied beriveen the major steps; these are proved. For exmnple, the laws could be read in from oi1e or more files, the idea
that reduce rhe complexity of intermediate expressions. A good exam!)le is of splitting laws into two kinds can be generalised into a more 'abstract notion
law f . id = f (and also id . f = f'). It is wilikely to be !1 mistake to apply rn .....,.
law assoon as the opJ:iortunity arises. Silnilarly, early application .o f la~s
of a proof strategy, and the calctlla~or could be
made interactive. Give a' list
of other features or improvements that you would like to seem an automatic
I . ', '. nii f = ni!and fst pair.(/, g) = f c~ help to~reduce. the sizes of
. I
calculator.

expressions. For the sake of a word, let us call these basic laws. Jt .rh<,,,...,.,"
seems a sensible idea to divide the given list of laws into two k.iilcts, basic
.and others , and to give priority to the basic laws in the steps of a calcul ation. ,..\1-l'ifi.H ~ 12.2 Expressions, laws, and calculations
' 1 1

Bearing this asp~ct in mind, we will change the defjni~ion of s}mplify u"''''
At the heart of the calculator is the datarype Expr of expressions; most of the

-
0.: ci:l lcu late slightly:
components of the calculator are concerned with recognisillg, manipulatil!~, or
$implify laws printing expressipns. In the proposed framework, every expression describes
= pucStr printCalc calculate (basic, others) parseExpr a function. Expressions are built from (function) variables and constants, us
where (basic , otlters) "" partition basicLaw la~s illg 'functional coiilposition as the basic combining form Variables take no
arguments. but constant functions can take any number of arguments, which
The-function partition p partitions the elements of a Ust into 1:\'.'0 sublists, rh <>c:i> themselves are expressions. We therefore will adopt the following definition of
satisfyiitg p and the others. The function basiCLaw.:: Lim.- Boo/ is defined
to .
Expr:
the following section. The type of calculate is changed'
.. data Expr
calculate :: ([Law ], [Law] ) - Expr- Calculation - = Var VarName Con ConName [Expr] compose [Expr]
I
deriving (fq)
and prove is changed in a similar manner.. The example calcuhii'ions reco
above. were produced with
. the modified definitions.' : .. type VarName "" Char
' . ..
type ConName = String
Exercises '
...
.. For simplicity, we suppose that single-letter names denote variables and multi-
12.1.1 Some of the laws one might wish t_o.use in calculqtiorrs depend on certaih'ffij: letter names denote constants. We will avoid .special symbols in the n~es of
subsidiary conditions being satisfied. Give an example tJf such a law. constants, for example by writing p lus for (+ ) and zero Jor 0. Thus the names
laws can only be used ill the proposed scheme by asstimi.ii.g.that the sub of constants are sequences of at least two alphanumeric characters beginning
conditions hold. - with a lerrer. Variables and constants are referred to collectively as terms.

... ...
.
,'

,\' ' ... :


.. 382 12.2'/ tpressions, Jaws, and calculations 383. :: .
'' . " . .... ' . .... . ~ :" : .. . .
The type Expr is decl~ed tq be an, instanc of Eq because we wiJ.!, need:to The complexity of. an expression is defined to be its number of terms:
ex-pressions for equality. . . : : ... . : . . .
.. ~
. . Here arc some examples of expressions: complexity' .,~ ..... Expr - Int
, complexity (Vat ... .. v) : = .1
Con "fst" [ ]
.
fst ~
comple-xity (Coni xs) = 1
... . {st f ~ Compose [ Con "fst" [ ], Var 'f)
complexity. ( C<?i!tPi~~ xs) = lengt~. xs
map{ ~ Con "map" [ Var 'f.] . ..
. cross ({,g) ~ Con "cross" [ Var 'f, Var 'g'] It is possible to give a more refined definition of complexity, but the given one
suffices ~in practice. :
'Each constant takes a tuple of arguments, whiclr may l:ie the empty tuple .(as
In printing an expression, we put parentheses only .around tuples of size at
. the case of {sl'), a singleton tuple (as with map), a pair, and so on. The scl'1etr1P'
least t~o, or around siilgle arguments that are not simple terms:
is very simple and does not allow us ~o represent expressions, such as {oldr f
that make use of currying. But we can always represent foldr f e by 'the '".''11 printExpr .. Exp_r - .Sti-ing .
{oldr <.f, e). The two equations defining foldr can be expressed in the -.u,.u"' printEx.pr ( Var v) - [v] ..
form
{oldr ({,e) . nil = e printxpr (Con f xs) '
. foldr ({,e)' cons == f cross (id.foldr (f, e)) null xs - f
simp/exs - f' * "u" +I printExpr (head xs)
In these equations both f and cons are nonctp:ried ftm~tions taking a 'pair otherwise - f * "(" * ,.
..
argwnent. . .
It is the intention of the 'design that the associativity of functional comoOS'
join With ",u'' (map printExw xs) * ")"
. ition is builtin. Thus, both (f g) h and f (g h) will be represented by printExpr ( Compose"XS) = jotnWich "." (map printExpr xs}
. .. .
same eXpression
0
simple .. [Expr) ...:. Boo/
Compo~er var'f, Var'g' , Var'h'] .
' simplexs = singleton x.s A simpleton (head xs)
. As a l'esult, Expr has two datatype invariants: .(i) the expression Compose
r-
\
. is valld only. if the length of xs is at least two; (ii) no expression of the r~...;;,. simpleton
v)
.... xpr- Boo/
' Compose xs contains an element of xs that is itself of the form Compose ys. simpleton (Var = True
maintain these invariants, compositions of expressions are constructed by simpleton (Con f xs) - null xs
function compose: simpleton (Compose xs) = False

corrrpose [xpr] - Expr The function join Wit~ was defined In Section S..s. A more sophisticated def-
compose xs = if singleton xs inition of printExpr should arrange to break an expression attractively across
then head xs lines if it is too large to"fit em ~me line. This re fincment is .left as an exercise.
else Compose (concat (map decomposexs))
'
"

decompose .... Expr - [ Expr] ' 12.2.1 Parsing expressions


. decompo~e (.Var. v) -. [Varv]
It remains to define par.-seExp'r..' Natu~ally, we wiU use the conibinators described:
::.
decompose (Con f xs) - [Con{xsJ
in the previous chapter. The l'iefinition is '"
decompose (Compose xs) = xs ' r

. )
parsexpr :: String - Expr
The function compose will be applied only to nonempty lists. '
parseExpr = applyParser expr

. . ,.~
..
..-
... ..
. .. ..:. ..
'
. '

. . 3fl.4 12./' Ap au tom atic 12.2 / .Expressions, laws, and calculations. . 385
:, .. ' :
: ..::..; ;:.::. . '
I ' ' -
.., ;

. The parser expr recognises a nonempty sequeric'e'of terms ~epa~ared b~ conq:; eqn :~ P,arser (Expr, '<P.r) : . .. .. ...
eqn - do space
position signs:
.. .
- X- expr
symbol"=" .
e.'<pr :: Parser Expr
expr = do {xs - somewtth (5ymbol ".") tenn; reil:lr~ (compose xs> I. y- expr .
. .... . . ~ return (x, y )
The parser tenn ~ecognises a variable or constant
. term .. Parser.'<pr 12.2.2 Laws ..
..
term - do space .
c- letter A law consists of three logical components: a name and two expressions:
cs - many alphanum
if null cs type Law - (l..awName,Expr, Expr)
then return ( Var c) type LawName = String
else do xs - arg~1ment
By definition, a law.is a basi~ law if the complexity of its left-hand expression
. . r:eturn
.(Con. ' (c': cs). xs)
'. is greater than its right-hand one:
Th~ pars~r ~rg~ment recognises the ariiument of a constant f~nction, if any: . basidaw
,
.. Law- Boo/
argume~l' .. ;: P~rser [Expr] . . . . . . basicT;aw (name,lhs, rhs) = (complexity lhs > complexity rhs) .
argument = tJ.lpleorelse (notuple orclse r~turn.[ ))
' ..
Other definitions of a basic law are possible, but' this one works well enough in
Tlie parser tuple recognises an expression in parentheses: most situations.'
The remaining function on laws 'is' 'parseLaw:
tuple .. Parser [Expr ] ~ .. .
IUple = do symbol "(" parseLaw -String- Law
xs - somewith (symbol ",") expr parseLaw - applyParser law
symbol")"
r,etum xs law .. Parser Law

1-be ~a.r:ser n~n~ple recognises a variablC. or' a constant ~th no ':f_guments: law - do space
name - some (sat ("' ':')}
:: Parser Expr
., ~ymbol":"
notuple
noruple = do space ' (x,y)- eqn )

,.
c- letter rerurn (name, x, y)
/
(
cs - many alpl:rqnum
'
if null cs 12.2.3 Calculations
then ret~1rn ( Var C)
else return [ Cori ( c : cs) ( ]] with .a sequence of steps.
... together
Acalculation consists of a starting expression . . . '

Each step consists of the name of the law being applied and 'the resulting ex-
Tlti,s completes the definition of parseExpr. pression. Hence we ca~ define : ... ' :
but simpler: ...
.. type Caln1lation = (Expr, [Siep]) :
pa,rseEqn :: String - (Expr, F.xpr)'
parseEqn = applyParser eqn ..
type Step =: (LawName, D<pr)' ' .
.. . '

.: .
;. . ..
. .. ...
313.6 . . .12 0;. All
.. auroillatic.calculator.
.. . ..: .12.3:/. Matchings
.
and. 'substitU:t~ons
. ..
.
387
.. '' : ' : ' : I
.

. . '
.'
.,
.. . ,
' ,
. ~ :.. , t . '
'
. ... . . ...
.
. .l2.2:2 ..A.. US~ful gC.!JCl:.<!li~<it~OJl. of fh,e proposed type ror xpr is. to. r~pJace the
. '

.. .The condusion of a calculation 'is the last expression.m it;


.' .: . . .: .constructor Compose: bya nit)fC general constmttor Ass coriName: Construe- ..
. c.onclusio'rt :: Calculation ..,.. Expr xs
tions ASs f are allowed when f is any associative opera t~on. on funttions. Give
conclusii.m (x, steps) = if nul/ stepS then ~ else S!lt((last StepS) an exampl~ where this generalisation mi.ght be useful.
.: .
The flmction paste. for paSting two calculations together.. can now be defined
'
by
.. . t-2.2.3 Give an improved definition of printExpr that handles line breaks in a
.. Cali::ulation.- Calculation - Calculation reasonable minnei:. " . '"
paste
pa.~te /he rhc = (fst lhc, snd lhc *
link xy tt shuffle rhc)
12.2.'! As an-alternative-to providing a fti.nctiori,printExpr: explicitly, l:)fpr can
where x = conciusion lhc
be made an instance of the class Show. Give details. .Show how.to lw,nclle .the.
y . . ;= concltlsion rl1c .
printing of calcillations in a similar fashion.. . . :.;:. .
:The function link inserts .an
. .indication of {aih,uc if the t1.vo .con<;lusions are not
.;

and substitutions
(
the. same: .:
12.3 Matchings
....
,.
link :: 'Expr-+ Expr- [Step]
tc:... ???. ...",y)J. , .
. .
if x:= y then [] els~
\.

(lnk.'!(Y := ..
'

Let us now show h{:>W "~o match one express~on x against a{fotiier e'.'Jlression
I ' ' I

.
The fu~ctibri shuffle reverses. the
. . . of a cal~ulatio'n, takmg.
. : steps .
y. t.-ratching is used in the calculator when x. is the lefthancl sid,e of some law1
, andy is some subexpression.of the currerit expression in a partially co~pietcd- ,,.
calculation. The result of matching is a set of possible substitlitions. A substi:
{Ution assOciates'each Variable of X With all eJ,:pre~sion in SUCh a ~vay that when
The defimtion is ' . the substitution is applied to?<. the resultis y. We also say thg.t y.is an i.nsl'aJlCe ,
.. ' x
of under the substitution.. '
s~u{fle . ::. ~alculation 7' [Step]
... ' ~huff/e(x, ss) = snd ({oidf shunt (X, ( }) SS) . . .. . A match may f<U,i, yi.e)di~g.the 'empty setof substitutions, or it may succe~d.

. '
. :=. (y, Cr.. x): r~)
where shunt (X, T$) (r,y) '
in one .or more ways. For exainpte, matching . .. .
..
The function)1rintCa/t
. . is defined by
~

(oo (f' g.{ . g) against foo (a : b. C, a. b: C) ..


.printCalc Calculation- String
printCalc (X, SS) - *
..-+uu" prin'tExpr x* . . succeeds in two different ways, either by binding f to a. band gto c, or by bind- .. ,
''+" -H- concat (map printS.tep ss) ilig f to a and 'g to b c. Although the al,J.tomaric calculator will select a sii1gle
substitution for use at each step a calculation, it is important to take account. of
pl'i ntStep .. Step - Siring of multiple ma.tchings in the process of determining ~he valid substitutions. As
prfntstep (why, x) - "'= uu(" *why* "f+"* we will see, the general. scheme is. to match expressioris by matching corres
. " ;,*
uu * ..
printExpr x . -+'' . .ponding subexpressions and.combining the results. Eor example, .in matching.
. ~'.

foo ({ g, bar g) agairtst foo (ci b c; bar c)


"
Exercises
. .. . .. -.~ .... . ., : :

,,

'. 12:2.1 v~ious alternative del'initicins ofEXpr are possible. One is to say the SUbCXpl'CSSiOll { g fS matched againSt a b C, resulting in {VvO pOSSible
an ~xpl:'essio~ is-either a' ~~i~ble, or aCQilSt~H~t (with no argum~nts), Of substitutions. Only.wh~n the subexpression bar g is matched with ba~ L~ is one
applicatiqn of ~me expression to another. Formalise the associated data type of the substitutions:t:ejected. A premature commitment to a single substitution
r
give the representation of {sc' . fold eas an element. wpat are the for the first pair of subexpi'essions may result in a successful substitution being
and ...disadvantages of this n!preseritation?' .. . . . . ~sscl
. .

..
,
... .
... ... ..
' ' . ' ~ - .. '

. .
. .. .. -. .

388 . . :. . . '. .. . .mitdmaric
. 12/:An .. . . c<wLw~cor, . . I Mate/lings
)2.3 . and
. sabsriruCions.
. . 389
.. .. .. . . . .
. i ~~ .... . ...
: ,
..
.. . .The fu:st ;arg~ept to ~match i$_.an accur;nulating ~aram.eter of ry.pe Subst. The
~

12.3.1 Substitutions
'

. 'r6nm. .ing definiriQn of xmatch will be derived formally ~ -Section 12.5 from a
direcrdefinition ofmatch; for now, we vvill siinplyexplain the definition clause
:' ,. ' ,by clause. First, . .
. '
type Subst :. ((VarNam~. Expr)J . .
. . ,. . xmt;~tch ;: Subst - '(Expr, E.Xpr) - [Subst]
In.Words, a suostitutioil is represented as alisr of biri.dirigs. Art. empty '
. ; .
." ....
.
noi:
represent'the undefined substimtfon, ~Ut ,ratherthe ~ubstitu~on in ,
xmatchs(Varv,x)
. .... . - extends(v', x) ..

'
each variablev is. associated with Var v. Thus an empty list represents Matching a variable.v.againsran arbitrary expression x always succeeds. How
, identity substitution. . ever, extending the substitgtion s with (v, x). inay
. yield an empty list of substi
The function binding retUrns the expression associated with a given tutions. Next,
, in a sul;>stitri(ion:
.',. . ..
x'match s (Con f xs, Var v) - [ l
.binding Stibsl - VarName - txpr xmatch s (Con f xs, Composeys) - []
. .
.., . binding {] v . - Varv
binding ( (u, x} : s) v - if u == v then x else ~inding s v xmatch s (Con f xs, Cong ys) .
. ..... = if ( ; g rheilXmcw:}Jiist s.(zip 'XS ys) else (J . . .
' ., : '. ' I

' -1 . J : :

We \Vill also want to appl.y a substitunon ~o an expresswn:


#- ,.
..

. . Matchil1g a constant against a variable or composition always fails. On t~e other; ,
a'pplySub :: Sitbst - Expr. -:- Expr
hand, matching a constant against the'same co.nstant succeeds if correspondiiig
applySub s ( Var v) - bindings v
elements in the two.argument lists can be matched. TP.e. fun~tion xmatchlist'is
applySub s (Con f xs) s = Con f'. (map (applySub:~> xs) .
defined by
. , applySub s (Compose xs) = compose (map (applySub s) xs)
-.
. Finally; ~ve
. . . .;
will want'to extend a substitugo~. with
.:. :
an addidonal binding:
. . . . ..,,. -. . ,
xmalchlist
xmatchlist ls[
.. $ubst :- [(Expr, .Expr)] - . (Subst]. ,
'= [s] '
.. . .

. extend ::'Subst-:..: (VarName,Expr)...,. [Subsr] xmatchlist s (xy: xys) , =: . con~at [xmarchlist .t xys I t- xmatch s xyj . .
.. .. . : . . . . . ,: .: ' . . .... ~ .. . . ' . '
.
(

extends(v,x) , Matching an empty list always succeeds; matching a list (xy : xjts) mvolves
., .... ~. .
y== x - (s] ..
.. . . .
first computing xmatch s'xy to produce ~ list of possible _subs_titurions, and
Y==Varv = [(v,x):s] .
,
tben r~finirig each subshmtion'_t'iri. .this list by computing xmatchiist t xys. The
otherwise . . [ ]
~esult is a list of lists of substitutions, \vhich is flattened by conceit.
where y = binding sv
Tqe
. remaining
. . dire~ c!auses of xrriaich are
The 1\mctio~ exrend ierurns a list of substitutions; this .list is .empty if -
xmarch s (Compose xs, Var v) . (] . ,, . ...
. additional btpding is incompatible wHh the given stibstituQon, ~~d ~sa ::.u''l:>!~ xmatch s (Composexs, Con g ys) - []
. list otherwise. ..:. : :.
- . ...
. .
.. .
:
. .. .
xmatch s (Compose xs, Compose ys) .
12.3.2 M~tching = concat (map (xmatchlist s) (align xs ys))
.. ... ..
The funcrion march takes a pair of expres~ions and remms a set of sut,sl;.i~ Matching a composition against a variable or'constant fails because Composexs
tutions. For reasons of efficiency, march is defined in terms of a gene <lli':c:~t:: is.a valid e){pression only when l~ngth xs > 2. Matching .two se,quences of com
,
function xmatch: : positions succeeds if matching appropri~tely aligned segments'does. The furic-
. .ma(i:h .. (Expr!Expr)- [Subsr] tion align is defined below. For each list xys bf appropriately aligned segments,
... . ..,
. tn~tch (x, y) ' .;.., xmatch [ l(x, y) the value of xmatchlist s xys is computed and the results are concatenated.
. .
... ~ . ;' ,..,
)

... \ ' .. " ,. . .


390 f
. . 121 An~utomaticc~lcu/ator . 12.4:I Subexpressions a_nd rewriting
. .391
~

Tod~flne ~s- suppose


. : .!

. . .. align xs iength xs m. anct-lengtll .ys =n. If m >.n , 12.3.2 Th~.fun~tion ~alch can be defined diiectly. Two of the dausesare .
then xs ca~ot be matched to ys as there are not enough eleme~ts of Y~ ~o .go . .. ', '
' '' ' I
' . ~ ,.

match (Con r :~s,'.Cbn g)IS)


oun. .d u m s; n then each element of xs has to be rp.atched with soxpe segment
r ys. In other words,
of if YS1. ysz, YSm ~s
a partHJon f ys m to nonemp ty
. = if r::
g 'then match list (zip xs ys) else ( J
conti&ruous: segments then the first clement of xs has to ,be matche~ to Y,St, match( Compose xs, Compose ys) -
the seco~d ~iemeilt tc~ YS2 , anciso on. We will tl;terefore need to m~e u~: of a =: conca((m ap rrlatchlis~ (align xS ys)} '.

func tion parts m that return~ a list of all partitions of a seq.uence mto a hst of i; answered in
. . m compo)lents. Given parts, we can define Fill in the remainin
.
g dm.i.ses. (This e.xercise
. .. . .Section
.
.
12.5.}
~
.
12.3.3 The function inatchlis t of the previous exercise is defined by
.. [Expr] _ [ Expr] - [[(Expr,E xpr)]] . .. .. . ~ ..
align
match/is t :: '[(Expr, Expr)] - [Subst J
align xsys = [zip xs (map compose zs) I ~s- parr_s (length xs) ~s]
matchlis t . = coneat map unify cp/ist . map match
The definition of pares is
This definition reads: firs t compute the list of lists of partial substitutions
(via map tnatch), then combine all partial substitutions' into a list of canclidare
.,
pa~'ts jm' .:.. [ex]- [[~ ex] ])
substitu tio~s (via cpli~:~>. then \Uiify each can.didate (via unify), and fii1ally coliect

partsci u - uJJ the valid substirutions (yia concat}.
parts 0 (x : xs} - { J
. The function cplist (short for 'cartesian produ~t ov.er lis.ts') is defil).etq urormally.
-
pail'~ ( n + 1) [ ] - . [] .
. . . , . :: . ; . .
by . . . .. . . . .
part-s (n ;t- l) (x: xs) = map .(new x).(parts n xs) #
. map (g/uex} (parts (n +.1) xs)
cplist [XSJ, ... , xs/1] == [(.~! . : . ,Xn] I x, - xs,, ... I Xn- XSn] .
'
..
..

. definitio
Give a forn:iai .' . n.:' of
.: cplfst.
. .' ' .
(This exercise.' is answere
...
' . SectiOI~
d in . . . 12.5 .)
12.3.4 The function unify :: [Subs!'] - [ Subst] takes a list of partial substi-
rutions and combines them lito a single complete substitution. Thus, unify .
returns either an empty list, if the partial substitutions cannot be combined,' .or
a singleton list containing the _unified substitution. It cari be defined by
unify [Subst] - [Subst]
unify [ J - ([)]
un ify (s: ss) = concat [unions t I t - unify ss]
ex;- [[ex]] - [[ex]]'
new The function union :: Subst . ions and,
. .:. Subsl - [Stlbst) takes two substitut
. provided they are compatible,_ merges them into a single substitu tion. Give a
new xyss _ [x]: yss
glue.: ex- [[ex]]- [[ex]] defulition of union. (Jhis exerdse is answered in Section i2.5.)
ghw x (ys : y.~s) = (x: ys) : yss
' .
. . ' '

: ..... .. 12.4 Subex.Pressions ~d rewriting . .


. . . ... .
Exercise ~.

. .. . . . In the previous section we.saw how tomatch one expression (the left-hand side
. )2.3.1 Prove that applySub [ J =id. . of a Jaw) ag<tinst anothet.: expression. Now we want t() match an expressioq
against a subexp'ression of:'! given expression.- If the matching succeeds, then_
.-
., .
~.
'
.' ' ..
: .=;, ..
~
.o_:
... ..
. ' . .
... '

392 l2/. Ali autoivaric rall"lll.ltn. 12.4 I Sub~xpressions and rewriring


. . ..: ~r.... ~.. .
~ . . ' 1
393
' .: '
, 1 ' ~ l . :;.,_ : ,.. ' '; ::.;. ' . . . .. . .
the appropriate instance of the righthanl;l side Qf .the law :replaces. the - supc~rms :: [Expr.] - [SubExprJ
pression. .T.o carry out this replacement, it is necessary10 h~,c~te:Subexpress subtimns xs
in their parent expression. Hence we define : 5 :~...
....
- . [(Posj loc,y) I j - [0 .: n -1], (loc,y)- subexprs (xs !!j))
.. where n = length xs
lyP.e SubExpr = (Location, Expr )
.-
~ . ~
.. .c. - . . )fegments :: [Expr ]' - [Subfxpr]
. .
A subeXf)ression of an expression x may be all of x, or a segment of x (if x is
segments xs .
composition of terms), or a sube}qJn!ssion of some term of .X. This leads to
= [ (Seg j k, Compose (Cake k (drop j xs))} I k - [2 .. n ..... 1 ),
following declaration of Location: .
; .
. , .. .~.:_,_.: .
:;.;._. ... . :_ .... J. - [0 .. n - k.}) ..
.
' -..vhere n = length xs
';

data Location = All I Seg Inc Inc Pos Int Locarion


... . . .
The location Seg J k denotes a 'segment beginning at position j and cxt1enCling The function subexprs produces segments before subterms; this .is probably
fork ~ 2 terms; a location Posj loc denotes the subexpressfon located at loc sensible, though more sophisticated generation orders .are possjble. Again,
the expression located at position J.. :.. subterms are generat'ed from left to right; in practice, manipulations usually
Let' us see how this scheme works out on the express19_fr .. proceed right. to. left: .Another option is to have subexprs take ai} adP.itional ar-
. . gument, the loca~op ar'wh.ich the ctUTent expression was last .changed, and then .
f st .pair ({ {st, g snd) zip . to gener~te subexprt:ssions around that location fi.ist. All these refinements ai'e
left as exerdses.
Here is a complete list of the sub~ressions of the aboveexpression and the Finally, we need a function for replacing subexpressions by other expres
locations at which each subexi)ression appears: . _ sions:
{st pair <f fst, g snd) zip at All .. replace .. Expr - Location - Expr - Expr
f st pair <I' fst , g snd} : at Seg 0 2 .replacex Ally - y
... -
at
~ ;,
pair ({ {st, g snd) iip Seg.12
{st at PosO All rep(ace(CQn-{ xs) (Posj loc) y
pair <f fst. g snd ) at Pas 1 AI/ = Con f (take] xs [ replace (xs !! J) Joey) it drop () + 1) xs)
*
f fst at Pos 1 (Pos 0 All) replace(Ca,;.,posexs) (Posj Joe) y
f at Pos 1 (Po~ 0 (Pas Q Am) . =: compose.(iakej xs * [ replace (xs !)j) loc y] *drop U + 1) xs}
. {sc . at Pos 1 (Pos O(Pos 1 All)) replace (Composexs) (Segj k) y
g snd at Pos 1 (Pas 1 A/I) = compose (take) xs (y] *drop U + k) xs) *
g at Pos 1 (Pas 1 (Pos 0 Ail))
snil at Pas 1 ( Pos 1 (Pos.l A./1)) . ~: .. . ...
.. : .. --;-'. - . ...:;.
\ _,'
.
~ ~: .
.. 12.4.1 Rewntrng
-

l ip at Pos 2 All . ..
We are at last in .a position to dcl'ine the ftmc.tlon.ca1cu1are. To calculate with
.. The above subexpressions .arc listed in the order in \vhictt'.'tneyfll'e generated
by the functionsi1bexprs: .. :. ' . an expression means i.tstllg the laws repeatedly to rewrite the expression until
,. ' . . ''
.. . no more steps are possible. J-Iet;ice .we can de.fin!! .. . , ,
subcxprs .. Expr - [SubExpr]
calculate . :: . ([Law], [Law)) "'1 Ex.,pr .-: Calculation
subexprs ( Var v) = [(All, Var v))
calculate pis x = (x, repeatedly (rewrites pls.}x) .
subexprs (Con f xs) - [(All, Con f xs)) *
subterms.xs
subexprs (Compose xs) - [(All, Compose xs)) * ..wigmen1s xS+t- Recall that rhe list of laws is split into two. sublists .. the basic l<:~WS that are
subterms xs always tried first, and the others.

..
' .
12.5 I Testing tllc calcu1itor 395
12 I An auto mati c ca!cUJato( ' . . . ' ." . t
394
'
. ..:1 ,,.'::' . .. " ..
. ' iting an expression: 12.5-. Testing .the:~~i ~~i~. tbr
Tl!e function rewr iles produces <ill poss ible \'Jays of rewr
.. . '

. :.. .. ""; : .
[.Step J ~ow use~Lll is the cals~ato~ h1 p~actice? The only way to answer thetoque~ tion ..
rewrites :: (['La w], {Law ]) - .Exb r - ~se - the
going
t~ try it out ~n a pon_~rivial example. In this sect ion we arc
''
rewrites (Jlaws, rlaw s) x . IS .., '
given in Section 12.3
- concat ([re writ e law sx xI law - /laws, sx.- sube
xprs x } : calc ulat o_r to gc~e~a~~. pa}'t ~f the definitio n of xma tch .;.
we have chos en to auto mat e is the
* [rew rite law sx. x I sx - sube;\:prs x, law - rlaw s])
I
,
'
from .a _direct definit10n of matc h. The part
mos t.dt~c~lt one; the r_est of the synt hesi s is sufficien tly
.
easy not

warr an t to
are tried first, each
'

auto mfitiop. .
'

. The tv.o klnds .of law are trea ted differently. Basic laws
'

ns. In the case of the follo~s: ......


law beh ig tried il) sequ ence witll all poss ible sube xpresslo The 1ec t defin ition of ma'tch (see ~ercise 12.3 .2) is as
tried in sequ ence with.
othe r laws, the rule is different: each sube xpre ssio n is
. match . .. (.Expr, Expr ) - [Sub s;]
all poss ible laws. [[(v ,x)J ]
iting a sing le expr es =
The func tion rewr ite prod uces all poss ible ways of rewr
match (Va r v,x)
match (Con f xs, Var v) = (]
'sion ""ith a sing le law:
mat ch (Con f xs, Compose ys) = (]

Sub Exp r ... EXpr -~ [Step]



rew~i_te ::La w .-
rew rite (nam e, lhs, rhs) (loc , y) x . . . . match (Co n f xs, Coi1 g ys) .
= [(name, replace x lac (applySub s rhs)) if f == g then mat ch list' (zip xs ys) else ( }
,
I s- mat ch (/hs, y.)]. .. =
I

:
filially, repe ated ly applies the first rewrite at each step matc/1 ( Co11ipose xs, V.ar v) = [ ]
mat ch (Compose x.S;qn~ g ys) = [] ..
repe ated ly:: (Ex pr- [Ste p])- Expr - [Step] .. .. ... ~

. '
rep~atedly,rw_s x . inatc/1 ( Com pose xs, Compose ys)
= if null steps then [ ) else ( n, y) : repeated
ly. rws y ... ..
= concat (ma p matc h/is( (alig n xs ys))
.where steps. . = rws. x
.
(n, y) = hea d steps.
.. . The func tion mat cftlis t (se~- ~ercise 12.3.3) is de~ed by
. .
amo ng man y poss ible
Nondeterrrtinism is reso lved simp ly by choo sing the first
steps. Other sche mes are, of cour se, .possible .. For.- hlsta
nce, in an
.interactive mat chlist :: . [ (Expr, Exp r)] - . [Subst]
= c9~ncat mqp imify cp/ist . map mat ch
::iossibility is to exJJtore matchlis t
setti ng the choice cou ld be offe red to the user. Ano theq
shor test one. pair of expr ess-ions,
the complete tree of feas ible' calculat ions and retu rn a The ftmc tion ma~chli:5t com pute s the subs titutions for each
.
collects all combma nons, and unifies each com bination
. dcfineq by
Th~. func tion cplis t i~ ,
Exe rcise s .. . ";

:.~ [ [ ~xJ) ~ [ [ex]]


inst all different gen: ..
12.4.1 Modify the definitio n of sube xprs so that one can
cplis t '

an extr a argu men t to cplis t [ r. .=;;.. , ( [. J] ...


eration orde rs in asimple way: This will involve adding [J:': ys I y xs, ys - cplis t xss J
of 1'ct be chos en. . cplis t (xs: xss) . =:=
.calCulate to hldi cate which' the orde ring s shou
""c

. .
the idea that sube xprs s.hou ld take The func tion unifY. is cte'fi ned by
12..4.2 Rewrite.- the duc ulat or to imp lem ent
repl acem ent. .
an add itional argu men t, nam ely the location of the last unif y :: . [Subst] .:.. [Subst]
e, so that a chOice of unif y [ J
12.4.3 E.xplore the idea of mak ing the calculator interactiv
= [[ ])
unif y (s: ss)' = con~a~'[union s t I r - unify ss]
step s can be.o.t'fer ed to the user . .. "' .
' _. . ~ '

' .. .
' ... . .. .. ..
.. .. -.
.. . .:._....... . .. .
396 . \
12/'An ~ ~i rorii;!ricc;~JcuJCJ
' J , .. ~'.I;..
12.5' /.Testing the calculator
' . 397
.:.,, :': .. ' . .,.".,.,;.:~"I,'.
....;J!,. \&"!'-: . '
. .......
# r - ~'1,

The function L!rzion can be defined by ' xma(ch s (Con f xs, Con g ys)
. . .... . . '

= iff ., g then cgncat [union .s r I r - matchlist (zip xs ys) l else


. -: ' ; .,
fl
unwn Sttbst- Subst- [Subst]
:: . . ~ ~ ]~:,.
xma~ch s (Compose xs, Compose ys)
ei'se [)'_:. .::.
union~ t ~ if compatibles ( then [merge s t1 ~ = concac [ unions t'l t - concai
.
lig~xi.ys)) ]
. . (map matchlisr(~
..
Two substitutio~ are compatible if and only if they agree onthe
..
.. o o _ r ,
o
. .

their co~on domain. The function merge can be imple.q.en~ed_ by .( * ) ,; The last two equations can be sirriplified by i.l:ltroducing
by merging the r.wo lists of bindings, removing duplicates. We will not go xmatchlist :: Subst - [(Expr,Expr)} - [Subst]
details. Not only is union complicated to define, it is also expensive to cornollltt!l xmatchlist s xys = .. co neat [unions t I t - match list xys]
A betteridea, and ~ne that moQvates the efficient definiti,on. of .xma cch , is .
comput.e the..union of two substitutiQns only when one of them is a subs Then we have
involving a single binding. Tllis is the point of the function extend, which xmatch s (Con f xs, Con g ys)
specified by = if f ~= g then xmatcfllist s (zip xs ys) else [ ]
extends (v,x) = unions [(Varv,x)]
xmatch s (Compose xs, Compose ys)
The definition of extend given in Section 12.3 ilnplemems 'tllis spe.cification : . .= concat (map (xmatchlist ~) (align xs ys))
' . . . ...
an obvious ~vay. .
The first equation is immediate, and the second is left as an easyexer:cise.
However it is implemented, we will need two assump'tions about un ion
At this point we have derived the required delWtion of xmatch, except for
i!ni9n [ l s = [s) for all s. In words, the empty substitution i~ compatible
the crucial fact that xmatchlist is defined as above, and llOt in the form given
. .every substiri.Ltion and is the tm.\t of rYierge. Second, define L;Up 'by .. ;
. . . . . .. in Section 12.3, namely
cup :: (Subsr] - [Subsr]- (Subst]
cup ss rs = concar [tmion s c 1 s- ss, r- rs]
xmatchlisr s [ 1 = [s ]
xmarchlist s (xy : xys) = concar [xmacchlist t xys I t - xmatch s xy]
The assumpt;ion is that cup is associative: .."' ~ This def{ni(ion does not involve the function ~nion, which is the whole.point pf
. ' cup ss (cup ts us) = CtlP ( cup ss rs) us phr_asin&Jn;:ttching in terms of. xmatch. . .
In order to prove that the t\..,o definitions of xmatchlisc ~e equivalent, we .
It follows from the flrst assumption that [ [ )) is the unit of cup. .. ~
have to pass through an intermediate stage. Born xmacch and xmatchlisc. take a
.. single subsritution as an acnunulating parameter, while the functions gmatch
12.5.1 The generalisations
and gmarch/ist each take a lisr of substitutions:
. .
The function xmatch is specified by [Subsr] - (Expr,Expr ) - [Subst]
gmacch
xmacch :: Subsc - (Expr, Expr) - (Subst] gmarch ss xy - concac [~nion s t I s- ss, t - match xy1
xmacch s xy = co neat [unions t I t :. match A.Y] .
gmatchlist .. [Subst1- [(Expr,Expr)] - [Subsr] .
Since union [] r = [ t], we obtain match = xmatch [ ]. .. . . . .. ..
gmatchlist ss xys - concat [union s c I s - ss, l'- rnatchlist xys]
lt is very easy to use the clefiilition of match to derive the following equations
I I
for xmatcl!: . . It is clear that xmatch s = grnatch [sl and xma.tchlist s = mnacchlis( [s]. In
, I
xrnal'ch s ( Var v, x) - extends (v, x) fact, except at one point, we will use thesedefinitions of xmcltch and xmatchlist
xmatch s (Con f' xs, Var v) - [] rather than the previous ones. It is also clear that match = grnatch [ [ ]}. In
xtnacch s (Con f' xs, Compose ys) - [] ' fact, one way of viewing the derivation of anefficient program for match is firs t
xmatch s (Cornposexs, Var v) - [] .. . to express the program in terms of gmatch, and then refine ihe ~esult to use
xmatch s (Composexs , Con g ys) - [] xmatch.
. . .. .

'
.. ..
398 i2 l An ailtomatic calculator . . . 12.5 I Testing t11e calcul;~wr .. 399
.. '...' . ' .
... ':'. .. : . ' :: . 14
. ...
. . .-corrtbinatots
12.5.2 The .. . The above definiti<;ms.. arc S.~r<.Ugqtforward transla(ions of the previous 'ones
. . . .
match because it ~s ri.ot
.. is no definition of
..
into functional form. Note t11at there
\

The first. task is to recast ail the previous equations in functional, noncutried .
.needed in the proof.
form..For this purpose we 1-\'ill .need a numberof special combinators.
Fi!st, the combinator star is defined by . For the proof we will ncea a number of laws, including the following:
.
star (ex- [/3])- [ a ] - [13] l aws l ~ stars ++ cps ++ i ds +t f uncto rs
starr - concat . map r ' , stars ' - . +. \ '

= map parseLaw [
Use of star is 'not absolutely nec'essary,.bu t it will help to shorten expressions.
"star after map: star f. rnap g ~ star(f.g)" ,
The next group of combinators arc cpp, cpr, and cp/: "star after concat : star f . cbncat = s t ar (star f)",
cpp .... ([ ex], [/3))- [(ex, /3)] "star after wrap: star f .wrap ,. f",
''star after nil: star f.nil = nil'' ,
cpp (xs,ys) = [(x,y) I x-" xs, y - .ys] "star after star: s ta r (s tar f. g) = s tar f. star g" ]

cpr (ex,[/)])- [(ex, /3 )]


cpr (x,ys) = [(x,y) ly - ys]
The "star after star" law is an easy consequence of "star after concat" and "star
after ma!J".' One can use the calculator to prove these laws, a task "\'e leave as
cpl ( [ex] ' .8) - [ (ex, /3 )] an exercise.
cp l (xs, y) - [(x,y) I x .- xs]
cps = cpps ++ cpl s ++ cprs
.. .
Use of cpp is cqnvenicnt but not necessary, because cpp = star cpr cpl, as the cpps
reader can check from the laws of list compreh~nsions. = map parseLaw [
Finally, we Will need the combinator assl (short for 'associate left'), defined "def cpp: cpp ;, sl:::t r cpr .cpl"J
by '
... .. cpl s .. ...
- ((c.x, /3). r>
'

assl (a, (13. y)) = map pa r selaw [


ass/ (x, (y, z)) (( x , y), z) "cpl after nil: cpl.cross(ni l ,id) . nilh,
. "cpl after wrap: cpl . cross(wrap, id) = wrap",
. Here are the defmitions we will use: "cpl after map : cpl . cross(map f, id) = map(cross(f' ld)) .cpl",
"cpl after concat: cpl .cross(conca t ,id) star cpl.cpl" ,
matchs "cpl afte r . i d: cpl. cro'Ss (i d, g) = map (cross ( i d, g)). cp1",
a map parseLaw [ :cpl a f ter star: cpl . cross(sta r f,g) = star(cpl .cro ss(f,g)) .cpl"]
"def matchl ist: ma tchlist ~ st a r unify.cplist.m ap match",
"def un ify: unify.ni l = wrap.nil ", cprs
"def unify: . unify . cons ~ star union.cpr .cross(id,unif y)", = map pa r selaw [
~def c'p list: cpl i st.nil = wra p. nil " , "cpr after nil: cpr.,ross(id,n il) ni l " ,
"def cplist: cplist.cons =map cons . cpp .cross (id,cpl ist)"] "cpr aft er wrap: cp r .cross(id,wra p). wrap" ,
"cpr after map: .. cp r~sross( i d,ma p g) map(cross(id;g )) .cpr'' ,
gmat chs ' "cpr after' con~.a.t: cpr .,c ross_(i d, concat) sta r cp r. cpr'~,
,. map parselaw [ "cpr afte r id : cpr. cr oss( Lid) . map( cro ss(f,id) ).cpr",
;~def gmatchl; s t: gmat'c liiist ,; s t ar union.cpp.cross(id,matc hl i st)", "c'p r afte r star: cpr.cross( f,star g) = star(qlr . cross(f,g)) .cpr")
. "def gmatch.: ., g[llatch. ~ star un ion.cpp.cross( id , match) ")

xmatchs
The "cpl after star" and "cpr after star" laws are easy consequenc!!S of the as
e map parseLaw [
sociated "after concat" and "after map" laws. The "after id'' laws are instances
"de f xma tchlist: xmatchl is t = gmatchlist .cross(wrap,id )", of the corresponding "after map" laws, introduced simply to avoid use of the
"def xmat ch : xma tch = gmatch .cross (wrap , id)"] law id = map id. The remaining laws are

:. .
..:

- -
.. ..;

400 ..... .aucomaric


12-/An. .... calculator 12:5./. Testing the calculator 401
. .. : :..-~~ ::..~ :.: ,;';"~. ..
. ids ., ~ <>- - ....
claims . ~ '
a map parselaw (
= map pa r selitw (
"claim~ .sta ~(cpr.c ros s (id,g)).cpp .. cpp .cros s(id ;st a r g)"]
:I .
.'
" i d left uni t : ; d. f f ". '
''id right UQi t: f~id .. f "] :
? prove l awsl ''s~ar(cpr.cross (id,g)).cpp cpp . cross(i d ,star g) "
f unctors . . -
; ma p parsel aw [ sta r(cpr.cross(i d, g)).cpp
"cross functor; cross(f,g).cro ss (h,k) "'cross(f.h, g.k) " , {def cpp}
"cross f unc tor: cross(id , id) ~ i d"; sta r (cp r .cross(i d, g)). sta r cp r.c pl
"map f un ctor : map f. map g = map(f.g) " , {star afte r star}
,;map f unc t or ; map i d .. i d", s tar(star (cRr. cross( i d, g)) . cpr). cpl
"map a f ter ni 'i: map f. ni 1 ; nil ", .. {cpr afte r star}
"map after cons : map f.cons a cons .cross(f,map f) '.' ] star(cpr . cross(id, star g)) .cpl
{star after map}
star cpr. map(cross(id, star g)).cpl
wewill also need some additional laws,. to be described in due course. .. {cpl afte r id}
1 is a fair question O ask why we have chosen the above laws and not others. star cpr . cpl.cross'(i d, star g)
The answer is simply that we have recorded all the {av/s of scar; cpr, and so on, .. {def cpp}
that might prove useful. In fact, many of the laws listed above are not used in cpp. cross(i d , star g)
the proof.
Ffaving established the claim; we can proceed with the task of obtaining a re
cursive defu1ition of match/ist: .
12.5.3 The calculations
laws2 ; matchs ++. lawsl ++ cl ai ms
Om eventual objective is to show
? prove laws2 "matchl ist. ni l = wrap.nil"

xmatchlist.c ross(id , nil ) =


wrap . fst
mat c.hlist.rlil
..
xmatchl i st, cross(i d, cons) : sta r xma tch1 i st. cpl . cro ss (X:match ,;d). ass l -
{def mat chl i st}.
star uni fy.cplist .map match. ni l
At the point level, these equations read:' {map afte r ni l}
. xmatchlist (_s, [ J) - [s] . . ..
star unify.cpl ist .nil
{def cplist}
xmatchlist (s, xy : xys)
= coricat [xmacchlist (r,xys) -1 r-:- xmatc'h (s,xy) ] ..
star un ify .wrap.nil
'{sta r after wrap}

Apart from the fact that xmacchlist is a noncwTied funcri_o)l., tl1is iSa
..
un i fy . nil
{def unify}
wrap . ~il
trans'cription of the definition in Section 12.3~ . . . ..
I.I It would b'e nice to just press a button and have the calculation unfold, but The second proof is as follows:
li life is not like that and we have to proceed more slowly, In outline, th e proof .
~: I is in tluec stages: : : ~ ? prove laws2 "matchlist. cons =star union.cpp.cros s(match,match list)"
.'
matc hl ist: . cons
') ~

'I i. Obtain a recursive deJ'inition of macchlisr. " {def matchlist}


I/ I
f,.l Use the result to obtain a recursive definition of gmatchlist. st ar unify. cpli st. rnap match . cons

or xmat~hlisc.
1! {map after 'cons}
Use the result to obtain the required definition s tar un i fy.cpl ist .cons.cross(ma tch, map match)
" {def cplist} .
For the first stage we will need a claim: star unify.map cons.cpp.cross (i d, cplist).cross(m atch, map ma t ch)
..
- ..
.,
~

404 .12.5 /.resting the calculator


: ... . . ;
.. 405
''
-.
= {def 9ma'tch'} xma~chl.ist.'cross(id, nil) ; ' ... :

cup. c'ross (gmatch. match 1; st) 'assl ...-:.... ..,.. ' .... ...... .
; :_ .:
-
~ ~ {def xmatchlist} .
{id right unit} gmatchlist.crqss(lvrap, id) .crossCid, nil)
cup. cross (gmatch. ma.tch 1iSt. i d). ass 1 ;, {cross functor.f . .,.. .'
{id left unit} gmatchlist.tross(wrap.id, id.nil)
cup. crqss(i.d. ginatch, match 1i st. id) . assl
.":" .. "' . {id left uni't} .:. . . .
. {c ros ~- func.to r} . :.-, - . gmatchiist.cross(wrap . id, nil)
cup.cross(id, matchlist) .'cross(gmatch, id) . assl = {id right unit}
= {cup intro} gmatchl i st. cr6ss (wrap, n1 1) " '
. '
s'tar uni o'n: cpp. cross (i d, matchl i st~. cross (gmatch,. i d). assJ. ~ .{gmatchlist-1} ..
'
{def gmatchlist} wrap. fst
gmatchlist.cross(gmatch, id).assl
. ... '
? prove laws4 "_xmatch1 i st .cross (i d, cons) = gm~tchl i st. cross(xmat~h,; ~j. assl"
At the point ,level, we ha\'e shown
xmatchlist.cross(id, cons)
gmacchlist (ss, [ }) - ss = {de f. xmatchl is t}
gmatchlist . cross(wrap, id).cross(id, cons)
gmarch/ist (ss. xy: xys) gmatchlist (gmatch (ss, ~y), xys) = {cross functor}.
ginatchlist.cross(wrap. id, id . cons)
j
.
Hence we have shm-vn that mrry gmacch/ist "' {old/ (curry gmatch). = {id left unit} .,, ' .
In a seu~e. we have achieved the main objective of the optimisation ofmQrtdil ~5?i.' 'gmatchlist.cross(wrap.'id, cons)
na~ely to derive a computation in which the function Lmion does not appear. = {id right unit}
is easy to use the definition of match to get a definition of gmatch that does gmatchlist.cross(wrap, cons)
l . . .

= {gmatchlist-2}
mention 'union, so why bother with the extra refinement of replacing grnatch
gmatc;hl i st . cross (gmatch, i d) . assl : c.ross (wrap, i d)
xnicitch? The ariswer has to do with efficiency. If xrnatch {.s., xy) fails, = {assl help} '
'rhe empty list:thenxmatchlist(s, X)i : xys) fails at once; hut J gm'qtch..(ss, gmatchlist , cross(gmatch, i(l) . cross(cross(wra~. id), id).assl .
fails, rheh gmacch/ist (ss, xy: xys) does not Jail until all the remaining pffirs a . {cross .functor} ' "
have been processed. In this context, see Exercise 12.5'.4 .. . gma~ch 11 st. cross (gmatch , cross(wrap, ..i d), .. i d. i ~O . assl
{ld, left unit} ' .
To continue, we install the t:ecursive definition of gmatchliscas a 'r
~
, ,. gmatchlist.. cross(gmatcli.cross(wrap, id), id).assl
ment for the previous one: = {def xmatch}
gmatchlist.cross(xmatch, id).assl
newgmatc hs
= map parselaw [
''gmatchlis t -1: gmatchlist.cross(f;nil) ~ f.fst",
Coniparison of the last result with the on'e we are after shows that we need
' .
. "gmatchl i ~t - 2: gmatch1i st. cross (f, cons) _a ~al fac~, namely that gmatchlist = star xmatchlist . cp/. In O'rder to prove
'. = gmatch 1i st.
. cross
. (gniatch,
. i d). assl. cross
. . (f ,,id)
. . "]
~
rhis equanon, we have to go back ro the original definitions of xmatch/ist and
. ' .. gmatchlist:
The forms of these equations are made necessary in.order to av'oid appeal
the law cross({. g) = cross (id, g) cross({, id) . The right-ham! side of the originals . ...
= map parselaw [
equaifon i~ equalto f.~t cn)ss ({, id). . ~ ...
"xmatchlist: xmatchlist; = star union.cpr.cross(id,matchlist)",
We can now use the recursive definition of gmatchlist to get close to
"gmatchlist : gmatchlist =star union.cpp.cross(id,matchlist)'')-
result we ar.e after: . ' . . .
lawsS = originals ++ lawsl
laws4 = riewgmatchs ++ xrnatchs ++ assls ++ . lawsl
? prove laws5 "gmatt:hlist = star xmat.c hlist.cpl"
.:, .
? prove iaws4 "xmatchlist.cross(id,nil) =wrap. fst"
gmat'Ch 1i s't
-~ . ... .. .
406 12 I An au roma~!t; calcula 12.61 Chapter noles ..
. .. . .. .407 .
: . . ~

Since .-... . ..
'
' ... ,. . {gm atch list} . '' .'

.sta r union .cpp .cro ss(i d, match h st)


,;" {def cpp} ' . .
.... (oldl (Ell) e(Xs'-H; jis) = (old/ (Eil}({oldl (e) ,exs) ys
sta~ ~ni~n.st ar cpr. cpl. cros s(id , matc hl l st)
.. {cpl aft,:er id} . . . .
star unio n.st ar cpr.map(c ross (id, match l lst) ) .cpl
it is clear tha~ if {oldl'( f ) exS j s akft zero of Ell, then '

"' {star afte r map}


star unio n.star(c pr.c r9ss (id , matchlls . . {old/ (Ell) e (xs * .ys)
.
= {old I (ID) xs
t)).~pl
'

- {sta r afte r star } In wor ds, evaluation of {old/ .can be truncated as


star (sta r unio n.cp r.cr oss( id, mat chH st)) .cpl soon as a left zero is en
cou ntered. Definea function ..
,. {xm atch list} .
star xmat chli st.c pl ..
. doWhile :: <If- Bool) - {/3 - a- tn - 13- (a] - 13
i 2.5.4 Con clusions so that if p is an effe ctive test for left zero s of e, then
doJ-Yhile p (Ell) = fold/ (Ell).
Usin g doWhi/e in th e definitio n of gma tchlist ~ead s
The positive conclus io~ from the E!?{ercis~ _is that o~e to a pro gran1 with the sam e
lato r to assi st ill the constructiQn of deta iled p roof
inde ed c:~n get the. cru~:u~ efficiency as matchlist.
s. Ho~eve r, there
a nee d for hum an inp uno the pro cess, to set up app
rop nate ~aws , to ideotif 12.6 ChaiJler notes :
.eli d s and to con trol the order in which
sub st ary rum , calc ulations are
out. The maj or negative conclus ion is that some b
Jaws ha~e to : msti} ~
ud . .
Mik e Spivey's original calculat o'r was wri ttert iri Onv
a ~~~e com plic ated form than is desired, in orde
r to avOld havrng to '"'"n" ell, a predeces sor of Haskell;
other'law s in a .right to left, as well as left to right, alth oug h the pro gram has n't been doc ume nted in
direclio n. Tl;le fwlc tor the litcr atme, Spiv ey (1990)
.con tain s a ctisc ussiono n mat chin g and rewTiting exp
cau se p arti cula r trou ble in this respect. ressions. Ano ther in teract:
. : . .. . . ive equ atio nal reas oning assistan t for On-veil, called
Per haps the mos t in~eresting conclus ion of the exp ERA, is des crib ed iil Wils on _
en men t ts th~t ~~ . (1993).
see m a viable approach to eXJ?ress all laws as equ atio
ns bet~een funct!On_s, . Mec han ical tlieorem provi.J.1g and interactive proo f
assi stan ce form a large
to use~ sim ple equatio nal logic for proving results.
.. and buo yan t sub ject , and
doz ens of syst ems are available to the interes ted use
r.
We will n ot atte mpt to erm mer ate them , but the refe
rences in Cha pter 4 give
Exe rcises some p ointers. For ane asily accessib le reference, con
sult Pau lson (1996). This
t~xt des cribes the imp lem enta tion irt ML of a
12.5.1 Use the calc.ulat or to pro ve the laws of siar tactical theo rem pro ver called HaL
.
;~.S .2 Use the definition of ma;ch to get. a program for gm~tch that does The hidden agenda of this cha pter bas bee n to dem
ons trat e the adv ant
men tion union. ages of phra sing laws and pro ofs as equ ations betw
e~n functional exp ressions.
12.5 .3 The.pro of that matcl1list can be exp~esse d The mat hem atic al foundatiol)~ of nus app roac h is
rccur~ively in effect the subject mat ter of cat-
egory theo ry (see th e references cite d in Chapter 2).
that matchlist = foldr (cup, [( 1)). Apply the first However, for a truly viable.
du altty theo rem to o . met hod of specification an.d proof, one nee ds to repl
' ano ther exp ress ion for matchlist . ace runclional exp ress ions
by relation al ones, and equatio nal reas onin g by ineq
12.5.4 Consider evaluation of {oldl (Ell~ e. Say that z is
uational reas onin g. See
a left z~ro of Ell if zex Bird and de Moo r (1997)..for details.
for: all x. Prove that '

(old[ (Ell) Z XS = Z

for all finite lists xs whenever z is a left zero of Ell. How


,-'
f man y step s does it "'.-~_,,;.;,
i to redu ce the left han d side to z?
'
I '

"

' .. . .. '
~

. .. .!"
'
. .. .
~

Appendix: Som~ standard functions '


. . ' '
f
:.
!


'
~

.
Below, arranged in alphabetical order, is a summary of the most commonly (

used functions, together with their del'initions. In some cases, these definitions .
'
differ slightly from those foWld in the Haskell Standard Prelude;
' . '. .
.. . " . r
. 1. '(). FWlctional composition:

() :: (/3- ;y).- (ex - /3) - (a - .Y)


(f g) x =. f (g x)
. .
2. ( * ). Concatenates i:Wo lists: .. - ...-~

(* ) .... [ex] - (ex] ~[~]


U*YS - ys .
.";. (x : xs) * ys = x: (xs * ys) ..
i
3. (A). ConjW1Ction: . ,
'

(A) Boo/ - Boo! - Boo/ '
True" x - x
Fa lse A x - False
.. .
4. (v). Disjunction:
(v) .. Boo/- Boo/- Boo/
. ' True v x - True
False v x - x '

' '
410 .. . funcil~ns
Appefldbc Some standard . .. .. 411
. . I . . . .. .. . . . :;. . ..... ..

.. 5. (!!). List indexiilg: ' .


. .. 13. fi/terj Filters ayst wit!) ii.~(~~c~te~__
.
~: .
< . .
filter ::_ (a: Baa6.~ [aJ- [aJ
. ~!!) .. [a)- Inc- a
filter p [ ] . = [ ] .., .... .
error u(!!): index too large"
filter P ~x : xsf =: iLp' x,ilie~:x : filter p xs else filter p xs
[ l !! h =
.. . .. .
(X: .XS) !!.0 = X
.(x: xs) !! (n + 1) = xs !!'n 14. flip. Flips the a;gumen;;. t~ a:f~c~lon:
.........
6. and. Returns the logical conjunction of a list of booleans: flip .. (/3 - C( - y) ;-' a- 11 - )'
flip f Xy - I)' X ..
and. :: [Boo/] - Bool
ani = foldr ( 1\) True 15. fold/. Foldleft:

7. concat. Concatena tes a list of lists: fold/ .. ({3- a- 11> - f3- [ a) - 11


. . . . .. fold/ f e [ ) - e
concat _:: [[a)] - [a] fold/ f e (x: xs) - strict (fold/ f) (f ex) ,'(S
. . .F. foldr. ( *) [ ) . . ..
lists:
concat ~ '

16. foldll. Fold-left ove;. no11empcy


' \

8. canst. Crea.tes a constant-valued function:


foldll .... (IX- a - e<) - [a] - a
COI)St :; a - {3 - a fold/1 f [ J = ..error "fo/411: empty list"
!
const x.y
= '
x foldll f (x : xs) - {o(dI ( X ,''iS I

.I
9. cross. Applies a pair of functions to corresponcling elements of a pair: .17. foidr. Fold-right:
. .. '
cross :: (a- r_./3- 6)_- .(a,/3)- (y,6) foldr .... (~ ~ 13. ~ -tn , f3 - [ IXJ - 13
. . ..
cross (f, g) == pair (f fst, g snd) . foldr f e [] = e
a noncurried fun.ction into a cunied one:
foldr f e (x: xs) - f.x (foldr f e xs)
.10.. curry.. Converts
.
18. {oldrl. Fold-right over nonemptY.llsts:
.
cuny
curry f x y
::
=
((a, /3) - y)- (a- 13- y)
f (x, y) foldrl .... {ex-- C< - IX)- (a) - IX .,
I

foldrl f( J - error "foldr.l: empty list" I


11. drop. Selects a final segment of a list: foldrl f [x] =: X
foldrl f (x : xs) f x (f'oldrl f xs)
.... Jnr-
=
drop [a)- [a]
dropOxs - xs 19. {st. Selects the first compon~n t of a pair:
drop (n+1)[ ] - .[1
drop (n + l) (x: xs) = drop n xs fst :: . (IX, 11) - C< . .
.. ' .. '
=
'

. . (st (x,y) X
12. dropWhile. Removes the longest initial segment of a list all of whose
ments satisfy a given predicate: 20. head. Returns the first elt:ment of a nonempcy list:
head .. [a) - a .
dropWhile .. (a - Boo[)- [a]- [e< ]
head [] - error "head: empty list"
drop While p [ ] - [J
xs
jf p x then drop While p xs else x: xs head (x: xs) -
--
drop While p (x : xs)
.
-
.... . ..
..
' . ..
...
I
-~
' .''

'
: , ,_.~ t
'
l
: ~ ..
412 Appendix: Sdjne standard runctioIfs?l . .' )' \ppendix:.Some standard functions 413
.
. ....:
..
-~~
..

.. 21. id. The idenrity function:


... .:..::.. ~~-~ .;i;Y .
I
. ''
.-_.;, ~
. . '

: Z9. ~r.: R~~ris ~h~ }~gical disjunction of a list of bool~ans: I


... ..... ... :'
I'd :: .cx-'a - - .... '
or .. [Boo/]'- Bool
idx = x
or = {oldr (v) False
..... ..-- .
22. inic. Returns a 'list \vithout its last element: . '
. . ' 30. pair. Applies a pair of functions to an argument: .
init .. [a] - [{x] .
init [ 1 . - error "init: empty list" pair :: (cx ~ {J, cx - y)- cx- (/3,y)
init [x] - [)
. ( pair({, g) X ;= (f X, g X)
.... .
init (x: y : xs) - X: init (y : XS) \ ....

31. panition. Partitions a list accorcling to a given test (compare span and
23. iterace. Produces an infinite list of i terated applications of a Junction to
splitAt):
value:
iterate .. .. (ix - CX) - a .:.. (LX) .. partition :: (cx - Boo!)- [cx]- ((cx], ('-'<])
iterate f x - X: iterate ( ((X) .. . ,, .
partition p [ '] = ([].[])
, ..
partition p (x: xs) - if p x then (x : ys, zs) else (ys, x : zsi
24. IC1st. Retwns the last element of anonempty l_ist: ',
Where (ys, zs) = partitiof!p xs ,. -
.,.
last .. [cx] - cx
last [] - error ~last: empty list!'. 32. reverse. Reverses a finite list:
..
last [x] - X reverse .. [cx] -'- ( i:X]
last (x: y: xs) - last (y: xs) reverse - (oldl ({lip (:).) [ ]
25. length. Returns the length of a list:
.. ... .. ... 33.' seem/. Applies fold/ to every niltial segment of a list:
'
length .. [a] - Jnt ;

= 0
. sca~i 'I~ ?d .
length [] . . scciril : .:: . ({3- ci .- ID ,- j3- [cx] - [/3]
length (x: xs) - 1 +length xs = ~ ~ si:i:ml' f B' xs
:where scanl' f a [ ] = '[)
26. map. Applies a function to every element of a list .. ' scan/' fa (y: ys) - scan/ f (fay) ys
map .. (cx- {3) - (a] - [,8]
map f( ] . - [] 34. scanll. Applies {o/clll to every nonempty initial segment of a nonempty
' '
map'f (x: xs) = { x: map f xs list:
.,
-; .........:.:.:.:> -:. ..
27. nor. Negation: . , .. scarill .. (a - cx - cx) - [a] - [cx] ..
scanll f [] - error "scanll: empty list
not Boo/ - Boo/ . .. ,. ... .,..
scanll f (x : x.~) - scan! f x xs
not True = False .
~ . .... .
not False = True 3 5. scanr. Applies {oldr to eyery tail segment ()f illiSt:
28. .null. Tests a list for being empty:
scanr . .. (cx- {3- ,8) - f3 - [a] - [/3 ]
null .. [ cx) -Boo/ ,. scanr r e (] = [e] .
riull ( 1 . = True . scanr r e (x : xs) - f x (flead ys): ys
null (x ; xs) = False where ys = sc:anr f e xs

' I,
' I ' _. ' l

414 Append ix: Some stanaiu-~ "Appendix: SoiPe stan,ljArd ..functions 415 .
.' . .; .
.. .. .. .
..
.. .... '

..36. Applies ' (oldrl to every nonemply tail segment of a nonemp ty 43. take While. Selects th~ Longest initial sq,rment or a list all of whose eler~en ts
. scm1rl. . . ..
._
satisfy a givcll:.'p reai2ate:"
~
.. .
-
. .
scanrl :: (e<- e<- ex) 7" [ex]...,- [ex) . -
scanrl f(]: = ' error "scanr l: emp_ty list" _takeWflile ,-. =-. . .. :: (ex-Bo ol) -[ex)"' - (ex]
(J
scanrl f {x] - [x) takeWh ilep{J " =

scanrJ f (x: y_: xs) = f x (head zs) : zs . takeWhile ..p (?( ; ~) -'-- if p x then x : lake While p xs else [ )
.... .
where zs = scanrl f (y: xs)
. 44. uncuny . Conv~ts a curried fw1etio n to noncun;icd form:
37. singl~ton. Tes~s a list for being a singlet on list: uncurl')' :: (ex- /3- y) - (oc, /3) - ;y
singleton :: [ex)- Boo/ uncun y f xy :- f (fst :.y) (snd xy)
nul( (tail xs)
45. until. Applied to a predica te, a function, and a value, returns the result
singleto n xs = not.(nu l/ xs) A

38. span. Splits a list into rwo parrs: of applying the functio n to the value the smalles t numbe r of times in order to
satisfy the predica te:
span . .. :: (ex- Boo/)- [ex) - ([ix). [<X))
' p [ } :
span = ([),[)) . . until (ex- Boo/) - (C< - ex) - C<- C<
::
span p (x: xS) = if p x then.(x ; ys, zs) else ([ ], x : xs)
until p f x = if p x then x else until p f ({ x)
where (ys, zs) = span p xs 46. unzip. Unz.ips a List of pairs: ' .
. 39. spittAt.. sp uts
. a )1st tnto two parts
or given 1engr~1:
. unzip .. [ (ex~ /3>J.- ([C<). um
unzip = foldr f ( [ ). [ ])
Int.- [ex).- ((ex], [ex])
splitAt
- ([]!xs)
wh~rc f (x, y) = cmss ( (x :) , (y :) ~
splitAt 0 XS ' .
splilAt ( n-+ 1) [ ] = ([),{]) ' 47. wrap. Converts a value into a singletdn list
splitAt ( n +.l) (x : xs) = (x : ys, zs)
where (ys, zs) = splitAt n xs wrap :: ex - [ex]
' = [x]
. . wrap ~

. Selects the second


.40. snd. . compo nen t of a pair:
48. zip. Zips two lists:
..
(ex, /3)
'
snd . :: -13
= y zip .. [e<) - [,B) - [(ex, /3) ]
snd (x,y)
zip [) ys = . []
41. tail. Removes the first elemen t of anonem pty,list : zip (x: xs) [ J .; [ ]
zip (x: xs) (y: ys) =: (x, y) : zip xs ys
tail . . :: [ex.]- [c:x] ' ..
tail [ ] - error "tail: emply list" 49. zipp. The uncurried version of zip:
tai~ (x : xs) = xs
... zipp .. ([ex], [,8 }).:.. [(C<, {J)]
. 42. take. Selects an initial segmen t of a list: zipp . = wzcu~ty zip

take .... fnt - [ex] - [ c:x]


cake Oxs - [l ' .
.. cake ( n + l) [] - [)
take (n + 1) (x: xs) - x: taken xs -
.

...
,. . .....
1. . -': - .
.,
....
-
: .. :. . -.. ~
..' ...' . --

~- ':: . .. .:\l
"";:. .
M -
.. ...
.. .. . . . :. .
. ... .
. . ' -.. . ; __ . '
' . ' .. .
~ .. . . "' . .. .. .. .
.,
.' ' I '
..
' .;_ I o ~ ' ''

Blbliography
o
~ ~ ..~
' ~-

' '

...........
.;. .

... -
' ..
... - .a

.
1
.... . . ..
.... ,\
: .. ' : .. " .... .
' .. ;
. ' '

' . Adelson-Velski, G. M. and Landis, E. M. (1962). An algorithm for the organisation


of information. Soviet Matlwmatics Doklady, 3(5), 1259-1263. English
.. . translation in Doklady.Akademia Nauk SSSR, 146, 263-266.
. ..
-
'

. Aho, A.,. Sethi, R., ~mct u11ru'~. J. (1986). Compilers


. - PrinCiples, Techniq1,.1es and
. ' Tools. Addison-Wesley, Reading, Mass., USA. '
.

' I '

Andersson, A. (1993). Binary tree~ .made simple. In Dehne, F., Sack, J..-R.,
Santoro, N., and Whitesides, S., editors, Wori-shop on Algoritlim Design .
and Data Structures, Volume 709 of Lecrure Notes in Computer Science. ,.'
Springer-Verlag. ...
.' .... . .' . ' " "
Barr, M. and Wells, C. (1995). Categ01y Theory for Computing Science (second r
...
edition). Prenrlce..Halll~terii~tiona( i-Ieniel Hempstead, Herts, UK.
~
'
'
' ..... ..: ,, f :.. .. ._, .... . ~ . " . . ; . '
'
Bellman, R. E. (1957). Dynamic Progrll111I1liilg. Princeton University Press, Prin
'

ceton, USA.
Ben-Ari, M. (1993). Mathematical Logic for _Computing Science. Prentice Hall
. International, Heme! H~mpstead, Herrs; UK.
. '
Bentley, J. R. (1987). Programming Pearls. Addison-Wesley, Readirig, Mass., USA.
Bird, R. and de Moor, 0. (1997). Tlic Algebra of Programming. Prentice Hall
.. International, Heme! Hempstead, Herts, UK. -
. . . .. . ' .
Bird, R. s. (1980). Tabulation techniques for recursive programs. ACM Comput
.; ~

illg Surveys, 12(4), 403-417, . . :. : . '

Bird, R. s: (1984). The promotion and accum\'tlation .sn-ategies in 'runctional


'
programming. ACM Transactions on Programming Languages and Systems,
'

6(4), 487-504.

-..
\
,'
418 BibliogrC!PfiY
. .. , Bibliograpll y 419
.~ ... - . ~ . .. '
Bird, R: S. (1986). T(ansformational program.rillng and the paragraph problem. Fokkinga, M. M. (1992). L~1~ and Order in Algorithmics. Ph.D. thesis, Tecb,nical
Science
. of Computer Programming,
. 6(2), 159.:.189.,
. . University of nvente,.The
... . ...Netherlands.
Bird, R. S. (1989). Algebraic id.cntities for progrart;l calculation." Computer Gibi;JOns, ]. (1991). Algebr:as fo! Tree Algorithms. Ph.D. thesis, Programming
journal, 32(2), 122-126. Research Group, Oxfo~d Vniyersity, UK. Technical Monograph PRG-94.
Bird, R. S. (1991): Meertens' nwnber. tn Jewing, j., editor, Lambert Meertens, GOdel, K. (1990). Kurt G6del, Collected Works, Volume I. Oxford University
IJber Amicorwn, pages 4-10 Amsterdam, The Ncther1ands. CWI. Press, Oxford, Ul<.-Edited by:s. Feferman er al.
. Bjerner, B. and Holmstrom, S. (1989). A compositional approach to time analysis Gordon, A. (1993). . Functional Programming and Input/Output. Ph.D. thesis,
of first order lazy functional programs. 1n Conference ~n Functional Pro- . Computing Laborato.ry, Cambridge, UK. Published as a Distinguished Dis-
gram.ilwJg Languages anp Computer Architecture, pages 157-165. ACM. sertation by Cantbridge University Press.
. . . .
Boole, G. (1847). T/Je Mathematical Analysis of Logic. Cambridge. Reprinted, Gordon, M. J., Milner, R., and Wad~worth, C. P. (1979). Edi.J1burgh LCF, Volume 78
1948. by_Basil Blackwell, Oxford, UK. of Lecture
. .Notes in Computer Science. Springer-Verlag. .
Boyer, R. $. and Moore, J. S. (1979). A Computational Logic. Academic Press, Gordon, M. J. C. (1979). TlJe Denotatiomil Description of Progrnrruning Lan-
London, \.JK. guages, AlJ Int1oductio.n.. Springer-Verlag.
,. .
Burge, W. H. (1975). Recursive Programming Techniques. Addison-W~sley, Gordon, M. J. C. (1994). Programming Lallf:,'Uage 11Hwry and its Impleme{ltation.
Reading, Mass..USA." . Prentice Halllnternational, Herilel Hempstead, IIerts, UK.
. .
Burke, E. and Fc.>xley, E. (1996). Logic and its Applications. Prentice Hall Inter- . Graham, R. L., Knuth, D. E., and Pat~slmi.\<, 0. (1990): Concrete Mathema~ics; A
national, Hemel
. Hempstead, Herts, UK. . . Foundation fo~ Computer Science. AddisonWesley, Reading, Mass., USA.
Burs.taU, R. M. and Darlington, J. (1977). A transformational systen;t for devel Gries, D. and Schneider, F. B. (1995). A Logical Approach to Discrete Math. T~"ts
oping recursive programs. Journal of the ACM, 24(1), 44-67. and Monographs in Computer'sCience. Springer-Verlag. .
Church, A. (194 1). . TlJe CalcUli of Lamda Conversion, Volume 6 of Annals. of Gunter, C. (1992). Semantics of Programming Languages. Foundations of Com-
Mathematical Studies. Princeton Uruversity Press, Princeton, USA. . puting. t.irr Press, Cambridge, M_ass., USA.
Clack, C., Myers, C., and Poon, E. (1995). Programming with Miranda. Prentice Guttag, J. V. and Horning,). J. (1978). The algebraic specification of abstract
Hall International, Hemcl Hempstead, Herts, UK. data tjpes. Acta Informatica, 10(1), 27-52.
Cormen, T. H., Leiserson, C. E., and Rivest, R. L. (199_0): Introduction co Al Hall, C., Hammond, K., Partain, W., Jones, S. P., and Wadler, P. (1992). The Glas-
goritluns. MIT Press, Cambridge, Mass., USA. gow Haskell compiler: a retrospective. In ProccediJJ.gs of the 1992 Gl(Jsgow
Workshop in Functional Programming, Springer-Verlag Workshops in Com-
.
Davey, B. and Priestley, H. (1990). InlroductiOIJ. to Lattices and Order. Cambridge
University Press, Cambridge, UK. .. puting, pages 134-143. Springer-Verlag.
de Moor, 0. (199.4). Categories, relations and dynamic progranuning. MatlJem- Harrison, R. (1989). Abstract Da.ta Types in Modula-2. John Wiley and Sons,
, . ' Chichester, UK.
atical Struclures in Computer Science, 4, 33-69.
Hoare, c. A .R. (1962). Quicksor.t. 'compuccr Jownal,
,' , ' o " I . "

Dielis~en, V. ]. and Kaldewaij, A (1995). A simple, efficient, and flexible im- S(l), 10-15.
plementation of fle'xible arrays. . bi r-.1oller, B., editor;' Third Intemational Hofstadter, D. R. (1979). G6del, Escher, Bacll: An Eternal Golden Braid. Har-
C<(nference on the Mathematics of Program Construction, Volume 947 of . vester Press, Hassocks, Essex, U~.
'Lecture f!otes in (omputer,S(:ieiJce, pages 232-241. Springer-Verlag.
Hoogerwoord, R. (1991). A .!ogmithniic implementation of flexible mTays. In
Fokker, J. (1995). Functional pm:sers. In Jeuring, ]. and Meijer, E., editors, Ad- Bird, R. S., Morgan, C. C., and Woodcock, J. P. C., editors, Second Inter-
vanced Fun ctional Programming, Volume 925 of Lecture Notes in Computer national Confel'en.ce on 'tlJe Matllcma!ics of Program Construction, Volume
Science, pages 1-23. Springer-Verlag. 669 of Lecture Notes iJJ Computer Science, pages 191-207. Springer-Verlag.
I ...'
i .

4~0 : . .Bibliography .. Bibliography


' '
.. '

. -: ' .. ~ ,... ~..


. ,.~; ~~ :-:-.

Hu, T. C. (1982): Combinatorial Algorithms. AddisoQ,:We~ley..~Reading, Mass., Knuth, D. E (1981) T. 1Je Art ofCompuc'er Programm.irl' - . .
. ~ : .-.......~;. -~ ..::~.._./,
USA ,. . . . ;,,
.. gomhins (second edition) Vol , . . . . . g. Sel111!1umencal AJ. . .
Hudak, P., Fasel, J. and Peterson, J. (1996). A gentle introd~ction to Haskell. USA. ~ .. umc 2 Addison-Wesley, Reading, .Mass.,
Technical Report y ALEtl/DCS/RR90L yale.u~~ersi~; .. ~S'A Knuth, D. E .and Plass, M. F. {1981) Breakin . . .
Huffman, D. A. (1952). A method for theconstruction o'f Ulinlmum redundancy Practice and Experience, ll, ' _ _g paragraphs mto lines. Softwar~
11 19 1184
codes. Pro_ceedings of the IRE, 40, 1098-llOl. : ' ~ : :: .
Launchbwy: J. .(1993). Lazy imperative pr
Hughes, R. ]. M. (1~84). The Design and Implementation of Prograinmi.ng lan- . ACM SigPlan Workshop on State in P ogrami~mg. In !'roceedings of the
[J}Jages. Ph.D. thesis, Programming Research Group, Orlord University, Ox- sity of Yale Resear.ch Report, YALEU/';fsa/~R-96g8.LNanguages. Also Univer
ford, UK. :~ff~~ . . . , ewHaven, USA.
Liang, S., Hudak, P., and Jones M (1 995) M . d , . . .
Hughes, R. ]. M. (1995). The design of a pretty-printing library. In jeuring, J. ona transfomers and d 11
. mterpreters. Tn Proceedings of the 22ncl AC'-' . mo l ar
and Meijer, E., editors, Advanced Functional Pmgtamming, Volume 92 5 of Prog~' lm""i"a
w .u,;:,
L anguages. '
11
Conference on Principles of
Leccure Notes in Computer Science, pages 53-96. Springer-Verlag. ' .
Malcolm, G. R (1990). Algebraic Data T . . d P.
Hutton. G. (1992). ~Jigherorder functions for parsiflg. Jou.rnal of Ftwcrional thesis, University of G. . , yp~s an TOgram Trm1sformarion. Ph.D.
Programming, 2, 323-343. , . . . I onmgcn, Grorungen, The Netherlands.

Hun on, G. and Meij(!r, E. (1996). t-1onadic parser combimitors: Draft manuscript. Mar:;~1t ~e~~~t~;~~1J:.~:~~~Data Struc.tu,res. Pl:e.nclc~ Hall International,
ISO '(1989). A character set for Western European languages:ISO Standard Martin, U. and Nipkow T (1990) A . .
8859-1. '
' ' '

. utomanng.sqmggol. In Broy, M. and Jones :


'
'C B editors p ' .
'
..
rogrammmg Conce r d
Jeuring, ]. (1993). Theories for Algorithm Calculation. Ph,D. thesis, University .,.,..,"'" terdam, The Netherlands. North-H~I=n~~ . Methods, pages 223-236 Ams-
o.f Utrecht, The.Netherlands.
Meerrens, L G. LT. (1987). First ste s tow . . ..
Jones, M. P. (1992). Qualifled Types: Theory 'a nd f'ractite. Ph.D. thesis, Pro ,.""~'" . Report, Ci-Vl, Amsterdam, The N~ther).a~:s~ .the theory of rose trees. Draft
gramming Research Group, Oxford University, Oxford, UK. M.. . . . .
eiJer, E. (1992). Calculatmg Compilers Ph 0 th . U . ..
jones, M. P. (1993). Release notes for Gofer 2:28. User manual for Gofer. The Netherlands. .. CSIS, ruvers1ty of Nijmegen,
:

Jones, M. P. (1995). A system of constructor classes: overloading and .......~u~.. .


higher-order polymorphism. Journal of Functional Programcnilig, 5(1), 1- Moggi, E.: (1989). Computational lam~da-calculus and d
p osmm L . mona s. In IEEE Sym-
35. . on !fl~ m Computer Science Asilomar, Calif., USA.
Moggi, E. (1991). Notions ofcomput c d .
Jones, S. P., Gordon, A., and Finne, S. (1996). Concurrent .Haskell. 93, 55-92. a Jon an monads. Information and Co!ltrol,
ACM Symposium on Principles Of Programming Languages, St. Peters:ou rf!
Florida. ACM. Morgan, C. (1996). Programming l S n . . .
Hall Int . . . rom .peq 1cacJons (Second edition). Prentice
Kaldewaij, A. (1990). Programming: The Derivation of Aifjori'thms. Prentice Hall. emanonal, Heme! Hempstead, Herts, UK. . .
H~'P.'r'. ::
111
~ternationaJ, Heine! Hempste'ad, Herts, uK: . . ... ~kasaki, C. 0 995). Simple and efficient pur 1 f . . .: .
Knuth, D. E. (l 973a). . The Art of Computer Programming: FWJdamenm.I "' ":">1~,., Journal oi' Functional Programming, S(4 ~' ~ 8 ~~~~.~a~ ~ueucs and deques.
gorithms (second edition)., Volume 1. Adclison-Wesley, Reading, Mass., . Okasaki, C. (1996) Purely Fu t'O 1D .
USA. Computer Sci~nce, Carne~~~ ~~~~on ~:~:;;:~~~s~~~~h~l~;~ School of
Knuth, D. E. (1973b). The Art oJ'Compurer Programming: Sorring and Se<Jrching, Paulson, L. C. (1983). Remiting In Cambridge LCF . .
. Volume 3. Addison-Wesley, Reading, Mass., USA. . . grarnming, 3(2), 119_
149
_ Science of Computer Pro-
. '
. , ... ~ . w

422 BibliograpiJy 423

Paulson, L C. .(1996). ML for the Working Progr ammer (second edition). Wadler, P. (1984). J,J.s(les~pess is better tl1an Laziness. Ph.D, thesis; School of
bridge University Press, Cambridge, UK. Computer Science, ~arnegie Mellon University, Pittsburgh. USA. .~ .
Penrose. R. (1994). Shadows of the Mind. Oxford Univer~ity Press, Oxford, Wadler, P. (1985). How. to replace failure by a list of successes. ln Second J.n cer
n ati onal Conference oil Functional Programming Languages an.dCompurer.
Pettorossi, A. (1984). Methodologies for transfor mations and memoing in
plic~tive languages. Pb.D. th esis, UniversitY of Edinburgh, Edinburgh , UK. ~ Archi~ecture,. Voli:une~2oi of Lcctu1e Notes in Computer Science. Springer-
Verlag.
Peyton Jones, S. (1987). Tile lmplementation of Functional Programming
Wadler, P.. (198. 7). Strictness analysis aids time analysis. 'In Proceedings of the
. Hemel Hempstead, Hcrts, UK.
. . Prentice Hall International,
. guages. '

~ 14th ACM Symposium on rile Principles of Programnpng Languages, pages


Peyton Jones, S. and Les ter, D. (1991). Implem en ting Functional Languages.,. 307- 313 .
Prentice Hall International, Hemel Hempstead, Hen s, UK.
Wadler, P. (1989). Thcorc ~s for free!. In Proceedings of the 16th ACM Sym-
Pierce, B. C. (1991). Basic Category Theory for Computer Scient1sts. Foundations of Pr ogramming Languages, pages 347-359.
of Compu ting. MIT Press, Cambridge, Mass., USA.
.
posium on Principles
.
'
Wadlcr, P. (l990a). Comprehending monads. In Proceedh1gs of the A{:tvf Sym
Pitts, A. and Dyber, P., editors (1997). Semantics and Logics of Comp utation.,
'
posiuin on Lisp and Functional Prograrrfiili.ng, pages 34 7-3 59. Also in Math
Publicat~:oos of the Newton Institute, Cambridge University Press, Cam emalical Structures ill Computer Sci ence, 2, 461-493, 1992.
bridge, UK.
Wadler, P. (1990b). Deforestation: transforrning programs to eliminate trees.
Rlmci.rilan, C. and ROjemo, N. (1996). New dimensions in h eap profiling. Journal Tlleoretical Computer Scien ce, 73, 231-248.
of Functional PrograrnmirJ.g, 6~4), 587-620.
Wadler, P. (1995). Monads for functional pro.gramrning. In j eurin g, j. and
Sands, D. (199 5). A naive tin1e analysis and its theory of cost eqUiValence. Meijer; E., editors, Advan ced Fun ctional Prograrnming, Volume 925 of Lec-
Journal of Logic and Computation, 5(4), 495-541. ture Notes in Computer Science. Springer-Verlag.
Schoenmakers, B. (1992). Data Structures and Amortized Complexity fu a Func Wacller, P. and Blott, S. (1989). How to make ad hoc polymorphism less ad hoc.
tiona] Settiilg. Ph.D. thesis, Eindhoven University of Technology, Eind ~ Proceedingsor'rhe 1 6th ACM Symposium on Pri.Jlciples of Prograauning
hoven, The Netherlanas. Languages, pages 60- 76.
~ Scott, D. (1976). Data types as lattices. SIAM journ al of Compur:i.ng, 5, 522-587. Wilson, S. P. (1993). Equational reasoning supp ort for Orwell. Technical Re
Scott, D. (1982). Domains for denotational semantics. In l.ntemarional Col- . port PRG Monographs, PRG-104, Oxford University Computing Laboratory,
loquium on Aurornara, Languages and Progr ainming, Volrnne 140 of Lee Oxford, UK.
cwe Notes in Computer Science,.pages 577- 613. Springer-Verlag.
Sijtsma, B. (1988). Verification and Deri vation of lnfinitelis.t Programs. Ph.D.
thesis, University of Groningen, The Netherlands.
Spivey, M. (1990): A fun5=tional theory of exceptions. Science of Computer
Progr a.mmiJJg, 14, 25-42.
Stoy, j. (1977). Denot~tional Semantics: Tile ScottStracbey Approach to Pro
. gramm irig LaL~guage..Th eOiy. MlT Press, Cambtidge, Mass., USA.
Thompson, S..(1995). J\fir.;p.~da; Tile Craft of Functional Programming. Addison
Wesley, London, UK.
. ' '

Thompson, S. (1996). Haskell: Th e Crafr of Funcrional Progr ammi11g. Addison-


. Wesley, London, UK.

'
PAGES MISSING
sorry:-(
. .. t... ..

426 Index 427


" .Index
,.... '
. ......
..
.:
. .. :- ;

asymptotic data ~eclararions, 29. equational axioms, 253, 256


.. . . .. analysis, 222. . chain completeness, 302 ..
data compression, 2.02 .....: ;- :: equations, 2
asYJDptotic exact bounds,.224
asymptotic lower bounds, 22.4
chain of approxim;:1tions,
Char 35
30.0, 315::
'.,._ ... ; ,;:.
- " .. datatype declarations, so; i8.7, 251 error, 20, 23
data type invaiiant:,;, 1:88,:'192,255
I ' '

asyrnptotic upper bounds; 223 characters. 35, 55 error handling, 334


. ,. .
augmented nees, 185 datatypes,
' 29 . . .. ..,., error messages, 8, 20, 23, 53, 327; .
chr,36 .
~

amdliruy-results. 1oo. 111',129. Church booleans, 86 de!=imals, 121 _. . .. ::-~ . 335


avera~e. 238 Church numbers, 86, 89 default definitions, 32 escape sequences, 55
average-case analysis, 224, 246 definitions, 1, 17 Euclid's algorithm, 80
class methods, 32
AVL trees, ?70, 293 deforestation, 213,.244 evaluation, 1, 4, 22
clauses (in guarded equations),)8
axio.matic specifications, 252 deletion, 189 evaluators, 334
closure problems, 309
depth of a node, 182 Example
collapse law, 346
backspace characters, 322 depth-first order, 199, 212, 230 arbitrary-precision arithmetiC,
combinators, 398
Backus-Naur form, 369 combining monads, 351
deques, 292 lSO
. bags, 251,276 . .-. . . deriving clauses, 40, 4 7, 53 automatic calculator, 375
conunands, 51,325
balanced trees,._. 2.70 , .' deterministic parse~s. 362 class lists, 142
. ... commutativity, 67, 74
beside, i64 dictionaries, 264, 2'70 ' convening numbers, 1'39
compariso(l operators,see (s;),
best-case digits, 150 Hamm1ng's problem, 30$
. . analysis,
. 224 .
(<), (~).and(>)
bi11~y representation. 8 disjoi.r,n patterns, 103, 104 hangman, 3 31
compatible substitutions.396
binary search, 81,89 'disjunction, see (v) Huffman trees, 202
complete partial ordering; 300 leap years, 33.
binaiy trees, l79, 187 div, !3, 77, in; 155 ,,I
computtJ.bl~ equality, see (==) . divide and conquer, 148
bindings, 3, 220 linear and binary search, 81 .!
computable functions, 30~ division, 8, 74, 76,78, 155 maximum segment suni, 134
. bit-patten.ls, 8 i
computer arithmetic, 89 do notation, 329 . Meertens' number, 209
. boo~keeping law, 132 . , "I
;I
cencat, 98, 226, 348,410
Boo!,. 18, 29, 86. .. , ... domain theory, 299, 322 paper-rock-sdssors game1 311
' ~

concatenation, see (*) Double, 75, 78 position in a list, 117 :J


boolean algebra, SS
concrete datatypes, 251 drop, 104,410 printing a calendar, 161 I
booleans, see Bool
bottom, see 1.. conditional expressions, 17, 29,. 33,. dropWhi/e, 115, 148, 410 Pythagorean triads, 113
329 duality theorems, 128 quadratic ei:.tuations, 44
Bounded,l23
conjunction, see (I\) rational aritlunetic, 78
brackets~ 91
breadth-first order, 199, 211 Cons, see (:) eager eyaluation, 220, 224 square roots, 84
cons!, 185, 410 efficiency, xi, n, 26, 71, 99, 107, text processing, 169
building a tree, 233
. constructors, 38, 41,46 117, 123, 135, 146, 148, triangles, 3 3
C,32S contexts, 3 175, 184; 186, 189, 267, exception handling,. 335
. ,:.
calculations, F6, 381 . continuous functions, 301 366,369 exception monad, 351
empty l!s t, see [ 1
. . . ""
canonical representations, 4, 8, 78, control codes, 55 exceptions, 335, 352 .. ~

Enum, 3'9, 155 !I


81, 265 . . cross, 42, llQ, 1'45, 377, 410 execution traces, 334
l!i
cartesian PI:Oduct, 41 , ~- .curried fwKtions, 12, 266, 382 enumerations, ~8 existential quantification, 70, 302
environments, see contexts " exponentiation, 14, 59, 88
' I , , '

case analysis; 93 . curry, 13, 23, 25, 43, 410


Eq, 32, 37, 59, 76, 79,93,94, 153,
If
'case exhaustion, 60, 72, 95 cmrying, 11, 12, 19 7, 241 expo'rt lists, 262 ,II
265
'I
caregory theory, 28, 42, 4 ~: 55, cyclic lists, 295 . expressions, 1, 179, 381 :I
110,111,343,350,407 cyclic structures, 306, 310 equality operators, see (==) and ( :f.) extensionality, 10, 44
.. :r

I
.!
. . . -'
:II
I~
.
428 Index Index . 429
.
, '.
.
. '. ;. .
. . . _; ... ..'
external nodes, 179 functional coi:n~osjtion;: see (,) id, 412 last, 102, 412
functions 9 .. . : .. ..._ . : identity funcqon, 71 .. .. laws, 381
no;
.;,
I . ' \ . .. --.

fact, 19,23, 71, 76 . functor properties. 176, 184, -identity monad, 339 Jaws of fold, 128 '
factorial functio~ see fa~i . : ., 349, we< . ..
:~: iinp~ratlve programimng~ 325, 333 laws of list comprehensions: . .'u4
factoring parsers, 366, 371
I
' I fusion, 72, 131, 137,.176, 244,247 implementation hiding, 263 layout, 21, 330 , l,;.
l False, 29 : ; fusion theorem : _- ~~::: implementations, 25, 254 lazy evaluation, 6, 9, 43, 2'1 7{220,
Fibonacci function, ' .
. . 21, 61, 71, 2~4. for fold/, 13-i import declarations, 263 225,371
271 for f'oldn, 73 indexing a tree, 186 .. leaf nodes, 179 ,, ,.,.
file-handling primir~ves, 332 'f9r foldr, 131, 244 .. ,. induction,x, 57., 63, 72, 93, 137, leafnees, 283 , :
i8o, 195, 297 . .
. '
filling paragrapgs, 174, 235 leapfrog la\v, 347 "
filter, 109, 111, 411 Galois correspondence, 275 induction hypothesis, 63 least upper bounds, 300
finitary trees, i95 game semantics, 323 inequational reasoning, 407 left association, IS '
finite differencing, 244 garbage collection, .221 infinite lists, 84, 97, 2.95 left inverses, 39, zss '
finite trees, 180 gcd, 78,80 infinite loops, 377 left subtree, 179
first duality theorem, 128, 176, 243 general tr ees, 21 s . . infinite nup.lbers, 61 left unit, 63, 73,343 ....
flat ordering,. 299 .'
generalisation, 100, 129
~

infinite sets, 296 . , .. left zero, 406 '


flattening a tree, 229 generator functions, 309 infinity, 5, 8, 68 . left'perfe'c ftrees, z8,4 .r ., .
flexible arrays, 281 generator. rule, 112 left-recursion problem, 371
. ' \ ' ' .
init, 102, 412 "
flip, 25, 122, 411 generators, 112 initial segments, 124, 135, 203 length, 102, 130, 4 !2
Float, 3; 8.-.:57, 75, 78, 252 Gofer, x, 28 inits, 124, 236 . .
.
lexicographic ordering, .45, . . 51, 94,
floating-pq~t numbers, see Float grammars, 369 innemi~si're'duction, 2is, 240-'
'

152 :'
floor function, see L J graph reduction, 21~ insertion; 1S9 .. libraries, 3, 137 ,
fold functions, 70, 120, 128, 184, .
graphs, 306 . - .
': . ;-

insertion sort, 14 7 limited-precision mtegers, se~ Int:


19.7 greatest common divisor, see gcd instance declarations, 32, 39, 45, , limits, 298 .
.,
. '
fold-concat fusion, 132 greedy algorithms, 174,'235 s1, 93~ '' ' . ~ ' ..
. line editor, 261'
. .
fold-map fusion, 131 guard rule, 112 ' ' Int, 33, 36, 57, 75, 1SO
~ '

linear congmential metho'd, 317


fold~scan fusion, 133 guarded equations, 18, 21, 44; 80 . 3, 57, 75, 150 '
linear search, 81, 89
.
Integer, ~

{old/, 122, 226, 241, 243, 407, 411 guards, 18,n2 integer overflow, 75 . lines, 169
{oldll, 123, 411 Integral,77, 155 list comprehensions, 112, 296
foldn, 70 Haskell, x, xi; 2, 6, 12,18, 28, 39, inrensionaliry, 11, 22.4 list,index,'see (!!)
foldr, 120, 152, 243, 411 . 50, 75, 88, 137-,155 interact; 320 . list notation, 91 . .
foldrl, 123, 411 head, 102, 411 "
interaction, 258, 259, 288, 295, local defini tions, 20,.44,
. ... 82,. 213,
formal differentiation, 244 head-normal form, 240 ~ 319,325
.
2.20
Fractional, 78, 80 heaps, 192-194, 278 internru nodes, 179
,

{romfnteger; 76 . heapsort, 194 interrupts, 9, 45, 96, 295 map,109, 184,197,348,412


{romRational, 78 height of a tree, 181 . 10, 51, 320, 32S matching, 377, 387
fst, 41, 411 height -balanced trees,. 2 70 isomorphic dararypes, SO mathematical equa.Iity, : .~ee ('::)
fuU induction; see induction hidden constmctors, 276 iterate, 211, 303, 307~ 377, 412 marheimiticaln6'ration,z
function type operator, see ( -) Horner's rule, 122 merge, 192, 309
ftmctional application, 10, 12, is, Huffman coding,.~02 -: . labelled trees, 187 merge sort, 148
44 . HUGS, x, xi, 28 . . . . ' A:calculus. 86 merging, 267, 277
. '
' 1:
.'

430 Tndex
. . . 431
. .
... ~
. .. . .. . '

x,
Miranda, 28, 75 null, 93, 412 pretcy prlnting,.373 . ... rewrite rules, 5, 30.
ML, 28,4.07 nullary tuple, see () primes, 210, 297 .., . :; .. . right association, 15
mod, 13, 77, 1.55 Num, 24, 76, 153-160. - ~<-~' primitive operations, 3, 4 . right spines, 2 79 .
modularity, xi numbers, l , 24, 29, 75- . , principle of optimality, 236..... right subtree, 179 .
. module d eclarations, 262 numerals, 2, 7, 53, 121, 150 priori{}' queues, 2?T right tmit, 63, 73,343'
modules, 262 nujneric type classes, 76 . proc~dures, 11 right-perfect trees, 285
. modulus, see mod . program derivation, see program rose trees, 195-201, 209
monad composition, see ( o) operators, 13 synthesis .
monad laws, 343 or, 413 program synthesis, xi, 27,28, i58, scalar product, 116
monad morphisms, 359 Ord, 32,37, 59,79,153 124,173,191, 198,229, scanl, 124, 156, 163, 413
monad transformers, 351 ord, 36 24 6,395 scanll, 126, 146, 176, 413
monadic evalualion, 339 order notation, 222 prompt sign , '1 scanr, 125. 413
monadic interaction, 325 otherwise, 34 proof format, 26, 64 scanrl, 126, 414
monadic parsing, 362 outermost reduction, 218, 240 p seudo-random .numbers, 31) , 317 scope, 20,44
monadic programming, 325 overloaded operations, 31 putStr, 51 , 326 scripts, l , 2, 263
monads, x, 328 search trees, 187, ~68 i
monoids, 343, 348, 364 pair, 42, 118, 377, 413 qualifiers, 112 searching, 188 f
monotonic fWlctions, 301 paragraphs, 173-177, 235 quasi-perfect trees, 282, 285 second dualicy theorem/ 128
multiplication, 2, 6, 14, 21, 59, 76, parentheses, 10, 11, ~3, 15, 31, 60 queues, 25 1-258,287,32 2 sections, 14, 34 7
88, 154 parsing, 361, 383 quicksor t, 189, 245-248 semi-colon, see layout
multisets, 276 partial lists, 96, 97, 102, 296 quotation marks, 35, 51, 53 separator charq.cters, 170
partial numbers, 61, 67 ... separators, 368 .
'
Nat, 57, 76 . . . panial operations, 60 Rational, 77, 78. .. . sesslO.QS, 1, 2, 336 ..
natural numbers, 62 partial ordering, 299 rational numbers, 75, 78.. set representation s, 189
naturality properties, 111; 119, partition, 189, 246, 413 Real, 77, ~ 55 set theory, 296
. r(!cursive daracypes, 57 set union,98
137, 144, 176, 349 partitions, 390
neg_are, 76; 154 Pasc~l. 325 recursive datatypes, x, 4 Z.. sets, 98, 25 1,264, 296 .
n egativenumbe rs, I SO . pattern matching, 29-3~, 36, 39, recursive definitions, i9; 57 ' Show, S2, 60,V6, 79,159, 2~2 , 336
.newline characters, lu9 46,60,'92, 103,104,116, recursive functions, x show, 52, 79, 160,232,336
newline characters, l, 36, 55, 326, 142 red-black trees, 293 show monad, 351
328 perfect trees, 182, 196, 229 redex, 218 showsPrei:, 159, 232
Newton's m ethod, 84 rr, 4, 8, 17 . reducible e.xpressio~ see red ex sieve of Eratosthenes, 297
oewrype declarations, 49-50, 150, pictures, 163 reduction, 4 signed-comple ment
. .
262,263 point-free, 11 , 16, 43, 44, 114, 118, reduction rules, 6 representation , 154
nondec, 116 143,375,406 reduction sequences, 4, 5', 19, 26, signeclmagnit ude representation,
nondecwising 9rder, 116 point-wise, 11, 16, 114' 41., 217, 240 -. . . 154
nondetermini~~ 265 pointers, 219 . repeat, 307 signum, 18
nonstrict functio.n s .9, 46, 243, . polymorphic functions, 13 7 representations, 7 simplification, 4, 6, 101
normal form, 5, 30, 151 p olymorphic types, 22, 11 1 results of functions, w singleton, 207, 414
normal-order reduction, 219 precedence, 10, 14, 31 reverse, 99, 122, 130, 222, 226, size of a tree, 181
not, 30, 412 preludes, 3, 13 7 289, 413 ... smaller, 2
... '
. ' .

..
,.
... ......
.;

433
432
:
. . ,..-
. . .. .-....
~
.
uncu~,l3, 17,43 ,415.
1 , ... ::

snd, 41, 414 tail segm ents: 1.26, ~35.


, _. _ und-efined value, see 1.
snoc-lists, 94 tails, 126, 236 .:
unjt, 63
sortby, 1_44, 147, 206 take, 104, 300, 30(?, 4i4
takeWhile, 11:5, 148,.175, 297,4 15 .universal quant1fication,70, 302
sorting, 35, 127, 144, 147-1 48, unlines, 147,1 69, 170
. ,189, 194, 3'03 . targe t type; 19 . '
until, 81,41 5
sortwith, 149 termi nal symbols, .370
unwords, 171
sourc e..rype, 10 termi nation, 6-8, 19, ;119
unwrap, 183
space chara cters, 36, 55, 169 termi nator characterS, 170
unzip, UB, 415 .
space efficiency, 107, 148, 200, terms , 382
uppe r bound s, 300
201, 212, 221, 238, 239, text formatting, 172
246 text proce s.sing, 369 . valid repre senta tions, 255
space leaks, 246,3 73 theor em proving, 3 75 values, 7, 22
span, 148,2 38,41 4 third dualit y theor em, 130, 198, variables, 2, 3 77
specifications, 25, 39, 68, 81, 134, 229 '
. 144 . well-formed expre ssion s, 8, 21
splitA t, 107, 183, 238, 414 wher e clm,ises, 20, 308; 330
sqrr, 3, 84 white sp~ce, 368
square, 2, 5, 6 width (of a tree), 195
s tanda rd funct ions, 137 words, 171
state. 336 worst-case analysis, 224, 225
state mona d, 351 wrap, 185, 415
state trans forme rs, 337
s tream-base d intera ction, 319
strict, 240 '

strict funct ions, 9, 30, 43, 7 2, 111,


242,2 43,25 3
String, 38, SO, 92
string s, see String, 92
stron g typing, 22
srruct~al induc tion, see induc tion ..
-- ~ '
subcl asses, 32
subst itutio ns, 6, 377, 387
subtr action, 60~ ~8, 76, 153
successor funct ion, 12, 57, 76, 87,
. 240
synta ctic categortes, 370
synta x,8, 22,41 ,179
synta x errors, 22
unary minu s, 14
tab chara cters, 169, 172- l 73 uncur ried functions, 13, 118, 143,
rail, 102, 414 382

.. .........
'

Vous aimerez peut-être aussi