<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/teaching/2627/FoundsCS/forest/default.xsl"?>
<fr:tree
xmlns:fr="http://www.forester-notes.org"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
root="true"
base-url="/teaching/2627/FoundsCS/forest/"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:contributor>Lawrence C. Paulson</fr:contributor><fr:contributor>David Allsopp</fr:contributor><fr:contributor>Jon Ludlam</fr:contributor><fr:contributor>Jeremy Yallop</fr:contributor></fr:authors><fr:date><fr:year>2026</fr:year><fr:month>10</fr:month><fr:day>1</fr:day></fr:date><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/index/</fr:uri><fr:display-uri>index</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/index/</fr:route><fr:title
text="Foundations of Computer Science (2026–27)">Foundations of Computer Science (2026–27)</fr:title></fr:frontmatter><fr:mainmatter><html:p>See also the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>, the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-topics/"
title="Topic index"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topics/"
display-uri="focs-topics"
type="local">topic index</fr:link> and the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-all-exercises/"
title="All exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-all-exercises/"
display-uri="focs-all-exercises"
type="local">collected exercises</fr:link>.</html:p><html:p>This course has two aims. The first is to teach programming. The second is to
present some fundamental principles of computer science, especially algorithm
design. Most students will have some programming experience already, but there
are few people whose programming cannot be improved through greater knowledge
of basic principles. Please bear this point in mind if you have extensive
experience and find parts of the course rather slow.</html:p><html:p>The programming in this course is based on the language <fr:link
href="https://ocaml.org/"
type="external">OCaml</fr:link>
and mostly concerns the functional programming style. Functional programs tend
to be shorter and easier to understand than their counterparts in conventional
languages such as C. In the space of a few weeks, we shall cover many
fundamental data structures and learn basic methods for estimating efficiency.</html:p><html:p>The first thing you will notice about this course is that there is an
<html:em>interactive</html:em> version hosted online at <fr:link
href="https://hub.cl.cam.ac.uk/"
type="external">hub.cl.cam.ac.uk</fr:link>, where you
can login with your Cambridge Raven identity and edit the code fragments in
your browser.  You are encouraged to do so — such edits will only persist in
your session, and will help you to explore the world of functional programming.
If you are using the web-based version, then you need to know a few concepts:</html:p><html:ul><html:li>The notebook consists of a sequence of textual and code snippets.</html:li>
  <html:li>The code snippets can be executed individually, and will “remember” the
  results of the previous snippets.</html:li>
  <html:li>To begin with, click on <html:code>Cell</html:code> / <html:code>Run All</html:code> in the menu to execute the
  entire notebook.</html:li>
  <html:li>You can later double click on any cell and modify its contents, and
  press <html:code>Shift+Enter</html:code> to reevaluate its contents.  This will only modify
  the current cell, so you will have to <html:code>Run All</html:code> again to see the effects
  on the whole notebook.</html:li>
  <html:li>While editing longer snippets, you can also press <html:code>Shift+Tab</html:code> while
  typing to get more documentation hints about the code you are writing.</html:li></html:ul><html:p>This course is lectured by <fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link> and Jon Ludlam.  These notes
are translated from Lawrence C.
Paulson’s earlier course on Standard ML, which had credits to David Allsopp,
Stuart Becker, Gavin Bierman, Chloë Brown, Silas Brown, Qi Chen, David
Cottingham, William Denman, Robert Harle, Daniel Hulme, Frank King, Jack
Lawrence-Jones, Joseph Lord, Dimitrios Los, Farhan Mannan, James Margetson,
David Morgan, Alan Mycroft, Sridhar Prabhu, Frank Stajano, Alex Trifanov,
Thomas Tuerk, Xincheng Wang, Philip Withnall and Assel Zhiyenbayeva for
pointing out errors.  The current notes were ported to OCaml in 2019 by Anil
Madhavapeddy, David Allsopp, and Jon Ludlam and subsequently edited by
Jeremy Yallop. We thank Richard Sharp, Srinivasan Keshav, Ambroise
Lafont, Vojtěch Tvrdík, Jeremy Yallop, Alexandra W. Chadwick,
Richard Mortier and Alex Nelson for further feedback and corrections since 2020.</html:p><html:p>Some books that are complementary to this course are:</html:p><html:ul><html:li><fr:link
href="http://ocaml-book.com/"
type="external"><html:em>OCaml from the Very Beginning</html:em></fr:link> by John Whitington.</html:li></html:ul><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/</fr:uri><fr:display-uri>focs-intro</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-intro/</fr:route><fr:title
text="Introduction to Programming">Introduction to Programming</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-basic-concepts/</fr:uri><fr:display-uri>focs-basic-concepts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-basic-concepts/</fr:route><fr:title
text="Basic Concepts in Computer Science">Basic Concepts in Computer Science</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Computers: a child can use them; <html:strong>nobody</html:strong> can fully understand them!</html:li>
  <html:li>We can master complexity through levels of abstraction.</html:li>
  <html:li>Focus on 2 or 3 levels at most!</html:li></html:ul><html:p><html:strong>Recurring issues:</html:strong></html:p><html:ul><html:li><html:em>what services</html:em> to provide at each level</html:li>
  <html:li><html:em>how to implement</html:em> them using lower-level services</html:li>
  <html:li><html:em>the interface</html:em> that defines how the two levels should communicate</html:li></html:ul><html:p>A basic concept in computer science is that large systems can only be
understood in levels, with each level further subdivided into functions or
services of some sort. The interface to the higher level should supply the
advertised services. Just as important, it should block access to the means by
which those services are implemented. This <html:em>abstraction barrier</html:em> allows one
level to be changed without affecting levels above. For example, when a
manufacturer designs a faster version of a processor, it is essential that
existing programs continue to run on it. Any differences between the old and
new processors should be invisible to the program.</html:p><html:p>Modern processors have elaborate specifications, which still sometimes leave
out important details. In the old days, you then had to consult the circuit
diagrams.</html:p>

<fr:tree
show-metadata="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/</fr:uri><fr:display-uri>focs-dates</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dates/</fr:route><fr:title
text="Example 1: Dates">Example 1: Dates</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">Abstract level</fr:link>: dates over a certain interval</html:li>
  <html:li>Concrete level: could be 6 characters: <html:code>YYMMDD</html:code> (where each character is represented by 8 bits)</html:li>
  <html:li>Date crises caused by <html:strong>inadequate</html:strong> internal formats:
    <html:ul><html:li>Digital’s PDP-10: using 12-bit dates (good for at most 11 years)</html:li>
      <html:li>2000 crisis: 48 bits could be good for lifetime of universe!</html:li></html:ul></html:li></html:ul><html:p>Digital Equipment Corporation’s date crisis occurred in 1975.  The
PDP-10 was a 36-bit mainframe computer. It represented dates using a 12-bit
format designed for the tiny PDP-8. With 12 bits, one can distinguish
<fr:tex
display="inline"><![CDATA[2^{12} = 4096]]></fr:tex> days or 11 years.</html:p><html:p>Last century, the most common industry format for dates used six characters: two for the
year, two for the month and two for the day. The most common “solution” to the
year 2000 crisis is to add two further characters, thereby altering file sizes.
Others have noticed that the existing six characters consist of 48 bits,
already sufficient to represent all dates over the projected lifetime of the
universe: <fr:tex
display="inline"><![CDATA[2^{48}]]></fr:tex> = <fr:tex
display="inline"><![CDATA[2.8\times  10^{14}]]></fr:tex> days = <fr:tex
display="inline"><![CDATA[7.7\times  10^{11}]]></fr:tex> years!</html:p><html:p>Mathematicians think in terms of unbounded ranges, but the representation we
choose for the computer usually imposes hard limits. A good programming
language like OCaml lets one easily change the representation used in the
program.  But if files in the old representation exist all over the place,
there will still be conversion problems. The need for compatibility with older
systems causes problems across the computer industry.</html:p></fr:mainmatter></fr:tree>
<fr:tree
show-metadata="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/</fr:uri><fr:display-uri>focs-floating-point</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-floating-point/</fr:route><fr:title
text="Example 2: Floating Point Numbers">Example 2: Floating Point Numbers</fr:title></fr:frontmatter><fr:mainmatter><html:p>Computers have integers like <html:code>1066</html:code> and floats like <fr:tex
display="inline"><![CDATA[1.066\times  10^3]]></fr:tex>.
A floating-point number is represented by two integers.
The concept of <html:em>data type</html:em> involves:</html:p><html:ul><html:li>how a value is represented inside the computer</html:li>
  <html:li>the suite of operations given to programmers</html:li>
  <html:li>valid and invalid (or exceptional) results, such as “infinity”</html:li></html:ul><html:p>Computer arithmetic can yield <html:em>incorrect answers!</html:em></html:p><html:p>In science, numbers written with finite precision and a decimal exponent are
said to be in <html:em>standard form</html:em>. The computational equivalent is the <html:em>floating
point number</html:em>. These are familiar to anybody who has used a scientific
calculator.  Internally, a float consists of two integers.</html:p><html:p>Because of its finite precision, floating-point computations are potentially
inaccurate. To see an example, use your nearest electronic calculator to
compute <fr:tex
display="inline"><![CDATA[(2^{1/10000})^{10000}]]></fr:tex>. I get <fr:tex
display="inline"><![CDATA[1.99999959]]></fr:tex>! With certain computations,
the errors spiral out of control. Many programming languages fail to check
whether even integer computations fall within the allowed range: you can add
two positive integers and get a negative one!</html:p><html:p>Most computers give us a choice of precisions. In 32-bit precision, integers
typically range from <fr:tex
display="inline"><![CDATA[2^{31}-1]]></fr:tex> (namely 2 147 483 647) to <fr:tex
display="inline"><![CDATA[-2^{31}]]></fr:tex>; floats
are accurate to about six decimal places and can get as large as <fr:tex
display="inline"><![CDATA[10^{35}]]></fr:tex> or so.
For floats, 64-bit precision is often preferred. Early languages like Fortran
required variables to be declared as <html:code>INTEGER</html:code>, <html:code>REAL</html:code> or <html:code>COMPLEX</html:code> and barred
programmers from mixing numbers in a computation. Nowadays, programs handle
many different kinds of data, including text and symbols. The concept of a
<html:em>data type</html:em> can ensure that different types of data are not combined in a
senseless way.</html:p><html:p>Inside the computer, all data are stored as bits. In most programming
languages, the compiler uses types to generate correct machine code, and types
are not stored during program execution. In this course, we focus almost
entirely on programming in a high-level language: OCaml.</html:p></fr:mainmatter></fr:tree>
</fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-goals-of-programming/</fr:uri><fr:display-uri>focs-goals-of-programming</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-goals-of-programming/</fr:route><fr:title
text="Goals of Programming">Goals of Programming</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>to describe a computation so that it can be done <html:strong>mechanically</html:strong>:
    <html:ul><html:li>Expressions compute values.</html:li>
      <html:li>Commands cause effects.</html:li></html:ul></html:li>
  <html:li>to do so efficiently and <html:strong>correctly</html:strong>, giving the right answers quickly</html:li>
  <html:li>to allow easy modification as needs change
    <html:ul><html:li>Through an orderly <html:strong>structure</html:strong> based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstraction principles</fr:link></html:li>
      <html:li>Such as modules or classes</html:li></html:ul></html:li></html:ul><html:p>Programming <html:em>in-the-small</html:em> concerns the writing of code to do simple, clearly
defined tasks. Programs provide expressions for describing mathematical
formulae and so forth. This was the original contribution of FORTRAN, the
FORmula TRANslator. Commands describe how control should flow from one part of
the program to the next.</html:p><html:p>As we code layer upon layer, we eventually find ourselves programming
<html:em>in the large</html:em> : joining large modules to solve some messy task. Programming
languages have used various mechanisms to allow one part of the program to
provide interfaces to other parts. Modules encapsulate a body of code, allowing
outside access only through a programmer-defined interface. <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queue-adt/"
title="An Abstract Data Type: Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/"
display-uri="focs-queue-adt"
type="local"><html:em>Abstract Data
Types</html:em></fr:link> are a simpler version of this concept, which implement a single concept
such as dates or floating-point numbers.</html:p><html:p><html:em>Object-oriented programming</html:em> is the most complicated approach to modularity.
<html:em>Classes</html:em> define concepts, and they can be built upon other classes. Operations
can be defined that work in appropriately specialised ways on a family of
related classes. <html:em>Objects</html:em> are instances of classes and hold the data that is
being manipulated.</html:p><html:p>This course does not cover OCaml’s sophisticated module system, which can do
many of the same things as classes. You will learn all about objects when you
study Java. OCaml includes a powerful object system, although this is not used
as much as its module system.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-why-ocaml/</fr:uri><fr:display-uri>focs-why-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-why-ocaml/</fr:route><fr:title
text="Why Program in OCaml?">Why Program in OCaml?</fr:title></fr:frontmatter><fr:mainmatter><html:p>Why program in OCaml at all?</html:p><html:ul><html:li>It is interactive.</html:li>
  <html:li>It has a flexible notion of <html:em>data type</html:em>.</html:li>
  <html:li>It hides the underlying hardware: <html:em>no crashes</html:em>.</html:li>
  <html:li>Programs can easily be understood mathematically.</html:li>
  <html:li>It distinguishes naming something from <html:em>updating memory</html:em>.</html:li>
  <html:li>It manages storage for us.</html:li></html:ul><html:p>Programming languages matter. They affect the reliability, security, and
efficiency of the code you write, as well as how easy it is to read, refactor,
and extend. The languages you know can also change how you think, influencing
the way you design software even when you’re not using them.</html:p><html:p>What makes OCaml special is that it occupies a sweet spot in the space of
programming language designs. It provides a combination of efficiency,
expressiveness and practicality that is difficult to find matched by any other language.
“ML” was originally the meta language of the LCF (Logic for Computable Functions)
proof assistant released by Robin Milner in 1972 (at Stanford, and later at Cambridge).
ML was turned into a compiler in order to make it easier to use LCF on different machines,
and it was gradually turned into a full-fledged system of its own by the 1980s.</html:p><html:p>The modern OCaml emerged in 1996, and the past twenty five years have seen OCaml
attract a significant user base with language improvements being steadily
added to support the growing commercial and academic codebases.
OCaml is therefore the outcome of years of research into programming languages,
and a good base to begin our journey into learning the foundations of computer
science.</html:p><html:p>Because of its connection to mathematics, OCaml programs can be designed and
understood without thinking in detail about how the computer will run them.
Although a program can abort, it cannot crash: it remains under the control of
the OCaml system. It still achieves respectable efficiency and provides
lower-level primitives for those who need them. Most other languages allow
direct access to the underlying machine and even try to execute illegal
operations, causing crashes.</html:p><html:p>The only way to learn programming is by writing and running programs. This web
notebook provides an interactive environment where you can modify the example
fragments and see the results for yourself.  You should also consider
installing OCaml on your own computer so that you try more advanced programs
locally.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-first-session/</fr:uri><fr:display-uri>focs-first-session</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-first-session/</fr:route><fr:title
text="A first session with OCaml">A first session with OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let pi = 3.14159265358979
val pi : float = 3.14159265358979]]></html:pre><html:p>The first line of this simple session is a <html:em>value declaration</html:em>. It makes the
name <html:code>pi</html:code> stand for the floating point number <html:code>3.14159</html:code>. (Such names are called
<html:em>identifiers</html:em>.)  OCaml echoes the name (<html:code>pi</html:code>) and type (<html:code>float</html:code>) of the
declared identifier.</html:p><html:pre><![CDATA[# pi *. 1.5 *. 1.5
- : float = 7.06858347057702829]]></html:pre><html:p>The second line computes the area of the circle with radius <html:code>1.5</html:code> using the
formula <fr:tex
display="inline"><![CDATA[A = \pi  r^2]]></fr:tex>. We use <html:code>pi</html:code> as an abbreviation for <html:code>3.14159</html:code>.
Multiplication is expressed using <html:code>*.</html:code>, which is called an <html:em>infix operator</html:em>
because it is written between its two operands.</html:p><html:p>OCaml replies with the computed value (about <html:code>7.07</html:code>) and its type (again <html:code>float</html:code>).</html:p><html:pre><![CDATA[# let area r = pi *. r *. r
val area : float -> float = <fun>]]></html:pre><html:p>To work <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstractly</fr:link>, we should provide the service “compute the area of a
circle,” so that we no longer need to remember the formula. This sort of
encapsulated computation is called a <html:em>function</html:em>. The third line declares the
function <html:code>area</html:code>. Given any floating point number <html:code>r</html:code>, it returns another
floating point number computed using the <html:code>area</html:code> formula; note that the function
has type <html:code>float -&gt; float</html:code>.</html:p><html:pre><![CDATA[# area 2.0
- : float = 12.56637061435916]]></html:pre><html:p>The fourth line calls the function <html:code>area</html:code> supplying <html:code>2.0</html:code> as the argument. A
circle of radius <html:code>2</html:code> has an area of about <html:code>12.6</html:code>. Note that brackets around a
function argument are not necessary.</html:p><html:p>The function uses <html:code>pi</html:code> to stand for <html:code>3.14159</html:code>. Unlike what you may have seen in
other programming languages, <html:code>pi</html:code> cannot be "assigned to" or otherwise updated.
Its meaning within <html:code>area</html:code> will persist even if we issue a new <html:code>let</html:code> declaration
for <html:code>pi</html:code> afterwards.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/</fr:uri><fr:display-uri>focs-npower</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-npower/</fr:route><fr:title
text="Raising a Number to a Power">Raising a Number to a Power</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec npower x n =
    if n = 0 then 1.0
    else x *. npower x (n - 1)
val npower : float -> int -> float = <fun>]]></html:pre><html:p>Our new <html:code>npower</html:code> definition can now take additional arguments, reflected in the arrows
present in the type of <html:code>npower</html:code>; these represent <html:em>parameters</html:em> that can be passed to the
new value being defined, with the final segment being the resulting type. Thus our <html:code>npower</html:code>
type can be read as "pass in a float and integer to return a float".</html:p><html:p><html:em>Mathematical Justification</html:em> (for <fr:tex
display="inline"><![CDATA[x\not =0]]></fr:tex>):</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
           x^0 & = 1 \\
           x^{n+1} & = x\times  x^n.
\end {aligned}
]]></fr:tex><html:p>The function <html:code>npower</html:code> raises its float argument <html:code>x</html:code> to the power <html:code>n</html:code>, a
non-negative integer. The function is <html:strong>recursive</html:strong>: it calls itself.  You
can spot a recursive function due to the <html:code>rec</html:code> keyword in the definition:
this indicates that any invocation of the function name within the function body should call itself.
This concept should be familiar from mathematics, since exponentiation is defined by the
rules shown above. You may also have seen recursion in the product rule for
differentiation: <fr:tex
display="inline"><![CDATA[(u\cdot  v)' = u\cdot  v' + u'\cdot  v]]></fr:tex>. In finding the derivative of <fr:tex
display="inline"><![CDATA[u\cdot  v]]></fr:tex>,
we recursively find the derivatives of <fr:tex
display="inline"><![CDATA[u]]></fr:tex> and <fr:tex
display="inline"><![CDATA[v]]></fr:tex>, combining them to obtain the desired result.
The recursion is meaningful because it terminates: we reduce the problem to two smaller
problems, and this cannot go on forever. The OCaml programmer uses recursion
heavily.  For <fr:tex
display="inline"><![CDATA[n\geq 0]]></fr:tex>, the equation <fr:tex
display="inline"><![CDATA[x^{n+1} = x\times  x^n]]></fr:tex> yields an obvious
computation:</html:p><fr:tex
display="block"><![CDATA[ x^3 = x\times  x^2 = x\times  x\times  x^1 = x\times  x\times  x\times  x^0 = x\times  x\times  x ]]></fr:tex><html:p>The equation clearly holds even for negative <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. However, the corresponding
computation runs forever:</html:p><fr:tex
display="block"><![CDATA[ x^{-1} = x\times  x^{-2} = x\times  x\times  x^{-3}=\cdots  ]]></fr:tex><html:p>Note that the function <html:code>npower</html:code> contains both an integer constant (<html:code>0</html:code>) and a
floating point constant (<html:code>1.0</html:code>). The decimal point makes all the difference.
OCaml will notice and ascribe different meaning to each type of constant.</html:p><html:pre><![CDATA[# let square x = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>Now for a tiresome but necessary aside. In most languages, the types of
arguments and results must always be specified. OCaml is unusual that it normally
infers the types itself. However, sometimes it is useful to supply a hint to
help you debug and develop your program. OCaml will still infer the types even if you don’t specify them, but in some cases
it will use a more inefficient function than a specialised one. Some languages
have just one type of number, converting automatically between different
formats; this is slow and could lead to unexpected rounding errors.  Type
constraints are allowed almost anywhere. We can put one on any occurrence of x
in the function.</html:p><html:pre><![CDATA[# let square (x : float) = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>Or we can constrain the type of the function’s result:</html:p><html:pre><![CDATA[# let square x : float = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>OCaml treats the equality and comparison test specially. Expressions like <html:code>if x = y then</html:code> …
are allowed provided <html:code>x</html:code> and <html:code>y</html:code> have the same type and equality testing is
possible for that type. (We discuss <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local">equality</fr:link> further in a later lecture.)
Note that <html:code>x &lt;&gt; y</html:code> is OCaml for <fr:tex
display="inline"><![CDATA[x\not =y]]></fr:tex>.</html:p><html:p>A characteristic feature of the computer is its ability to test for conditions
and act accordingly.  In the early days, a program might jump to a given
address depending on the sign of some number.  Later, John McCarthy defined
the <html:em>conditional expression</html:em> to satisfy <html:code>if true then x else y = x</html:code> and
<html:code>if false then x else y = y</html:code>.</html:p><html:p>OCaml evaluates the expression <html:code>if</html:code> <fr:tex
display="inline"><![CDATA[B]]></fr:tex> <html:code>then</html:code> <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> <html:code>else</html:code> <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex> by first evaluating <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.
If the result is <html:code>true</html:code> then OCaml evaluates <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> and otherwise <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex>.  Only one
of the two expressions <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex> is evaluated!  If both were evaluated,
then recursive functions like <html:code>npower</html:code> above would run forever.</html:p><html:p>The <html:code>if</html:code>-expression is governed by an expression of type <html:code>bool</html:code>, whose two
values are <html:code>true</html:code> and <html:code>false</html:code>.  In modern programming languages, tests are not
built into “conditional branch” constructs but can just be part of normal expressions.
Tests, or <html:em>Boolean expressions,</html:em> can be expressed using relational operators
such as <html:code>&lt;</html:code> and <html:code>=</html:code>. They can be combined using the Boolean operators for
negation (<html:code>not</html:code>), conjunction (written as <html:code>&amp;&amp;</html:code>) and disjunction (written as <html:code>||</html:code>).  New
properties can be declared as functions: here, to test whether an integer is
even, for example:</html:p><html:pre><![CDATA[# let even n = n mod 2 = 0
val even : int -> bool = <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/</fr:uri><fr:display-uri>focs-power</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-power/</fr:route><fr:title
text="Efficiently Raising a Number to a Power">Efficiently Raising a Number to a Power</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec power x n =
    if n = 1 then x
    else if even n then
      power (x *. x) (n / 2)
    else
      x *. power (x *. x) (n / 2)
val power : float -> int -> float = <fun>]]></html:pre><html:p><html:em>Mathematical Justification</html:em></html:p><fr:tex
display="block"><![CDATA[\begin {aligned}
           x^1 & = x \\
           x^{2n} & = (x^2)^n  \\
           x^{2n+1} & = x\times (x^2)^n.
\end {aligned}]]></fr:tex><html:p>For large <html:code>n</html:code>, computing powers using <fr:tex
display="inline"><![CDATA[x^{n+1} = x\times  x^n]]></fr:tex> is too slow to
be practical.  The equations above are much faster. Example:</html:p><fr:tex
display="block"><![CDATA[ 2^{12} = 4^6 = 16^3 = 16\times  256^1 = 16\times  256 = 4096. ]]></fr:tex><html:p>Instead of <html:code>n</html:code> multiplications, we need at most <fr:tex
display="inline"><![CDATA[2\lg  n]]></fr:tex> multiplications,
where <fr:tex
display="inline"><![CDATA[\lg  n]]></fr:tex> is the logarithm of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to the base <fr:tex
display="inline"><![CDATA[2]]></fr:tex>.</html:p><html:p>We use the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>even</html:code></fr:link>, declared previously, to test whether the
exponent is even.  Integer division (<html:code>/</html:code>) truncates its result to an
integer: dividing <fr:tex
display="inline"><![CDATA[2n+1]]></fr:tex> by 2 yields <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>A recurrence is a useful computation rule only if it is bound to terminate.
If <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex> then <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is smaller than both <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> and <fr:tex
display="inline"><![CDATA[2n+1]]></fr:tex>.  After enough
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive calls</fr:link>, the exponent will be reduced to <fr:tex
display="inline"><![CDATA[1]]></fr:tex>.  The equations also hold
if <fr:tex
display="inline"><![CDATA[n\leq 0]]></fr:tex>, but the corresponding computation runs forever.</html:p><html:p>Our reasoning assumes arithmetic to be <html:em>exact</html:em>. Fortunately, the calculation is
well-behaved using floating-point.</html:p><html:p>Computer numbers have a finite range, which if exceeded results in the
integer wrapping around.  You will understand this behaviour more as you
learn about computer architecture and how modern systems represent
numbers in memory.</html:p><html:p>If integers and floats must be combined in a calculation, OCaml provides functions
to convert between them:</html:p><html:pre><![CDATA[# int_of_float 3.14159
- : int = 3
# float_of_int 3
- : float = 3.]]></html:pre><html:p>OCaml’s libraries are organised using “modules”, so we may use compound
identifiers such as <html:code>Float.of_int</html:code> to refer to library functions. There
are many thousands of library functions available in the OCaml ecosystem,
including text-processing and operating systems functions in addition to the
usual numerical ones.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/</fr:uri><fr:display-uri>focs-ex-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-1/</fr:uri><fr:display-uri>focs-ex-1-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-1/</fr:route><fr:title
text="Two-digit year windowing">Two-digit year windowing</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>One solution to the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dates/"
title="Example 1: Dates"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/"
display-uri="focs-dates"
type="local">year 2000 bug</fr:link> involves storing years as two digits, but interpreting them such
that 50 means 1950 and 49 means 2049. Comment on the merits and demerits of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-2/</fr:uri><fr:display-uri>focs-ex-1-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-2/</fr:route><fr:title
text="Comparing and adding years">Comparing and adding years</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the date representation of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1-1/"
title="Exercises › Two-digit year windowing"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-1/"
display-uri="focs-ex-1-1"
type="local">the previous exercise</fr:link>, code OCaml functions to (a) compare two
years (b) add/subtract some given number of years from another year.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-3/</fr:uri><fr:display-uri>focs-ex-1-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-3/</fr:route><fr:title
text="Redundant conditionals">Redundant conditionals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Why would no experienced programmer write an expression of the form <html:code>if</html:code> … <html:code>then true else false</html:code>?
What about expressions of the form <html:code>if</html:code> … <html:code>then false else true</html:code>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:uri><fr:display-uri>focs-ex-1-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:route><fr:title
text="Type inference in power">Type inference in power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> both return a <html:code>float</html:code>. The definition of <html:code>npower</html:code> returns the float
value <html:code>1.0</html:code> in its base case. The definition of <html:code>power</html:code> does not, so how does the OCaml type checker
know that <html:code>power</html:code> returns a <html:code>float</html:code>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:uri><fr:display-uri>focs-ex-1-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:route><fr:title
text="Floating-point error by repeated addition">Floating-point error by repeated addition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Because computer arithmetic is based on binary numbers, simple decimals such as 0.1 often cannot be
represented exactly. Write a function <html:code>mul</html:code> that performs the computation</html:p><fr:tex
display="block"><![CDATA[\underbrace {x+x+\cdots +x}_{n}]]></fr:tex><html:p>where <fr:tex
display="inline"><![CDATA[x]]></fr:tex> has type <html:code>float</html:code>. (It is essential to use repeated addition rather than multiplication!)</html:p><html:p>The value computed with <html:code>n = 10000</html:code> and <html:code>x = 0.1</html:code> may print as
<html:code>1000.0</html:code>, which looks exact. If that happens, then evaluate the
expression <html:code>mul 0.1 10000 -. 1000.0</html:code></html:p><html:p>An error of this type has been blamed for the failure of an American Patriot Missile battery to
intercept an incoming Iraqi missile during the <fr:link
href="https://en.wikipedia.org/wiki/MIM-104_PatriotFailure_at_Dhahran"
type="external">first Gulf War</fr:link>.
The missile hit an American Army barracks, killing 28.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:uri><fr:display-uri>focs-ex-1-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:route><fr:title
text="Golden ratio instability">Golden ratio instability</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another example of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-floating-point/"
title="Example 2: Floating Point Numbers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/"
display-uri="focs-floating-point"
type="local">inaccuracy of floating-point arithmetic</fr:link> takes the golden ratio
<fr:tex
display="inline"><![CDATA[\phi \approx 1.618\ldots ]]></fr:tex> as its starting point:</html:p><fr:tex
display="block"><![CDATA[\gamma _0 = \frac {1+\sqrt 5}{2} \quad \text {and}\quad \gamma _{n+1} = \frac {1}{\gamma _n-1}.]]></fr:tex><html:p>In theory, it is easy to prove that <fr:tex
display="inline"><![CDATA[\gamma _n=\cdots  = \gamma _1 = \gamma _0]]></fr:tex> for all <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>. Code this
computation in OCaml and report the value of <fr:tex
display="inline"><![CDATA[\gamma _{50}]]></fr:tex>. <html:em>Hint:</html:em> in OCaml, <fr:tex
display="inline"><![CDATA[\sqrt 5]]></fr:tex> is expressed
as <html:code>sqrt 5.0</html:code>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion/</fr:uri><fr:display-uri>focs-recursion</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recursion/</fr:route><fr:title
text="Recursion and Efficiency">Recursion and Efficiency</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-expression-evaluation/</fr:uri><fr:display-uri>focs-expression-evaluation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-expression-evaluation/</fr:route><fr:title
text="Expression Evaluation">Expression Evaluation</fr:title></fr:frontmatter><fr:mainmatter><html:p>Expression evaluation concerns expressions and the values they return. This
view of computation may seem to be too narrow. It is certainly far removed from
computer hardware, but that can be seen as an advantage. For the traditional
concept of computing solutions to problems, expression evaluation is entirely
adequate.</html:p><html:p>Starting with <fr:tex
display="inline"><![CDATA[E_0]]></fr:tex>, the expression <fr:tex
display="inline"><![CDATA[E_i]]></fr:tex> is reduced to <fr:tex
display="inline"><![CDATA[E_{i+1}]]></fr:tex> until this
process concludes with a value <fr:tex
display="inline"><![CDATA[v]]></fr:tex>.  A <html:em>value</html:em> is something like a number
that cannot be further reduced.</html:p><html:p>We write <fr:tex
display="inline"><![CDATA[E \rightarrow  E']]></fr:tex> to say that <fr:tex
display="inline"><![CDATA[E]]></fr:tex> is <html:em>reduced</html:em> to <fr:tex
display="inline"><![CDATA[E']]></fr:tex>.
Mathematically, they are equal: <fr:tex
display="inline"><![CDATA[E=E']]></fr:tex>, but the computation goes from <fr:tex
display="inline"><![CDATA[E]]></fr:tex> to
<fr:tex
display="inline"><![CDATA[E']]></fr:tex> and never the other way around.</html:p><html:p>Computers also interact with the outside world.  For a start, they need some
means of accepting problems and delivering solutions.  Many computer systems
monitor and control industrial processes.  This role of computers is familiar
now, but was never envisaged in the early days. Computer pioneers focused on
mathematical calculations.  Modelling interaction and control requires a notion
of <html:em>states</html:em> that can be observed and changed.  Then we can consider
updating the state by assigning to variables or performing input/output,
finally arriving at conventional programs as coded in C, for instance.</html:p><html:p>For now, we remain at the level of expressions, which is usually termed
<html:em>functional programming</html:em>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/</fr:uri><fr:display-uri>focs-nsum</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nsum/</fr:route><fr:title
text="Summing the first n integers">Summing the first n integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nsum n =
    if n = 0 then
      0
    else
      n + nsum (n - 1)
val nsum : int -> int = <fun>]]></html:pre><html:p>The function call <html:code>nsum n</html:code> computes the sum <html:code>1 +</html:code> … <html:code>+ n</html:code> rather naively, hence the
initial <html:code>n</html:code> in its name:</html:p><fr:tex
display="block"><![CDATA[\begin {aligned}
\text {nsum}\;3 \Rightarrow  &\; 3 + (\text {nsum}\;2) \\
               \Rightarrow  &\; 3 + (2 + (\text {nsum}\;1)) \\
               \Rightarrow  &\; 3 + (2 + (1 + (\text {nsum}\;0))) \\
               \Rightarrow  &\; 3 + (2 + (1 + 0))
\end {aligned}]]></fr:tex><html:p>The nesting of parentheses is not just an artifact of
our notation; it indicates a real problem.  The function gathers up a
collection of numbers, but none of the additions can be performed until <html:code>nsum
0</html:code> is reached.  Meanwhile, the computer must store the numbers in an internal
data structure, typically the <html:em>stack</html:em>.  For large <html:code>n</html:code>, say <html:code>nsum 10000</html:code>, the
computation might fail due to stack overflow.</html:p><html:p>We all know that the additions can be performed as we go along.  How do we
make the computer do that?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/</fr:uri><fr:display-uri>focs-summing-iter</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-summing-iter/</fr:route><fr:title
text="Iteratively summing the first n integers">Iteratively summing the first n integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec summing n total =
    if n = 0 then
      total
    else
      summing (n - 1) (n + total)
val summing : int -> int -> int = <fun>]]></html:pre><html:p>Function <html:code>summing</html:code> takes an additional argument: a running total.  If
<html:code>n</html:code> is zero then it returns the running total; otherwise, <html:code>summing</html:code>
adds to it and continues.  The recursive calls do not nest; the additions are
done immediately.</html:p><html:p>A recursive function whose computation does not nest is called
<html:em>iterative</html:em> or <html:em>tail-recursive</html:em>. Many functions can be made iterative by
introducing an argument analogous to <html:code>total</html:code>, which is often called an
<html:em>accumulator</html:em>.</html:p><html:p>The gain in efficiency is sometimes worthwhile and sometimes not.  The function
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> is not iterative because nesting occurs whenever the exponent is odd.
Adding a third argument makes it iterative, but the change complicates the
function and the gain in efficiency is minute; for 32-bit integers, the maximum
possible nesting is 30 for the exponent <fr:tex
display="inline"><![CDATA[2^{31}-1]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/</fr:uri><fr:display-uri>focs-recursion-vs-iteration</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/</fr:route><fr:title
text="Recursion vs Iteration">Recursion vs Iteration</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>“Iterative” normally refers to a loop, coded using <html:code>while</html:code> for example (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural/"
title="Elements of Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/"
display-uri="focs-procedural"
type="local">final lecture</fr:link>)</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">Tail-recursion</fr:link> is only efficient if the compiler detects it</html:li>
  <html:li>Mainly it saves space (memory), though iterative code can also run faster</html:li>
  <html:li>Do not make programs iterative unless the gain is worth it</html:li></html:ul><html:p>A <fr:link
href="https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs"
type="external">classic book</fr:link>
by Abelson and Sussman, which describes the Lisp dialect known as Scheme,
used <html:em>iterative</html:em> to mean <html:em>tail-recursive</html:em>. Iterative functions produce computations
resembling those that can be done using while-loops in conventional languages.</html:p><html:p>Many algorithms can be expressed naturally using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>, but only awkwardly
using iteration. There is a story that Dijkstra sneaked recursion into Algol-60
by inserting the words “any other occurrence of the procedure name denotes
execution of the procedure.” By not using the word “recursion”, he managed to
slip this amendment past sceptical colleagues.</html:p><html:p>Obsession with tail recursion leads to a coding style in which functions
have many more arguments than necessary.  Write straightforward code first,
avoiding only gross inefficiency.  If the program turns out to be too slow,
tools are available for pinpointing the cause.  Always remember KISS (Keep
It Simple, Stupid).</html:p><html:p>I hope you have all noticed by now that the summation can be done even more
efficiently using the arithmetic progression formula:</html:p><fr:tex
display="block"><![CDATA[1+\cdots +n = n(n+1)/2]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sillysum/</fr:uri><fr:display-uri>focs-sillysum</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sillysum/</fr:route><fr:title
text="Silly Summing the First n Integers">Silly Summing the First n Integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec sillySum n =
    if n = 0 then
      0
    else
      n + (sillySum (n - 1) + sillySum (n - 1)) / 2
val sillySum : int -> int = <fun>]]></html:pre><html:p>The function calls itself <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> times!  Bigger inputs mean higher costs—but
what’s the growth rate?</html:p><html:p>Now let us consider how to estimate various costs associated with a program.
<html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local">Asymptotic complexity</fr:link></html:em> refers to how costs—usually time or space—grow with
increasing inputs. Space complexity can never exceed time complexity, for it
takes time to do anything with the space.  Time complexity often greatly
exceeds space complexity.</html:p><html:p>The function <html:code>sillySum</html:code> calls itself twice in each <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> step.  This
function is contrived, but many mathematical formulas refer to a particular
quantity more than once.  In OCaml, we can create a local binding to a computed
value using the <html:em>local declaration</html:em> syntax. In the following expression, <html:code>y</html:code> is
computed once and used twice:</html:p><html:pre><![CDATA[# let x = 2.0 in
  let y = Float.pow x 20.0 in
  y *. (x /. y)
- : float = 2.]]></html:pre><html:p>You can read <html:code>let x = e1 in e2</html:code> as assigning (or "binding") the name <html:code>x</html:code> with
the value of <html:code>e1</html:code> into <html:code>e2</html:code>. Any use of <html:code>x</html:code> within <html:code>e2</html:code> will have the value of <html:code>e1</html:code>,
and <html:code>x</html:code> will only be visible in subexpressions into which it has been bound.</html:p><html:p>Why do we need let bindings? Fast hardware does not make good algorithms unnecessary.
On the contrary, faster hardware magnifies the superiority of better algorithms.
Typically, we want to handle the largest inputs possible.  If we double our processing power,
what do we gain?  How much can we increase <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, the input to our function?</html:p><html:p>With <html:code>sillySum</html:code>, we can only go from <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>.  We are limited to this
modest increase because the function’s running time is proportional to <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex>.
With the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> defined in the previous section, we can go from <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
to <fr:tex
display="inline"><![CDATA[2n]]></fr:tex>: we can handle problems twice as big.  With <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> we can do much
better still, going from <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p><html:p>The following table (excerpted from <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">a 50-year-old book</fr:link>!)
illustrates the effect of various time complexities.  The left-hand column (dubbed "complexity")
is defined as how many milliseconds are required to process an input of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
The other entries show the maximum size of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> that can be processed in the given time (one
second, minute or hour).</html:p><html:table>
  <html:tr><html:th>complexity</html:th><html:th>1 second</html:th><html:th>1 minute</html:th><html:th>1 hour</html:th><html:th>gain</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n]]></fr:tex></html:td><html:td>1000</html:td><html:td>60 000</html:td><html:td>3 600 000</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  60]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n \log  n]]></fr:tex></html:td><html:td>140</html:td><html:td>4 895</html:td><html:td>204 095</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  41]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{2}]]></fr:tex></html:td><html:td>31</html:td><html:td>244</html:td><html:td>1 897</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  8]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{3}]]></fr:tex></html:td><html:td>10</html:td><html:td>39</html:td><html:td>153</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  4]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[2^{n}]]></fr:tex></html:td><html:td>9</html:td><html:td>15</html:td><html:td>21</html:td><html:td><fr:tex
display="inline"><![CDATA[+6]]></fr:tex></html:td></html:tr>
</html:table><html:p>The table illustrates how large an input can be processed as a function
of time.  As we increase the computer time per input from one second to one
minute and then to one hour, the size of the input increases accordingly.</html:p><html:p>The top two rows (complexities <fr:tex
display="inline"><![CDATA[n]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n \lg  n]]></fr:tex>) increase rapidly: for <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, by
a factor of 60 per column.  The bottom two start out close together, but <fr:tex
display="inline"><![CDATA[n^3]]></fr:tex> (which
grows by a factor of 3.9) pulls well away from <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> (whose growth is only
additive).  If an algorithm’s complexity is exponential then it can never
handle large inputs, even if it is given huge resources.  On the other hand,
suppose the complexity has the form <fr:tex
display="inline"><![CDATA[n^c]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[c]]></fr:tex> is a constant.  (We say
the complexity is <html:em>polynomial</html:em>.)  Doubling the argument then increases the
cost by a constant factor.  That is much better, though if <fr:tex
display="inline"><![CDATA[c>3]]></fr:tex> the algorithm
may not be considered practical.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/</fr:uri><fr:display-uri>focs-o-notation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-o-notation/</fr:route><fr:title
text="Comparing Algorithms: O Notation">Comparing Algorithms: O Notation</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Formally, define <fr:tex
display="inline"><![CDATA[f(n) = O(g(n))]]></fr:tex> provided <fr:tex
display="inline"><![CDATA[|f(n)| \leq  c|g(n)|]]></fr:tex> as <fr:tex
display="inline"><![CDATA[n\to \infty ]]></fr:tex></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[|f(n)|]]></fr:tex> is bounded for some constant <fr:tex
display="inline"><![CDATA[c]]></fr:tex> and all <html:em>sufficiently large</html:em> <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:li>
  <html:li>Intuitively, look at the <html:em>most significant</html:em> term.</html:li>
  <html:li>Ignore <html:em>constant factors</html:em> as they seldom dominate and are often transitory</html:li></html:ul><html:p>For example: consider <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex> instead of <fr:tex
display="inline"><![CDATA[3n^2+34n+433]]></fr:tex>.</html:p><html:p>The cost of a program is usually a complicated formula.  Often we should
consider only the most significant term.  If the cost is <fr:tex
display="inline"><![CDATA[n^2 + 99n + 900]]></fr:tex>
for an input of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, then the <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex> term will eventually dominate,
even though <fr:tex
display="inline"><![CDATA[99n]]></fr:tex> is bigger for <fr:tex
display="inline"><![CDATA[n<99]]></fr:tex>.
The constant term <fr:tex
display="inline"><![CDATA[900]]></fr:tex> may look big, but it is soon dominated by <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p><html:p>Constant factors in costs can be ignored unless they are large.  For one thing,
they seldom make a difference: <fr:tex
display="inline"><![CDATA[100n^2]]></fr:tex> will be better than <fr:tex
display="inline"><![CDATA[n^3]]></fr:tex> in the long
run: or <html:em>asymptotically</html:em> to use the jargon.  Moreover, constant factors are
seldom stable.  They depend upon details such as which hardware, operating
system or programming language is being used.  By ignoring constant factors, we
can make comparisons between algorithms that remain valid in a broad range of
circumstances.</html:p><html:p>The “Big O” notation is commonly used to describe efficiency—to be precise,
<html:em>asymptotic complexity</html:em>.  It concerns the limit of a function as its
argument tends to infinity.  It is an abstraction that meets the informal
criteria that we have just discussed.
In the definition, <html:em>sufficiently large</html:em> means there is some constant <fr:tex
display="inline"><![CDATA[n_0]]></fr:tex>
such that <fr:tex
display="inline"><![CDATA[|f(n)|\leq  c|g(n)|]]></fr:tex> for all <fr:tex
display="inline"><![CDATA[n]]></fr:tex> greater than <fr:tex
display="inline"><![CDATA[n_0]]></fr:tex>.  The
role of <fr:tex
display="inline"><![CDATA[n_0]]></fr:tex> is to ignore finitely many exceptions to the bound, such as the
cases when <fr:tex
display="inline"><![CDATA[99n]]></fr:tex> exceeds <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation-facts/</fr:uri><fr:display-uri>focs-o-notation-facts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-o-notation-facts/</fr:route><fr:title
text="Simple Facts About O Notation">Simple Facts About O Notation</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {aligned}
 O(2g(n)) & \text { is the same as } O(g(n)) \\
 O(\log _{10}n) & \text { is the same as } O(\ln  n)  \\
 O(n^2+50n+36) & \text { is the same as } O(n^2) \\[1.5ex]
 O(n^2) & \text { is contained in }  O(n^3) \\
 O(2^n) & \text { is contained in }  O(3^n)  \\
 O(\log  n) & \text { is contained in } O(\sqrt  n)
\end {aligned}
]]></fr:tex><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> lets us reason about the costs of algorithms easily.</html:p><html:ul><html:li>Constant factors such as the <fr:tex
display="inline"><![CDATA[2]]></fr:tex> in <fr:tex
display="inline"><![CDATA[O(2g(n))]]></fr:tex> drop out: we can use <fr:tex
display="inline"><![CDATA[O(g(n))]]></fr:tex> with twice the value of <fr:tex
display="inline"><![CDATA[c]]></fr:tex> in the definition.</html:li>
  <html:li>Because constant factors drop out, the base of logarithms is irrelevant.</html:li>
  <html:li>Insignificant terms drop out.  To see that <fr:tex
display="inline"><![CDATA[O(n^2+50n+36)]]></fr:tex> is the same as <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>, consider that <fr:tex
display="inline"><![CDATA[n^2+50n+36/n^2]]></fr:tex> converges to 1 for increasing <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. In fact, <fr:tex
display="inline"><![CDATA[n^2+50n+36 \le  2n^2]]></fr:tex> for <fr:tex
display="inline"><![CDATA[n\ge  51]]></fr:tex>, so can double the constant factor</html:li></html:ul><html:p>If <fr:tex
display="inline"><![CDATA[c]]></fr:tex> and <fr:tex
display="inline"><![CDATA[d]]></fr:tex> are constants (that is, they are independent of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>) with <fr:tex
display="inline"><![CDATA[0 < c < d]]></fr:tex> then</html:p><html:ul><html:li><fr:tex
display="inline"><![CDATA[O(n^c)]]></fr:tex> is contained in <fr:tex
display="inline"><![CDATA[O(n^d)]]></fr:tex></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(c^n)]]></fr:tex> is contained in <fr:tex
display="inline"><![CDATA[O(d^n)]]></fr:tex></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> is contained in <fr:tex
display="inline"><![CDATA[O(n^c)]]></fr:tex></html:li></html:ul><html:p>To say that <fr:tex
display="inline"><![CDATA[O(c^n)]]></fr:tex> <html:em>is contained in</html:em> <fr:tex
display="inline"><![CDATA[O(d^n)]]></fr:tex> means that the former gives
a tighter bound than the latter.  For example, if <fr:tex
display="inline"><![CDATA[f(n)=O(2^n)]]></fr:tex> then
<fr:tex
display="inline"><![CDATA[f(n)=O(3^n)]]></fr:tex> trivially, but the converse does not hold.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-complexity-classes/</fr:uri><fr:display-uri>focs-complexity-classes</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-complexity-classes/</fr:route><fr:title
text="Common Complexity Classes">Common Complexity Classes</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> is <html:em>constant</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> is <html:em>logarithmic</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> is <html:em>linear</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> is <html:em>quasi-linear</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> is <html:em>quadratic</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n^3)]]></fr:tex> is <html:em>cubic</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(a^n)]]></fr:tex> is <html:em>exponential</html:em> (for fixed <fr:tex
display="inline"><![CDATA[a]]></fr:tex>)</html:li></html:ul><html:p>Logarithms grow very slowly, so <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> complexity is excellent.  Because
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> ignores constant factors, the base of the logarithm is
irrelevant!</html:p><html:p>Under linear we might mention <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>, which occasionally is called
<html:em>quasilinear</html:em> and which scales up well for large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>An example of quadratic complexity is matrix addition: forming the sum of two
<fr:tex
display="inline"><![CDATA[n\times  n]]></fr:tex> matrices obviously takes <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex> additions.  Matrix
multiplication is of cubic complexity, which limits the size of matrices that
we can multiply in reasonable time.  An <fr:tex
display="inline"><![CDATA[O(n^{2.81})]]></fr:tex> algorithm exists, but it
is too complicated to be of much use, even though it is theoretically better.</html:p><html:p>An exponential growth rate such as <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> restricts us to small values of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
Already with <fr:tex
display="inline"><![CDATA[n=20]]></fr:tex> the cost exceeds one million.  However, the worst case
might not arise in normal practice.  OCaml type-checking is exponential in the
worst case, but not for ordinary programs.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sample-costs/</fr:uri><fr:display-uri>focs-sample-costs</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sample-costs/</fr:route><fr:title
text="Sample costs in O notation">Sample costs in O notation</fr:title></fr:frontmatter><fr:mainmatter><html:p>Recall that <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> computes <fr:tex
display="inline"><![CDATA[x^n]]></fr:tex>
by repeated multiplication while <fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link> naively computes the sum
<fr:tex
display="inline"><![CDATA[1+\cdots +n]]></fr:tex>.  Each obviously performs <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> arithmetic operations.  Because
they are not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">tail recursive</fr:link>, their use of space is also <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  The function
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-summing-iter/"
title="Iteratively summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/"
display-uri="focs-summing-iter"
type="local"><html:code>summing</html:code></fr:link> is a version of <html:code>nsum</html:code> with an accumulating argument;
its iterative behaviour lets it work in constant space.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> spares
us from having to specify the units used to measure space.</html:p><html:table>
  <html:tr><html:th>Function</html:th><html:th>Time</html:th><html:th>Space</html:th></html:tr>
  <html:tr><html:td>npower, nsum</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>summing</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n(n+1)/2]]></fr:tex></html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>power</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[\log ~n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[\log ~n]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>sillySum</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[2^n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td></html:tr>
</html:table><html:p>Even ignoring constant factors, the units chosen can influence the result.
Multiplication may be regarded as a single unit of cost.  However, the cost of
multiplying two <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-digit numbers for large <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is itself an important
question, especially now that public-key cryptography uses numbers hundreds of
digits long.</html:p><html:p>Few things can <html:em>really</html:em> be done in constant time or stored in constant
space.  Merely to store the number <fr:tex
display="inline"><![CDATA[n]]></fr:tex> requires <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> bits.  If a
program cost is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>, then we have probably assumed that certain operations
it performs are also <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>—typically because we expect never to exceed the
capacity of the standard hardware arithmetic.</html:p><html:p>With <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link>, the precise number of operations depends upon <fr:tex
display="inline"><![CDATA[n]]></fr:tex> in a
complicated way, depending on how many odd numbers arise, so it is convenient
that we can just write <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  An accumulating argument could reduce its
space cost to <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recurrences/</fr:uri><fr:display-uri>focs-recurrences</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recurrences/</fr:route><fr:title
text="Some Simple Recurrence Relations">Some Simple Recurrence Relations</fr:title></fr:frontmatter><fr:mainmatter><html:p>Consider a function <fr:tex
display="inline"><![CDATA[T(n)]]></fr:tex> that has a cost we want to bound using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link>.
A typical <html:em>base case</html:em> is <fr:tex
display="inline"><![CDATA[T(1)=1]]></fr:tex>.  Some <html:em>recurrences</html:em> are:</html:p><html:table>
  <html:tr><html:th>Equation</html:th><html:th>Complexity</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+1]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n) = T(n/2)+1]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex></html:td></html:tr>
</html:table><html:p>To analyse a function, inspect its OCaml declaration.  Recurrence equations for
the cost function <fr:tex
display="inline"><![CDATA[T(n)]]></fr:tex> can usually be read off.  Since we ignore constant
factors, we can give the base case a cost of one unit.  Constant work done in
the recursive step can also be given unit cost; since we only need an upper
bound, this unit represents the larger of the two actual costs.  We could use
other constants if it simplifies the algebra.</html:p><html:p>For example, recall our function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link>:</html:p><html:pre><![CDATA[# let rec nsum n =
    if n = 0 then
      0
    else
      n + nsum (n - 1)
val nsum : int -> int = <fun>]]></html:pre><html:p>Given <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>, it performs a constant amount of work (an addition and
subtraction) and calls itself recursively with argument <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  We get the
recurrence equations <fr:tex
display="inline"><![CDATA[T(0)=1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+1]]></fr:tex>.  The closed form is
clearly <fr:tex
display="inline"><![CDATA[T(n)=n+1]]></fr:tex>, as we can easily verify by substitution.  The cost is
<html:em>linear</html:em>.</html:p><html:p>This function, given <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>, calls <html:code>nsum</html:code>, performing <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> work.
Again ignoring constant factors, we can say that this call takes exactly <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
units.</html:p><html:pre><![CDATA[# let rec nsumsum n =
    if n = 0 then
      0
    else
      nsum n + nsumsum (n - 1)
val nsumsum : int -> int = <fun>]]></html:pre><html:p>We get the recurrence equations <fr:tex
display="inline"><![CDATA[T(0)=1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>.  It is easy to
see that <fr:tex
display="inline"><![CDATA[T(n)=(n-1)+\cdots +1=n(n-1)/2=O(n^2)]]></fr:tex>.  The cost is
<html:em>quadratic</html:em>.</html:p><html:p>The function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> divides its input <fr:tex
display="inline"><![CDATA[n]]></fr:tex> into two, with
the recurrence equation <fr:tex
display="inline"><![CDATA[T(n) = T(n/2)+1]]></fr:tex>.  Clearly <fr:tex
display="inline"><![CDATA[T(2^n)=n+1]]></fr:tex>, so
<fr:tex
display="inline"><![CDATA[T(n)=O(\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/</fr:uri><fr:display-uri>focs-ex-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-1/</fr:uri><fr:display-uri>focs-ex-2-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-1/</fr:route><fr:title
text="Iterative power">Iterative power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-2/</fr:uri><fr:display-uri>focs-ex-2-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-2/</fr:route><fr:title
text="Extending the complexity table">Extending the complexity table</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Add a column to the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sillysum/"
title="Silly Summing the First n Integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sillysum/"
display-uri="focs-sillysum"
type="local">table of complexities</fr:link> from <html:em>The Design and Analysis of Computer Algorithms</html:em> with the heading <html:em>60 hours:</html:em></html:p><html:table>
  <html:tr><html:th>complexity</html:th><html:th>1 second</html:th><html:th>1 minute</html:th><html:th>1 hour</html:th><html:th>60 hours</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n]]></fr:tex></html:td><html:td>1000</html:td><html:td>60 000</html:td><html:td>3 600 000</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n \log  n]]></fr:tex></html:td><html:td>140</html:td><html:td>4 895</html:td><html:td>204 095</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{2}]]></fr:tex></html:td><html:td>31</html:td><html:td>244</html:td><html:td>1 897</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{3}]]></fr:tex></html:td><html:td>10</html:td><html:td>39</html:td><html:td>153</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[2^{n}]]></fr:tex></html:td><html:td>9</html:td><html:td>15</html:td><html:td>21</html:td><html:td /></html:tr>
</html:table></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-3/</fr:uri><fr:display-uri>focs-ex-2-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-3/</fr:route><fr:title
text="Simplifying sums in O notation">Simplifying sums in O notation</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Let <fr:tex
display="inline"><![CDATA[g_1]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[g_k]]></fr:tex> be functions such that <fr:tex
display="inline"><![CDATA[g_i(n)\ge 0]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=1]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[k]]></fr:tex> and all sufficiently
large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>Show that if <fr:tex
display="inline"><![CDATA[f(n) = O(a_1 g_1(n)+\cdots +a_k g_k(n))]]></fr:tex> then <fr:tex
display="inline"><![CDATA[f(n) = O(g_1(n)+\cdots +g_k(n))]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:uri><fr:display-uri>focs-ex-2-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:route><fr:title
text="A tighter recurrence bound">A tighter recurrence bound</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Find an upper bound for the recurrence given by <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+1]]></fr:tex>.  You should be
able to find a tighter bound than <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/</fr:uri><fr:display-uri>focs-lists</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lists/</fr:route><fr:title
text="Lists">Lists</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let x = [3; 5; 9]
val x : int list = [3; 5; 9]
# let y = [(1, "one"); (2, "two")]
val y : (int * string) list = [(1, "one"); (2, "two")]]]></html:pre><html:p>A <html:em>list</html:em> is an ordered series of elements; repetitions are significant.
So <html:code>[3; 5; 9]</html:code> differs from <html:code>[5; 3; 9]</html:code> and from <html:code>[3; 3; 5; 9]</html:code>.  Elements in the
list are separated with <html:code>;</html:code> when constructed, as opposed to the <html:code>,</html:code> syntax
used for fixed-length tuples.</html:p><html:p>All elements of a list must have the same type.  Above we see a list of
integers and a list of <html:code>(integer, string)</html:code> pairs.  One can also have lists of
lists, such as <html:code>[[3]; []; [5; 6]]</html:code>, which has type <html:code>int list list</html:code>.</html:p><html:p>In the general case, if <fr:tex
display="inline"><![CDATA[x_1; \ldots ; x_n]]></fr:tex> all have the same type (say
<fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>) then the list <fr:tex
display="inline"><![CDATA[[x_1;\ldots ;x_n]]]></fr:tex> has type <fr:tex
display="inline"><![CDATA[(\tau )\texttt {list}]]></fr:tex>.</html:p><html:p>Lists are the simplest data structure that can be used to process collections
of items.  Conventional languages use <fr:link
href="/teaching/2627/FoundsCS/forest/focs-arrays/"
title="Arrays"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-arrays/"
display-uri="focs-arrays"
type="local"><html:em>arrays</html:em></fr:link> whose elements are
accessed using subscripting: for example, <fr:tex
display="inline"><![CDATA[A[i]]]></fr:tex> yields the <fr:tex
display="inline"><![CDATA[i]]></fr:tex>th element of
the array <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  Subscripting errors are a known cause of programmer grief,
however, so arrays should be replaced by higher-level data structures whenever
possible.</html:p><html:pre><![CDATA[# x @ [2; 10]
- : int list = [3; 5; 9; 2; 10]
# List.rev [(1, "one"); (2, "two")]
- : (int * string) list = [(2, "two"); (1, "one")]]]></html:pre><html:p>The infix operator <html:code>@</html:code> (also called <html:code>List.append</html:code>) concatenates two lists.
Also built-in is <html:code>List.rev</html:code>, which reverses a list.  These are demonstrated
in the session above.</html:p><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/</fr:uri><fr:display-uri>focs-list-primitives</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-list-primitives/</fr:route><fr:title
text="The List Primitives">The List Primitives</fr:title></fr:frontmatter><fr:mainmatter><html:p>There are two kinds of lists:</html:p><html:ul><html:li><html:code>[]</html:code> represents the empty list</html:li>
  <html:li><html:code>x :: l</html:code> is the list with head <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and tail <fr:tex
display="inline"><![CDATA[l]]></fr:tex></html:li></html:ul><html:pre><![CDATA[# let nil = []
val nil : 'a list = []
# 1 :: nil
- : int list = [1]
# 1 :: 2 :: nil
- : int list = [1; 2]]]></html:pre><html:p>The operator <html:code>::</html:code> (also called <html:code>List.cons</html:code> for “construct”), puts a new element on
to the head of an existing list.  While we should not be too preoccupied with
implementation details, it is essential to know that <html:code>::</html:code> is an <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
operation.  It uses constant time and space, regardless of the length of the
resulting list.  Lists are represented internally with a linked structure;
adding a new element to a list merely hooks the new element to the front of
the existing structure.  Moreover, that structure continues to denote the same
list as it did before; to see the new list, one must look at the new <html:code>::</html:code> node
(or “cons cell”) just created.  We will explain the <html:code>'a</html:code> notation in the next
section.</html:p><html:p>Here we see the element <html:code>1</html:code> being consed to the front of the list <html:code>[3; 5; 9]</html:code>:</html:p><fr:tex
display="block"><![CDATA[\begin{array}{ccccccccccc}
:: & \to & \cdots & :: & \to &  :: & \to &  :: & \to & [] \\
\downarrow &  &        & \downarrow &  & \downarrow &  & \downarrow  \\
1     &  &        & 3     &  & 5     &  & 9
\end{array}]]></fr:tex><html:p>Given a list, taking its first element (its “head”) or its list of
remaining elements (its “tail”) also takes constant time.  Each
operation just follows a link.  In the diagram above, the first down arrow
leads to the head and the leftmost right arrow leads to the tail.  Once we
have the tail, its head is the second element of the original list, etc.</html:p><html:p>The tail is <html:em>not</html:em> the last element; it is the <html:em>list</html:em> of all elements
other than the head!</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/</fr:uri><fr:display-uri>focs-head-tail</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-head-tail/</fr:route><fr:title
text="Getting at the Head and Tail">Getting at the Head and Tail</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let null = function
    | [] -> true
    | x :: l -> false
val null : 'a list -> bool = <fun>
# null []
- : bool = true
# null [1; 2; 3]
- : bool = false
# let hd (x::l) = x
Line 1, characters 8-14:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val hd : 'a list -> 'a = <fun>
# hd [1; 2; 3]
- : int = 1
# let tl (x::l) = l
Line 1, characters 8-14:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val tl : 'a list -> 'a list = <fun>
# tl [7; 6; 5]
- : int list = [6; 5]]]></html:pre><html:p>The empty list has neither head nor tail.  Applying <html:code>hd</html:code> or <html:code>tl</html:code> to <html:code>[]</html:code>
is an error—strictly speaking, an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">“exception”</fr:link>.  The function <html:code>null</html:code> can
be used to check for the empty list beforehand.  Taking a list apart using
combinations of <html:code>hd</html:code> and <html:code>tl</html:code> is hard to get right.  Fortunately, it is seldom
necessary because of <html:em>pattern-matching</html:em>.</html:p><html:p>The declaration of <html:code>null</html:code> introduces a new concept known as "pattern matching",
which we will explore more in subsequent lectures. For now, it is sufficient
to observe that <html:code>let null = function</html:code> allows for matching on the two possible values
that might be passed in as argument to <html:code>null</html:code> here: one for the empty list (for which it returns <html:code>true</html:code>)
and one for non-empty lists (for which it returns <html:code>false</html:code>).</html:p><html:p>The declaration of <html:code>hd</html:code> above has only one clause, for non-empty lists.  They
have the form <html:code>x::l</html:code> and the function returns <html:code>x</html:code>, which is the head.  If you
compile this program, OCaml also prints a warning to tell us that calling
the function could raise an exception because not all possible inputs are handled,
including a counter-example (in this case, the empty list <html:code>[]</html:code>). The declaration of <html:code>tl</html:code> is similar to <html:code>hd</html:code>.</html:p><html:p>These three primitive functions are <html:em>polymorphic</html:em> and allow flexibility in the
types of their arguments and results. Note their types!</html:p><html:pre><![CDATA[# null
- : 'a list -> bool = <fun>
# hd
- : 'a list -> 'a = <fun>
# tl
- : 'a list -> 'a list = <fun>]]></html:pre><html:p>Symbols <html:code>'a</html:code> and <html:code>'b</html:code> are called <html:em>type variables</html:em> and stand for any types. Code
written using these functions is checked for type correctness at compile time.
And this guarantees strong properties at run time, for example that the
elements of any list all have the same type.  They are usually read as their
corresponding greek characters; <html:code>'a</html:code> is "alpha", <html:code>'b</html:code> is "beta", and so on.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nlength/</fr:uri><fr:display-uri>focs-nlength</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nlength/</fr:route><fr:title
text="Computing the Length of a List">Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nlength = function
  | [] -> 0
  | x :: xs -> 1 + nlength xs
val nlength : 'a list -> int = <fun>
# nlength []
- : int = 0
# nlength [5; 6; 7]
- : int = 3]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nlength }[a; b; c] \Rightarrow  &\; 1 + \text {nlength }[b; c] \\
   \Rightarrow  &\; 1 + (1 + \text {nlength }[c]) \\
   \Rightarrow  &\; 1 + (1 + (1 + \text {nlength }[])) \\
   \Rightarrow  &\; 1 + (1 + (1 + 0)) \\
   \Rightarrow  &\; \ldots  \;\; 3
\end {aligned}
]]></fr:tex><html:p>Most list processing involves <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  This is a simple example; patterns
can be more complex.  Observe the use of a vertical bar <html:code>|</html:code> to separate the function’s
clauses.  We have <html:em>one</html:em> function declaration that handles two cases.
To understand its role, consider the following faulty code:</html:p><html:pre><![CDATA[# let rec nlength [] = 0
Line 1, characters 17-19:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_

val nlength : 'a list -> int = <fun>
# let rec nlength (x::xs) = 1 + nlength xs
Line 1, characters 17-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val nlength : 'a list -> int = <fun>]]></html:pre><html:p>These are two declarations, not one.  First we declare <html:code>nlength</html:code> to be a
function that handles only empty lists.  Then we redeclare it to be a function
that handles only non-empty lists; it can never deliver a result.  We see that
a second <html:code>let</html:code> declaration replaces any previous one rather than extending it
to cover new cases.</html:p><html:p>Now, let us return to our original declaration of <html:code>nlength</html:code>.  The length function
is <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link></html:em> and applies to <html:em>all</html:em> lists regardless of element
type!  Most programming languages lack such flexibility.</html:p><html:p>Unfortunately, this length computation is naive and wasteful.  Like
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link> earlier, it is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">tail-recursive</fr:link>.  It
uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its input.  As usual, the
solution is to add an accumulating argument.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/</fr:uri><fr:display-uri>focs-length</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-length/</fr:route><fr:title
text="Efficiently Computing the Length of a List">Efficiently Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec addlen n = function
  | []    -> n
  | x::xs -> addlen (n + 1) xs
val addlen : int -> 'a list -> int = <fun>
# addlen 0 [5; 6; 7]
- : int = 3]]></html:pre><html:p>Recall that the use of <html:code>function</html:code> introduces an extra (unnamed) argument
that is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matched</fr:link> in the subsequent clauses; in this case, to break
open the list.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {addlen }0 [a; b; c] \Rightarrow  &\;  \text {addlen }1\;[b; c] \\
  \Rightarrow   &\; \text {addlen }2\;[c] \\
  \Rightarrow   &\; \text {addlen }3\;[] \\
  \Rightarrow   &\; 3
\end {aligned}
]]></fr:tex><html:p>Function <html:code>addlen</html:code> is again <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.  Its type mentions the integer
accumulator.</html:p><html:p>Now we may declare an efficient length function.  It is simply a wrapper for
<html:code>addlen</html:code>, supplying zero as the initial value of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# let length xs = addlen 0 xs
val length : 'a list -> int = <fun>
# length [5; 6; 7; 8]
- : int = 4]]></html:pre><html:p>The recursive calls do not nest: this version is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It takes <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
space.  Obviously its time requirement is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> because it takes at least <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
steps to find the length of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/</fr:uri><fr:display-uri>focs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-append/</fr:route><fr:title
text="Append: List Concatenation">Append: List Concatenation</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec append xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> x :: append xs ys
val append : 'a list -> 'a list -> 'a list = <fun>
# append [1; 2; 3] [4]
- : int list = [1; 2; 3; 4]
# let (@) = append
val ( @ ) : 'a list -> 'a list -> 'a list = <fun>
# [1; 2; 3] @ [4]
- : int list = [1; 2; 3; 4]]]></html:pre><html:p>Patterns can be as complicated as we like.  Here, the two patterns are
<html:code>[], ys</html:code> and <html:code>x::xs, ys</html:code>.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {append }[1; 2; 3] [4] \Rightarrow  &\; 1 :: \text {append }[2; 3]\;[4] \\
  \Rightarrow  &\; 1 :: (2 :: \text {append }[3]\;[4]) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: \text {append }[]\;[4])) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: [4])) \ [1; 2; 3; 4]
\end {aligned}
]]></fr:tex><html:p>Here is how append might be declared, also noting that we have defined <html:code>@</html:code> as
an infix operator that is a more convenient way to call <html:code>append</html:code> on two lists.
However, this function is also not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It scans its first
argument, sets up a string of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code> operations</fr:link> (<html:code>::</html:code>) and finally does them.</html:p><html:p>It uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its first argument.
<html:em>Its costs are independent of its second argument.</html:em></html:p><html:p>An accumulating argument could make it iterative, but with considerable
complication.  The iterative version would still require <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time
because concatenation requires copying all the elements of the first list.
Therefore, we cannot hope for asymptotic gains; at best we can decrease the
constant factor involved in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>, but complicating the code is likely to
increase that factor.  Never add an accumulator merely out of habit.</html:p><html:p>Note append’s <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic type</fr:link>. It tells us that two lists can be joined if
their element types agree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nrev/</fr:uri><fr:display-uri>focs-nrev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nrev/</fr:route><fr:title
text="Reversing a List in O(n^2)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:p>Let us consider one way to reverse a list.</html:p><html:pre><![CDATA[# let rec nrev = function
  | [] -> []
  | x::xs -> (nrev xs) @ [x]
val nrev : 'a list -> 'a list = <fun>
# nrev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nrev }[a; b; c] \Rightarrow  &\; \text {nrev }[b; c]\;@\;[a] \\
  \Rightarrow  &\;  (\text {nrev }[c]\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  ((\text {nrev }[]\;@\;[c])\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  (([]\;@\;[c])\;@\;[b])\;@\;[a] \ \ldots  \ [c; b; a]
\end {aligned}
]]></fr:tex><html:p>This reverse function is grossly inefficient due to poor usage of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>, which
copies its first argument.  If <html:code>nrev</html:code> is given a list of length <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>, then
append makes <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> conses to copy the reversed tail.  Constructing the list
<html:code>[x]</html:code> calls <html:code>cons</html:code> again, for a total of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> calls.  Reversing the tail
requires <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> more conses, and so forth.  The total number of conses is:</html:p><fr:tex
display="block"><![CDATA[ 0 + 1 + 2 + \cdots  + n = {n(n+1)/2} ]]></fr:tex><html:p>The time complexity is therefore <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Space complexity is only <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>
because the copies don’t all exist at the same time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/</fr:uri><fr:display-uri>focs-rev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-rev/</fr:route><fr:title
text="Reversing a List in O(n)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec rev_app xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> rev_app xs (x::ys)
val rev_app : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {rev\_app }[a; b; c]\;[] \Rightarrow  &\; \text {rev\_app }[b; c]\; [a] \\
  \Rightarrow  &\; \text {rev\_app }[c]\; [b; a] \\
  \Rightarrow  &\; \text {rev\_app }[]\; [c; b; a] \\
  \Rightarrow  &\; [c; b; a]
\end {aligned}
]]></fr:tex><html:p>Calling <html:code>rev_app xs ys</html:code> reverses the elements of <html:code>xs</html:code> and
prepends them to <html:code>ys</html:code>.  Now we may declare</html:p><html:pre><![CDATA[# let rev xs = rev_app xs []
val rev : 'a list -> 'a list = <fun>
# rev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><html:p>It is easy to see that this reverse function performs just <fr:tex
display="inline"><![CDATA[n]]></fr:tex> conses, given
an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.  For both reverse functions, we could count the number of
conses precisely—not just up to a constant factor.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-o-notation/"
title="Comparing Algorithms: O Notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/"
display-uri="focs-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> is still
useful to describe the overall running time: the time taken by a cons
varies from one system to another.</html:p><html:p>The accumulator <fr:tex
display="inline"><![CDATA[y]]></fr:tex> makes the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  But the gain in complexity
arises from the removal of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.  Replacing an expensive operation (append)
by a series of cheap operations (cons) is called <html:em>reduction in strength</html:em>
and is a common technique in computer science.  It originated when many
computers did not have a hardware multiply instruction; the series of products
<fr:tex
display="inline"><![CDATA[i\times  r]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, <fr:tex
display="inline"><![CDATA[\ldots , n]]></fr:tex> could more efficiently be computed by
repeated addition.  Reduction in strength can be done in various ways; we
shall see many instances of removing append.</html:p><html:p>Consing to an accumulator produces the result in reverse.  If
that forces the use of an extra list reversal then the iterative function
may be much slower than the recursive one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-strings-chars/</fr:uri><fr:display-uri>focs-strings-chars</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-strings-chars/</fr:route><fr:title
text="Lists, Strings and Characters">Lists, Strings and Characters</fr:title></fr:frontmatter><fr:mainmatter><html:p>Strings are provided in most programming languages to allow text processing.
Strings are essential for communication with users. Even a purely numerical
program formats its results ultimately as strings.</html:p><html:pre><![CDATA[# 'a'   (* a character constant *)
- : char = 'a'
# "a"   (* a string constant of length 1 *)
- : string = "a"
# "abc" (* a string constant of length 3 *)
- : string = "abc"
# String.length "abc"
- : int = 3
# "abc" ^ "def"  (* concatenate two strings *)
- : string = "abcdef"]]></html:pre><html:p>In a few programming languages, strings simply are lists of characters. In
OCaml they are a separate type, unrelated to lists, reflecting the fact that
strings are an abstract concept in themselves.</html:p><html:p>Similarly, characters are not strings of size one, but are a primitive concept.
Character constants in OCaml have the form <html:code>'c'</html:code>, where <fr:tex
display="inline"><![CDATA[c]]></fr:tex> is any character.
For example, the comma character is <html:code>','</html:code>.</html:p><html:p>Special characters are coded in strings using <html:em>escape sequences</html:em> involving the
backslash character; among many others, a double quote is written <html:code><![CDATA["\\"]]></html:code> and
the newline character is written <html:code><![CDATA["\n"]]></html:code>. For example, the string
<html:code><![CDATA["I\nLIKE\nCHEESE\n"]]></html:code> represents three text lines.</html:p><html:p>In addition to the operators described above, the relations <html:code>&lt;</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code>, and
<html:code>&gt;=</html:code> work for strings and yield alphabetic order (more precisely, lexicographic
order with respect to ASCII character codes).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/</fr:uri><fr:display-uri>focs-ex-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:uri><fr:display-uri>focs-ex-3-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:route><fr:title
text="Summing a list">Summing a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function</fr:link> to compute the sum of a list’s elements. Then code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version
and comment on the improvement in efficiency.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:uri><fr:display-uri>focs-ex-3-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:route><fr:title
text="Last element of a list">Last element of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the last element of a non-empty list. How efficiently can this be done?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:uri><fr:display-uri>focs-ex-3-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:route><fr:title
text="Even-numbered elements">Even-numbered elements</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the list consisting of the even-numbered elements of the list given as its
argument. For example, given <html:code>[a; b; c; d]</html:code> it should return <html:code>[b; d]</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-4/</fr:uri><fr:display-uri>focs-ex-3-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-4/</fr:route><fr:title
text="Polymorphic types of id and loop">Polymorphic types of id and loop</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic types</fr:link> in these two function declarations:</html:p><html:pre><![CDATA[# let id x = x
val id : 'a -> 'a = <fun>
# let rec loop x = loop x
val loop : 'a -> 'b = <fun>]]></html:pre><html:p>Explain why these types make logical sense, preventing run time type errors, even for expressions
like <html:code>id [id [id 0]]</html:code> or <html:code>loop true / loop 3</html:code>. (<html:code>/</html:code> is the integer division operator in OCaml)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:uri><fr:display-uri>focs-ex-3-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:route><fr:title
text="Tails of a list">Tails of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function <html:code>tails</html:code> to return the list of the tails of its argument. For example, given
<html:code>[1; 2; 3]</html:code> it should return <html:code>[[1; 2; 3]; [2; 3]; [3]; []]</html:code>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/</fr:uri><fr:display-uri>focs-more-lists</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-more-lists/</fr:route><fr:title
text="More on Lists">More on Lists</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/</fr:uri><fr:display-uri>focs-take-drop</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-take-drop/</fr:route><fr:title
text="List Utilities: take and drop">List Utilities: take and drop</fr:title></fr:frontmatter><fr:mainmatter><html:p>This lecture examines more list utilities, illustrating more patterns of
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>, and concludes with a small program for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.</html:p><html:p>The functions <html:code>take</html:code> and <html:code>drop</html:code> divide a list
into parts, returning or discarding the first <fr:tex
display="inline"><![CDATA[i]]></fr:tex> elements.</html:p><fr:tex
display="block"><![CDATA[xs = [\underbrace {x_0,\ldots ,x_{i-1}}_{\text {take i xs}},
      \underbrace {x_i,\ldots ,x_{n-1}}_{\text {drop i xs}} ]]]></fr:tex><html:p>They can be implemented in OCaml as follows:</html:p><html:pre><![CDATA[# let rec take i = function
    | [] -> []
    | x::xs ->
        if i > 0 then x :: take (i - 1) xs
        else []
val take : int -> 'a list -> 'a list = <fun>
# let rec drop i = function
    | [] -> []
    | x::xs ->
        if i > 0 then drop (i-1) xs
        else x::xs
val drop : int -> 'a list -> 'a list = <fun>]]></html:pre><html:p>Applications of <html:code>take</html:code> and <html:code>drop</html:code> will appear in future lectures.  Typically,
they divide a collection of items into equal parts for recursive processing.</html:p><html:p>The <html:code>take</html:code> function is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>, but making it so would not improve
its efficiency.  The task requires copying up to <fr:tex
display="inline"><![CDATA[i]]></fr:tex> list elements, which must
take <fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> space and time.</html:p><html:p>Function <html:code>drop</html:code> simply skips over <fr:tex
display="inline"><![CDATA[i]]></fr:tex> list elements.  This requires
<fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> time but only constant space.  It is iterative and much faster than
<html:code>take</html:code>.  Both functions use <fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> time, but skipping elements is faster
than copying them:  <html:code>drop</html:code>’s constant factor is smaller.</html:p><html:p>Both functions take an integer and a list, returning a list of the same type.
So their type is <html:code>int -&gt; 'a list -&gt; 'a list</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:uri><fr:display-uri>focs-linear-search</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:route><fr:title
text="Linear Search">Linear Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>find <fr:tex
display="inline"><![CDATA[x]]></fr:tex> in list <fr:tex
display="inline"><![CDATA[[x_1,\ldots ,x_n]]]></fr:tex> by comparing with each element</html:li>
  <html:li>obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time</html:li>
  <html:li>simple &amp; general</html:li>
  <html:li>ordered searching needs only <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:li>
  <html:li>indexed lookup needs only <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p><html:em>Linear search</html:em> is the obvious way to find a desired item in a
collection: simply look through all the items, one at a time.  If <fr:tex
display="inline"><![CDATA[x]]></fr:tex> is in
the list, then it will be found in <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> steps on average, and even the worst
case is obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p><html:p>Large collections of data are usually ordered or indexed so that items can be
found in <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> time, which is exponentially better than <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Even
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> is achievable (using a hash table), though subject to the usual
proviso that machine limits are not exceeded.</html:p><html:p>Efficient indexing methods are of prime importance: consider Web
search engines.  Nevertheless, linear search is often used to search small
collections because it is so simple and general, and it is the starting point
for better algorithms.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/</fr:uri><fr:display-uri>focs-equality</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-equality/</fr:route><fr:title
text="Equality Tests">Equality Tests</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec member x = function
   | [] -> false
   | y::l ->
      if x = y then true
      else member x l
val member : 'a -> 'a list -> bool = <fun>]]></html:pre><html:p>All the list functions we have encountered up to now have been “<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>”,
working for lists of any type.  Function <html:code>member</html:code> uses <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link> to report
whether or not <html:code>x</html:code> occurs in <html:code>l</html:code>.</html:p><html:p>To do this generically, it uses a special feature of OCaml known as
“polymorphic equality”, which manifests itself via the <html:code>=</html:code>, <html:code>&gt;=</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code> and
<html:code>&lt;</html:code> operators.  These operators inspect the <html:em>structure</html:em> of the values using a
consistent order.  Types you can legitimately compare this way include integers,
strings, booleans, and tuples or lists of primitive types.</html:p><html:p>More complex types can be compared this way within careful limits: recursive
structures or function values will not work (we will cover function values in
the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-currying/"
title="Curried Functions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/"
display-uri="focs-currying"
type="local">Currying lecture</fr:link> later).  For now, it is sufficient to use these magic
polymorphic equality operators.  As you get more familiar with OCaml and the
use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functions/"
title="Functions as Values"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/"
display-uri="focs-functions"
type="local">higher order functions</fr:link> (also covered in a later lecture), you will
encounter the use of explicit <html:code>compare</html:code> functions that are used to provide more
complex equality tests.</html:p><html:p>The presence of polymorphic equality is a contentious feature in OCaml.  While
it provides a great ease of use in smaller codebases, it starts to become more
dangerous when building larger OCaml-based systems.  Most large-scale users of
OCaml tend towards not using it in important code, but it is just fine for our
purposes while learning the beginning steps of computer science.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/</fr:uri><fr:display-uri>focs-zip</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-zip/</fr:route><fr:title
text="Building a List of Pairs">Building a List of Pairs</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec zip xs ys =
    match xs, ys with
    | (x::xs, y::ys) -> (x, y) :: zip xs ys
    | _ -> []
val zip : 'a list -> 'b list -> ('a * 'b) list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[\left .[x_1,\ldots ,x_n]\atop 
         [y_1,\ldots ,y_n]\right \}\;\longmapsto \;[(x_1,y_1),\ldots ,(x_n,y_n)]]]></fr:tex><html:p>The <html:em>wildcard</html:em> pattern <html:code>_</html:code> matches <html:em>anything</html:em>. We could have written a
variable such as <html:code>p</html:code> instead, but the wildcard reminds us that the
relevant clause ignores this argument.</html:p><html:p>The patterns are also tested in order of their definitions: first
<html:code>(x::xs, y::ys)</html:code>, then <html:code>_</html:code>.</html:p><html:p>A list of pairs of the form <fr:tex
display="inline"><![CDATA[[(x_1,y_1),\ldots ,(x_n,y_n)]]]></fr:tex> associates each
<fr:tex
display="inline"><![CDATA[x_i]]></fr:tex> with <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex>.  Conceptually, a telephone directory could be regarded as
such a list, where <fr:tex
display="inline"><![CDATA[x_i]]></fr:tex> ranges over names and <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex> over the corresponding
telephone number.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link> in such a list can find the <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex> associated
with a given <fr:tex
display="inline"><![CDATA[x_i]]></fr:tex>, or vice versa—very slowly.</html:p><html:p>In other cases, the <fr:tex
display="inline"><![CDATA[(x_i,y_i)]]></fr:tex> pairs might have been generated by applying a
function to the elements of another list <fr:tex
display="inline"><![CDATA[[z_1,\ldots ,z_n]]]></fr:tex>.</html:p><html:pre><![CDATA[# let rec unzip = function
   | [] -> ([], [])
   | (x, y)::pairs ->
       let xs, ys = unzip pairs in
       (x::xs, y::ys)
val unzip : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>Given a list of pairs, <html:code>unzip</html:code> has to build <html:em>two</html:em> lists of
results, which is awkward using recursion.  The version shown above uses the
<html:em>local binding</html:em> <html:code>let p = </html:code><fr:tex
display="inline"><![CDATA[\;E_1\;]]></fr:tex><html:code> in </html:code><fr:tex
display="inline"><![CDATA[\;E_2]]></fr:tex>,
where the value of <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> is bound to the variable <html:code>p</html:code> within <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex>. The
let-construct counts as an expression and can be used (perhaps wrapped
within parentheses) wherever an expression is expected.</html:p><html:p>Note especially the phrase <html:code>let xs, ys = unzip pairs</html:code>
which binds <html:code>xs</html:code> and <html:code>ys</html:code> to the results of the recursive call.
In general, the phrase <html:code>let P = E</html:code> matches the
pattern <fr:tex
display="inline"><![CDATA[P]]></fr:tex> against the value of expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.  It binds all the variables
in <fr:tex
display="inline"><![CDATA[P]]></fr:tex> to the corresponding values.</html:p><html:p>The functions <html:code>zip</html:code> and <html:code>unzip</html:code> build and take apart lists of
pairs: <html:code>zip</html:code> pairs up corresponding list elements and <html:code>unzip</html:code>
inverts this operation.  Their types reflect what they do:</html:p><html:pre><![CDATA[# zip
- : 'a list -> 'b list -> ('a * 'b) list = <fun>
# unzip
- : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>If the lists are of unequal length, <html:code>zip</html:code> discards surplus items at the
end of the longer list.  Its first pattern only matches a pair of non-empty
lists.  The second pattern is just a wildcard and could match anything.  OCaml
tries the clauses in the order given, so the first pattern is tried first.
The second only gets arguments where at least one of the lists is empty.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-unzip/</fr:uri><fr:display-uri>focs-unzip</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-unzip/</fr:route><fr:title
text="Building a Pair of Results">Building a Pair of Results</fr:title></fr:frontmatter><fr:mainmatter><html:p>Here is a version of <html:code>unzip</html:code> that replaces the local declaration by a
function <html:code>conspair</html:code> for taking apart the pair of lists in the
recursive call.  It defines the same
computation as the previous version of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local"><html:code>unzip</html:code></fr:link> and is possibly clearer,
but not every local binding can be eliminated as easily.</html:p><html:pre><![CDATA[# let conspair ((x, y), (xs, ys)) = (x::xs, y::ys)
val conspair : ('a * 'b) * ('a list * 'b list) -> 'a list * 'b list = <fun>
# let rec unzip = function
    | [] -> ([], [])
    | xy :: pairs -> conspair (xy, unzip pairs)
val unzip : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>Making the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> yields <html:code>revUnzip</html:code> below, which is
very simple.  Iteration can construct many results at once in different
argument positions.  Both output lists are built in reverse order, which can
be corrected by reversing the input to <html:code>revUnzip</html:code>.  The total costs
will probably exceed those of <html:code>unzip</html:code> despite the advantages of
iteration.</html:p><html:pre><![CDATA[# let rec revUnzip = function
    | ([], xs, ys) -> (xs, ys)
    | ((x, y)::pairs, xs, ys) ->
        revUnzip (pairs, x::xs, y::ys)
val revUnzip : ('a * 'b) list * 'a list * 'b list -> 'a list * 'b list =
  <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/</fr:uri><fr:display-uri>focs-making-change</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-making-change/</fr:route><fr:title
text="An Application: Making Change">An Application: Making Change</fr:title></fr:frontmatter><fr:mainmatter><html:p>Consider a till that has unlimited supplies of coins.  The largest coins should be tried
first, to avoid giving change all in pennies.  The list of legal coin values,
called <html:code>till</html:code>, is given in descending order, such as 50, 20, 10, 5,
2 and 1.  (Recall that the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">head of a list</fr:link> is the element most easily reached.)
The code for <html:code>change</html:code> is based on simple observations:</html:p><html:ul><html:li>Change for zero consists of no coins at all.  (Note the pattern of <html:code>0</html:code> in the first clause.)</html:li>
  <html:li>For a nonzero amount, try the largest available coin.  If it is small enough, use it and decrease the amount accordingly.</html:li>
  <html:li>Exclude from consideration any coins that are too large.</html:li></html:ul><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise (Failure "no more coins!")
    | c::till, amt -> if amt < c then change till amt
                      else c :: change (c::till) (amt - c)
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>Although nobody considers making change for zero, this is the simplest way to
make the algorithm terminate.  Most iterative procedures become simplest if,
in their base case, they do nothing.  A base case of one instead of zero is
often a sign of a novice programmer.</html:p><html:ul><html:li>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link> <html:em>terminates</html:em> when <html:code>amt = 0</html:code>.</html:li>
  <html:li>Tries the <html:em>largest coin first</html:em> to use large coins.</html:li>
  <html:li>The algorithm is <html:em>greedy</html:em> and can fail!</html:li></html:ul><html:p>The function can terminate either with success or failure.  It fails by
raising exception <html:code>Failure</html:code> namely if <html:code>till</html:code> becomes empty while <html:code>amt</html:code> is still nonzero.
(<fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">Exceptions</fr:link> will be discussed later.)</html:p><html:p>Unfortunately, failure can occur even when change can be made.  The greedy
"largest coin first" approach is to blame.  Suppose we have coins of values 5
and 2, and must make change for 6; the only way is <fr:tex
display="inline"><![CDATA[6=2+2+2]]></fr:tex>, ignoring the 5.
<html:em>Greedy algorithms</html:em> are often effective, but not here.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/</fr:uri><fr:display-uri>focs-change-all</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-all/</fr:route><fr:title
text="All Ways of Making Change">All Ways of Making Change</fr:title></fr:frontmatter><fr:mainmatter><html:p>Now we generalise the problem to return the list of <html:em>all possible ways</html:em> of making change,
and write a new <html:code>change</html:code> function.</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Look at the type: the result is now a list of lists.
The code will also never raise <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>.  It expresses failure by returning an
empty list of solutions: it returns <html:code>[]</html:code> if the till is empty and the
amount is nonzero.</html:p><html:p>If the amount is zero, then there is only one way of making change;
the result should be <html:code><![CDATA[[[]]]]></html:code>.  This is success in the base case.</html:p><html:p>In nontrivial cases, there are two sources of solutions: to use a coin (if
possible) and decrease the amount accordingly, or to remove the current coin
value from consideration.</html:p><html:p>The function <html:code>allc</html:code> is declared locally in order to make use
of <html:code>c</html:code>, the current coin.  It adds an extra <html:code>c</html:code> to all the
solutions returned by the recursive call to make change for <html:code>amt - c</html:code>.</html:p><html:p>Observe the naming convention: <html:code>cs</html:code> is a list of coins, while
<html:code>css</html:code> is a list of such lists.  The trailing ‘s’ is suggestive of a
plural.</html:p><html:p>This complicated program, and the even trickier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-faster/"
title="All Ways of Making Change — Faster!"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/"
display-uri="focs-change-faster"
type="local">faster version</fr:link>, are
included as challenges.  Are you enthusiastic enough to work them out?  We
shall revisit the “making change” task later to illustrate <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-exceptions/"
title="Making Change with Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/"
display-uri="focs-change-exceptions"
type="local">exception-handling</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:uri><fr:display-uri>focs-change-faster</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:route><fr:title
text="All Ways of Making Change — Faster!">All Ways of Making Change — Faster!</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec change till amt chg chgs =
    match till, amt with
    | _       , 0   -> chg::chgs
    | []      , _   -> chgs
    | c::till , amt -> if amt < 0 then chgs
                       else change (c::till) (amt - c) (c::chg)
                                   (change till amt chg chgs)
val change : int list -> int -> int list -> int list list -> int list list =
  <fun>]]></html:pre><html:p>We’ve added <html:em>another</html:em> accumulating parameter!  Repeatedly improving simple code
is called <html:em>stepwise refinement</html:em>.</html:p><html:p>Two extra arguments eliminate many <html:code>::</html:code> and append operations from the
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all-solutions <html:code>change</html:code></fr:link> function.  The first, <html:code>chg</html:code>, accumulates the coins chosen so
far; one evaluation of <html:code>c::chg</html:code> replaces many evaluations of <html:code>allc</html:code>.  The
second, <html:code>chgs</html:code>, accumulates the list of solutions so far; it avoids the need
for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link>.  This version runs several times faster than the previous one.</html:p><html:p>Making change is still extremely slow for an obvious reason: the number of
solutions grows rapidly in the amount being changed.  Using 50, 20, 10, 5,
2 and 1, there are 4366 ways of expressing 99.</html:p><html:p>Our three change functions illustrate a basic technique: program development
by stepwise refinement.  Begin by writing a very simple program and add
requirements individually.  Add efficiency refinements last of all.
Even if the simpler program cannot be included in the next version and has
to be discarded, one has learned about the task by writing it.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/</fr:uri><fr:display-uri>focs-ex-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:uri><fr:display-uri>focs-ex-4-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:route><fr:title
text="Set union without repetitions">Set union without repetitions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Sets can be represented in OCaml using lists containing no duplicated items
(i.e. where no item is equal to another using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link> comparison).</html:p><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link> function defined above, code a function to implement set
union. It should avoid introducing repetitions, for example the union of the
lists <html:code>[4; 7; 1]</html:code> and <html:code>[6; 4; 7]</html:code> should be <html:code>[1; 6; 4; 7]</html:code> (though the order
does not matter).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:uri><fr:display-uri>focs-ex-4-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:route><fr:title
text="Partitioning integers by sign">Partitioning integers by sign</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function that takes a list of integers and returns two lists, the first consisting of all
non-negative numbers found in the input and the second consisting of all the negative numbers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:uri><fr:display-uri>focs-ex-4-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:route><fr:title
text="A non-exhaustive zip">A non-exhaustive zip</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>How does this version of <html:code>zip</html:code> differ from <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local">the one above</fr:link>?</html:p><html:pre><![CDATA[let rec zip xs ys =
  match xs, ys with
  | (x::xs, y::ys) -> (x, y) :: zip xs ys
  | ([], [])   -> []]]></html:pre><html:pre><![CDATA[Lines 2-4, characters 5-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(x::xs, [])]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:uri><fr:display-uri>focs-ex-4-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:route><fr:title
text="Assumptions in making change">Assumptions in making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What assumptions do the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">‘making change’</fr:link> functions make about the variables <html:code>till</html:code> and <html:code>amt</html:code>?
Describe what could happen if these assumptions were violated.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:uri><fr:display-uri>focs-ex-4-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:route><fr:title
text="Counting ways of making change">Counting ways of making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the number of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">ways of making change</fr:link> for <fr:tex
display="inline"><![CDATA[n]]></fr:tex> (ignoring order) is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> if there are two
legal coin values. What if there are three, four, … coin values?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:uri><fr:display-uri>focs-ex-4-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:route><fr:title
text="Reasoning from polymorphic types">Reasoning from polymorphic types</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>We know nothing about the functions <html:code>f</html:code> and <html:code>g</html:code> other than their polymorphic types:
<html:code>val f : 'a * 'b -&gt; 'b * 'a</html:code> and <html:code>val g : 'a -&gt; 'a list</html:code>.
Suppose that <html:code>f (1, true)</html:code> and <html:code>g 0</html:code> are evaluated and return their results. State, with reasons,
what you think the resulting values will be.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/</fr:uri><fr:display-uri>focs-sorting</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting/</fr:route><fr:title
text="Sorting">Sorting</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><html:p>A few applications for sorting and arranging items into order are:</html:p><html:ul><html:li>search</html:li>
  <html:li>merging</html:li>
  <html:li>duplicates</html:li>
  <html:li>inverting tables</html:li>
  <html:li>graphics algorithms</html:li></html:ul><html:p>Sorting is perhaps the most deeply studied aspect of algorithm design.
Knuth’s series <html:em>The Art of Computer Programming</html:em> devotes an entire
volume to sorting and searching!  <fr:link
href="https://algs4.cs.princeton.edu/home/"
type="external">Sedgewick</fr:link>
also covers sorting.  Sorting has countless applications.</html:p><html:p>Sorting a collection allows items to be found quickly.  Recall that <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear
search</fr:link> requires <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> steps to search among <fr:tex
display="inline"><![CDATA[n]]></fr:tex> items.  A sorted collection
admits <html:em>binary search</html:em> which requires only <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> time.  The idea
of binary search is to compare the item being sought with the middle item (in
position <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex>) and then to discard either the left half or the right,
depending on the result of the comparison.  Binary search needs arrays or
trees, not lists; we shall come to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link> later.</html:p><html:p>Two sorted files can quickly be <html:em>merged</html:em> to form a larger sorted file.  Other
applications include finding <html:em>duplicates</html:em> that, after sorting, are adjacent.</html:p><html:p>A telephone directory is sorted alphabetically by name.  The same information
can instead be sorted by telephone number (useful to the police) or by street
address (useful to junk-mail firms).  Sorting information in different ways
gives it different applications.</html:p><html:p>Common sorting algorithms include insertion sort, quicksort,
mergesort and heapsort.  We shall consider the first three of
these.  Each algorithm has its advantages.</html:p><html:p>As a concrete basis for comparison, runtimes are quoted for DECstation
computers.  These were based on the MIPS chip (an early RISC design)
and are really old now, but still useful to look at relative to each other.</html:p><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting-bounds/</fr:uri><fr:display-uri>focs-sorting-bounds</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting-bounds/</fr:route><fr:title
text="How Fast Can We Sort?">How Fast Can We Sort?</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>typically count <html:em>comparisons</html:em> <fr:tex
display="inline"><![CDATA[C(n)]]></fr:tex></html:li>
  <html:li>there are <fr:tex
display="inline"><![CDATA[n!]]></fr:tex> permutations of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements</html:li>
  <html:li>each comparison eliminates <html:em>half</html:em> of the permutations <fr:tex
display="inline"><![CDATA[2^{C(n)}\geq  n!]]></fr:tex></html:li>
  <html:li>therefore <fr:tex
display="inline"><![CDATA[C(n)\geq  \log (n!)\approx  n\log  n-1.44n]]></fr:tex></html:li></html:ul><html:p>The usual measure of efficiency for sorting algorithms is the number of
comparison operations required.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">Mergesort</fr:link> requires only <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>
comparisons to sort an input of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> items.  It is straightforward to prove
that this complexity is the best possible.  There
are <fr:tex
display="inline"><![CDATA[n!]]></fr:tex> permutations of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements and each comparison distinguishes two
permutations.  The lower bound on the number of comparisons, <fr:tex
display="inline"><![CDATA[C(n)]]></fr:tex>, is
obtained by solving <fr:tex
display="inline"><![CDATA[2^{C(n)}\geq  n!]]></fr:tex>; therefore
<fr:tex
display="inline"><![CDATA[C(n)\geq  \log (n!)\approx  n\log  n-1.44n]]></fr:tex>.</html:p><html:p>In order to compare the sorting algorithms, we use the <fr:link
href="http://www.firstpr.com.au/dsp/rand31/p1192-park.pdf"
type="external">following source</fr:link> of
pseudo-random numbers. Never mind how this works: generating
statistically good random numbers is hard.  Much effort has gone into those few
lines of code.</html:p><html:pre><![CDATA[# let nextrandom seed =
    let a = 16807.0 in
    let m = 2147483647.0 in
    let t = a *. seed in
    t -. m *. (floor (t /. m))
val nextrandom : float -> float = <fun>
# let rec randlist (seed, seeds) = function
    | 0 -> (seed, seeds)
    | n -> randlist (nextrandom seed, seed::seeds) (n-1)
val randlist : float * float list -> int -> float * float list = <fun>]]></html:pre><html:p>We can now bind the identifier <html:code>rs</html:code> to a list of 10,000 random numbers.</html:p><html:pre><![CDATA[# let seed, rs = randlist (1.0, []) 10000
val seed : float = 1043618065.
val rs : float list =
  [1484786315.; 925166085.; 1614852353.; 721631166.; 173942219.; 1229443779.;
   789328014.; 570809709.; 1760109362.; 270600523.; 2108528931.; 16480421.;
   519782231.; 162430624.; 372212905.; 1954184989.; 898872741.; 1651521688.;
   1114791388.; 1325968501.; 1469981427.; 465437343.; 1732504088.;
   280054095.; 1924919450.; 1244369648.; 1524535715.; 706293012.;
   1372325856.; 1302473561.; 941382430.; 2137445578.; 1937168414.;
   1852570660.; 495231255.; 1092873378.; 140232191.; 328129841.; 632752255.;
   227857208.; 1616471915.; 719842438.; 1402481130.; 745001020.; 791471334.;
   2131048000.; 312659966.; 1389551813.; 443838892.; 854190041.; 741774068.;
   267473377.; 1372555293.; 1539748349.; 697860888.; 1261546017.; 734770781.;
   1512111397.; 813238415.; 1034499961.; 602256496.; 462191385.; 250718457.;
   246489360.; 295426232.; 468306241.; 877829533.; 1130589227.; 1914364883.;
   1479854970.; 878528585.; 1268712064.; 115837978.; 1803525169.; 689954646.;
   1174020926.; 651968560.; 391152461.; 1776325865.; 2015344107.; 246977673.;
   1381242649.; 1115030853.; 190703911.; 316761032.; 464218769.; 1537522160.;
   1958981931.; 390463588.; 224009597.; 235243732.; 620352731.; 1374109567.;
   832140633.; 675075162.; 1296171190.; 2009054653.; 1534419747.; 145880482.;
   1649432515.; 403989126.; 1112417244.; 1290575192.; 896661113.; 218545469.;
   1002393512.; 2131316096.; 551979127.; 932010335.; 665881436.; 1975412808.;
   639877791.; 1781707137.; 894518191.; 568004958.; 1331430214.; 629489848.;
   183264178.; 162027282.; 464592882.; 93302056.; 1178713033.; 1401486247.;
   1846150129.; 1646978216.; 1104441491.; 111995009.; 66193165.; 2038880392.;
   79340676.; 871801051.; 967550305.; 2067810758.; 1600354198.; 1746626663.;
   1516388116.; 1308870791.; 173082747.; 189881227.; 478010722.; 739707315.;
   255334803.; 164203714.; 1893097038.; 1587694259.; 292950569.; 918323194.;
   41453146.; 1217297445.; 256768724.; 586494122.; 586258194.; 660494391.;
   507554325.; 699716071.; 672895139.; 76065072.; 1594869218.; 1439459639.;
   641123634.; 1650611940.; 177447368.; 301427463.; 525804524.; 553672425.;
   926899509.; 794676486.; 690277940.; 2115070333.; 1062048650.; 1653192448.;
   1808855340.; 126475289.; 1028198214.; 1739565096.; 1515748830.;
   427491435.; 319330584.; 666483848.; 854842154.; 1853528448.; 1975611245.;
   1905343266.; 1229802342.; 1416055428.; 2091603253.; 1068308139.;
   198239748.; 982076370.; 1094563396.; 44402415.; 889814989.; 290736902.;
   417580014.; 1935788352.; 595665917.; 367638848.; 894945148.; 1868608068.;
   317883051.; 941451621.; 1595942893.; 789094274.; 1150772108.; 422742112.;
   1444245279.; 1273601104.; 256005435.; 1742330161.; 1514599036.;
   956344512.; 2113041793.; 293237373.; 1386995194.; 1509339194.; 891946522.;
   1020832915.; 592544922.; 1746311153.; 1471539715.; 143832370.;
   2041568248.; 1039556199.; 1608726047.; 1205124472.; 2123533995.;
   1560620058.; 1837598795.; 1028172251.; 98318742.; 1405510706.;
   1047695837.; 59221314.; 1822176683.; 1096018886.; 1528104537.;
   1270922857.; 812074106.; 291115596.; 795788616.; 638657646.; 2034314619.;
   1527649272.; 156357479.; 1010056202.; 1139413443.; 1110927723.;
   1216083346.; 846825145.; 2100385733.; 315213605.; 1629637749.;
   1139833627.; 895118866.; 296359237.; 1361440746.; 1188627020.;
   1964199872.; 166733080.; 54185744.; 575493576.; 1810324496.; 1765549585.;
   53514233.; 747348448.; 61758907.; 1710119765.; 188311628.; 8827553.;
   67975851.; 1808633248.; 1290488843.; 1264775607.; 1711469075.;
   1537468597.; 706677101.; 518290019.; 190285086.; 157683412.; 985907152.;
   1571668636.; 632570698.; 791081325.; 1773794197.; 1787141077.;
   1727982894.; 794213057.; 633163306.; 682601940.; 1573439414.; 1041956036.;
   1169697582.; 758914445.; 2096291761.; 1502226099.; 1665995955.;
   948048264.; 1596326605.; 1816773893.; ...]]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:uri><fr:display-uri>focs-insertion-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:route><fr:title
text="Insertion Sort">Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:p>An insert operation does <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> comparisons on average.</html:p><html:pre><![CDATA[# let rec ins x = function
    | [] -> [x]
    | y::ys -> if x <= y then x :: y :: ys
               else y :: ins x ys
val ins : 'a -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Insertion sort</html:em> takes <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons on average:</html:p><html:pre><![CDATA[let rec insort = function
    | [] -> []
    | x::xs -> ins x (insort xs)]]></html:pre><html:p>Items from the input are copied one at a time to the output.  Each new item is
inserted into the right place so that the output is always in order.</html:p><html:p>We could easily write <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> versions of these functions, but to no purpose.
Insertion sort is slow because it does <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons (and a lot of list
copying), not because it is recursive.  Its quadratic runtime makes it nearly
useless: it takes 174 seconds for our example while the next-worst figure is
1.4 seconds.</html:p><html:p>Insertion sort is worth considering because it is easy to code and illustrates
the concepts.  Two efficient sorting algorithms, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link> and heapsort, can be
regarded as refinements of insertion sort.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/</fr:uri><fr:display-uri>focs-quicksort-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-idea/</fr:route><fr:title
text="Quicksort: The Idea">Quicksort: The Idea</fr:title></fr:frontmatter><fr:mainmatter><html:p>The Quicksort algorithm has the following flow:</html:p><html:ul><html:li>Choose a <html:em>pivot</html:em> element, <fr:tex
display="inline"><![CDATA[a]]></fr:tex></html:li>
  <html:li>Divide to partition the input into two sublists:
    <html:ul><html:li>those <html:em>at most</html:em> <fr:tex
display="inline"><![CDATA[a]]></fr:tex> in value</html:li>
      <html:li>those <html:em>exceeding</html:em> <fr:tex
display="inline"><![CDATA[a]]></fr:tex></html:li></html:ul></html:li>
  <html:li>Conquer using recursive calls to sort the sublists</html:li>
  <html:li>Combine the sorted lists by appending one to the other</html:li></html:ul><html:p>Quicksort was invented by Sir Anthony Hoare (1934–2026), who in later life worked at Microsoft
Research, Cambridge.  Quicksort works by <html:em>divide and conquer,</html:em> a basic algorithm design
principle.  Quicksort chooses from the input some value <fr:tex
display="inline"><![CDATA[a]]></fr:tex>, called the
<html:em>pivot</html:em>.  It partitions the remaining items into two parts: those <fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>, and
those <fr:tex
display="inline"><![CDATA[>a]]></fr:tex>.  It sorts each part recursively, then puts the smaller part before
the greater.</html:p><html:p>The cleverest feature of Hoare's algorithm was that the partition could be done
<html:em>in place</html:em> by exchanging array elements.  Quicksort was invented before
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link> was well known, and people found it extremely hard to understand.  As
usual, we shall consider a list version based on functional programming.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:uri><fr:display-uri>focs-quicksort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:route><fr:title
text="Quicksort: The Code">Quicksort: The Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quick = function
    | [] -> []
    | [x] -> [x]
    | a::bs ->
        let rec part l r = function
          | [] -> (quick l) @ (a :: quick r)
          | x::xs ->
              if (x <= a) then
                part (x::l) r xs
              else
                part l (x::r) xs
        in
        part [] [] bs
val quick : 'a list -> 'a list = <fun>]]></html:pre><html:p>Our OCaml quicksort copies the items.  It is still pretty fast, and it is much
easier to understand.  It takes roughly 0.74 seconds to sort our list of random
numbers.</html:p><html:p>The function declaration consists of three clauses.  The first handles the
empty list; the second handles singleton lists (those of the form <html:code>[x]</html:code>); the
third handles lists of two or more elements.  Often, lists of length up to five
or so are treated as special cases to boost speed.</html:p><html:p>The locally declared function <html:code>part</html:code> partitions the input using <html:code>a</html:code> as the
pivot.  The arguments <html:code>l</html:code> and <html:code>r</html:code> accumulate items for the left (<fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>) and
right (<fr:tex
display="inline"><![CDATA[>a]]></fr:tex>) parts of the input, respectively.</html:p><html:p>It is not hard to prove that quicksort does <fr:tex
display="inline"><![CDATA[n\log  n]]></fr:tex> comparisons, <html:em>in the average case</html:em>
(see <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">page 94 of Aho</fr:link>).  With random data, the pivot
usually has an average value that divides the input in two approximately equal
parts.  We have the recurrence <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>, which is
<fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.  In our example, it is about 235 times faster than <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insertion
sort</fr:link>.</html:p><html:p>In the worst case, quicksort's running time is quadratic!  An example is when
its input is almost sorted or reverse sorted.  Nearly all of the items end up
in one partition; work is not divided evenly.  We have the recurrence
<fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>, which is <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Randomising the input
makes the worst case highly unlikely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:uri><fr:display-uri>focs-quicksort-append-free</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:route><fr:title
text="Append-Free Quicksort">Append-Free Quicksort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quik = function
    | ([], sorted) -> sorted
    | ([x], sorted) -> x::sorted
    | a::bs, sorted ->
       let rec part = function
         | l, r, [] -> quik (l, a :: quik (r, sorted))
         | l, r, x::xs ->
             if x <= a then
               part (x::l, r, xs)
             else
               part (l, x::r, xs)
       in
       part ([], [], bs)
val quik : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>The list <html:code>sorted</html:code> accumulates the result in the <html:em>combine</html:em> stage of
the quicksort algorithm.  We have again used the standard technique for
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-rev/"
title="Reversing a List in O(n)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/"
display-uri="focs-rev"
type="local">eliminating append</fr:link>.  Calling <html:code>quik(xs, sorted)</html:code> reverses the elements of
<html:code>xs</html:code> and prepends them to the list <html:code>sorted</html:code>.</html:p><html:p>Looking closely at <html:code>part</html:code>, observe that <html:code>quik(r, sorted)</html:code> is
performed first.  Then <html:code>a</html:code> is consed to this sorted list.  Finally,
<html:code>quik</html:code> is called again to sort the elements of <html:code>l</html:code>.</html:p><html:p>The speedup is significant.  An imperative quicksort coded in Pascal (taken
from <fr:link
href="https://algs4.cs.princeton.edu/20sorting/"
type="external">Sedgewick</fr:link>) is just slightly faster than function
<html:code>quik</html:code>.  The near-agreement is surprising because the computational overheads
of lists exceed those of arrays.  In realistic applications, comparisons are
the dominant cost and the overheads matter even less.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge/</fr:uri><fr:display-uri>focs-merge</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge/</fr:route><fr:title
text="Merging Two Lists">Merging Two Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Merge joins two sorted lists.</html:p><html:pre><![CDATA[# let rec merge = function
    | [], ys -> ys
    | xs, [] -> xs
    | x::xs, y::ys ->
        if x <= y then
          x :: merge (xs, y::ys)
        else
          y :: merge (x::xs, ys)
val merge : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>Generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insert</fr:link> to two lists, and does at most <fr:tex
display="inline"><![CDATA[m+n-1]]></fr:tex> comparisons.</html:p><html:p><html:em>Merging</html:em> means combining two sorted lists to form a larger sorted list.
It does at most <fr:tex
display="inline"><![CDATA[m+n]]></fr:tex> comparisons, where <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are the lengths of the
input lists.  If <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are roughly equal then we have a fast way of
constructing sorted lists; if <fr:tex
display="inline"><![CDATA[n=1]]></fr:tex> then merging degenerates to insertion,
doing much work for little gain.</html:p><html:p>Merging is the basis of several sorting algorithms; we look at a
divide-and-conquer one.  Mergesort is seldom found in conventional programming
because it is hard to code for arrays; it works nicely with lists.  It divides
the input (if non-trivial) into two roughly equal parts, sorts them
recursively, then merges them.</html:p><html:p>Function <html:code>merge</html:code> is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>; the recursion is deep.  An iterative
version is of little benefit for the same reasons that apply to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">earlier lecture on Lists</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:uri><fr:display-uri>focs-merge-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:route><fr:title
text="Top-down Merge sort">Top-down Merge sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec tmergesort = function
    | [] -> []
    | [x] -> [x]
    | xs ->
        let k = List.length xs / 2 in
        let l = tmergesort (take k xs) in
        let r = tmergesort (drop k xs) in
        merge (l, r)
val tmergesort : 'a list -> 'a list = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons in worst case</html:p><html:p>Mergesort’s <html:em>divide</html:em> stage divides the input not by choosing a pivot (as
in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>) but by simply counting out half of the elements.  The
<html:em>conquer</html:em> stage again involves recursive calls, and the <html:em>combine</html:em>
stage involves merging.  Function <html:code>tmergesort</html:code> takes roughly 1.4
seconds to sort the list <html:code>rs</html:code>.</html:p><html:p>In the worst case, mergesort does <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons, with the same
recurrence equation as in quicksort’s average case.  Because <fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>take</html:code></fr:link> and
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>drop</html:code></fr:link> divide the input in two equal parts (they differ at most by
one element), we always have <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>.</html:p><html:p>Quicksort is nearly 3 times as fast in the example.  But it risks a
quadratic worst case!  Merge sort is safe but slow.  So which algorithm is
best?</html:p><html:p>We have seen a <html:em>top-down</html:em> mergesort.  <html:em>Bottom-up</html:em> algorithms also
exist.  They start with a list of one-element lists and repeatedly merge
adjacent lists until only one is left.  A refinement, which exploits any
initial order among the input, is to start with a list of increasing or
decreasing runs of input items.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting-summary/</fr:uri><fr:display-uri>focs-sorting-summary</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting-summary/</fr:route><fr:title
text="Summary of Sorting Algorithms">Summary of Sorting Algorithms</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Optimal is <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">Insertion sort</fr:link>: simple to code; too slow (quadratic) [174 secs]</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort/"
title="Quicksort: The Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/"
display-uri="focs-quicksort"
type="local">Quicksort</fr:link>: fast on average; quadratic in worst case [0.53 secs]</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">Mergesort</fr:link>: optimal in theory; often slower than quicksort [1.4 secs]</html:li>
  <html:li><html:em>Match the algorithm to the application</html:em></html:li></html:ul><html:p>Quicksort’s worst case cannot be ignored.  For large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, a complexity of
<fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> is catastrophic.  Mergesort has an <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> worst case running
time, which is optimal, but it is typically slower than quicksort for random
data.</html:p><html:p>Non-comparison sorting deserves mentioning.  We can sort a large number of
small integers using their radix representation in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time.  This result
does not contradict the comparison-counting argument because comparisons are
not used at all.  Linear time is achievable only if the greatest integer is
fixed in advance; as <fr:tex
display="inline"><![CDATA[n]]></fr:tex> goes to infinity, increasingly many of the items
are the same.  It is a simple special case.</html:p><html:p>Many other sorting algorithms exist. A few are outlined in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">the exercises</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/</fr:uri><fr:display-uri>focs-ex-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:uri><fr:display-uri>focs-ex-5-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:route><fr:title
text="Complexity of selection sort">Complexity of selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (selection sort) consists of looking at the elements to be sorted,
identifying and removing a minimal element, which is placed at the head of the result. The tail is
obtained by recursively sorting the remaining elements. State, with justification, the time
complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:uri><fr:display-uri>focs-ex-5-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:route><fr:title
text="Implementing selection sort">Implementing selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement selection sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:uri><fr:display-uri>focs-ex-5-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:route><fr:title
text="Complexity of bubble sort">Complexity of bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (bubble sort) consists of looking at adjacent pairs of elements,
exchanging them if they are out of order and repeating this process until no more exchanges are
possible. State, with justification, the time complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:uri><fr:display-uri>focs-ex-5-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:route><fr:title
text="Implementing bubble sort">Implementing bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement bubble sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-datatypes/</fr:uri><fr:display-uri>focs-datatypes</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-datatypes/</fr:route><fr:title
text="Datatypes and Trees">Datatypes and Trees</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-enumeration/</fr:uri><fr:display-uri>focs-enumeration</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-enumeration/</fr:route><fr:title
text="An Enumeration Type">An Enumeration Type</fr:title></fr:frontmatter><fr:mainmatter><html:p>We will now learn how to define more expressive types than the
basic ones supplied with the core OCaml language.</html:p><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike
               | Car
               | Lorry
type vehicle = Bike | Motorbike | Car | Lorry]]></html:pre><html:ul><html:li>We have declared a <html:em>new type</html:em> named <html:code>vehicle</html:code>.</html:li>
  <html:li><fr:tex
display="inline"><![CDATA[\ldots ]]></fr:tex> along with four new constants.</html:li>
  <html:li>They are the <html:em>constructors</html:em> of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link>.</html:li></html:ul><html:p>The <html:code>type</html:code> declaration adds a new type to our OCaml session.  Type
<html:code>vehicle</html:code> is as good as any built-in type and even admits
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link> (as we used with the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">built-in list types</fr:link> earlier).
The four new identifiers of type <html:code>vehicle</html:code> are called <html:em>constructors</html:em>.</html:p><html:p>We could represent the various vehicles by the numbers 0–3.  However, the code would be
hard to read and even harder to maintain.  Consider adding <html:code>Tricycle</html:code>
as a new vehicle. If we wanted to add it before <html:code>Bike</html:code>, then all the
numbers would have to be changed.  Using <html:code>type</html:code>, such additions are
trivial and the compiler can (at least sometimes) warn us when it encounters a
function declaration that doesn’t yet have a case for <html:code>Tricycle</html:code>.</html:p><html:p>Representing vehicles by strings like <html:code>"Bike"</html:code>, <html:code>"Car"</html:code>, etc.,
is also bad.  Comparing string values is slow and the compiler
can’t warn us of misspellings like <html:code>"MOtorbike"</html:code>: they will make our
code fail.</html:p><html:p>Most programming languages allow the declaration of types like
<html:code>vehicle</html:code>.  Because they consist of a series of identifiers, they are
called <html:em>enumeration types</html:em>.  Other common examples are days of the week
or colours.  The compiler chooses the integers for us; type-checking prevents
us from confusing <html:code>Bike</html:code> with <html:code>Red</html:code> or <html:code>Sunday</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-vehicles/</fr:uri><fr:display-uri>focs-vehicles</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-vehicles/</fr:route><fr:title
text="Declaring a Function on Vehicles">Declaring a Function on Vehicles</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let wheels = function
  | Bike -> 2
  | Motorbike -> 2
  | Car -> 4
  | Lorry -> 18
val wheels : vehicle -> int = <fun>]]></html:pre><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">Datatype constructors</fr:link> can be used in patterns.</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">Pattern-matching</fr:link> is fast, even complicated nested patterns.</html:li>
  <html:li>Notice the type of the argument is <html:code>vehicle</html:code>, which we defined earlier.</html:li></html:ul><html:p>The beauty of datatype declarations is that the new types behave as if they
were built into OCaml. Type-checking catches common errors, such as mixing up
different datatypes in a function like <html:code>wheels</html:code>, as well as missing
and redundant patterns.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-constructors-args/</fr:uri><fr:display-uri>focs-constructors-args</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-constructors-args/</fr:route><fr:title
text="A Datatype whose Constructors have Arguments">A Datatype whose Constructors have Arguments</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike of int
               | Car       of bool
               | Lorry     of int
type vehicle = Bike | Motorbike of int | Car of bool | Lorry of int]]></html:pre><html:ul><html:li>Constructors with arguments (like <html:code>Lorry</html:code>) are <html:em>distinct values</html:em>. (So <html:code>Car true</html:code> is distinct from <html:code>Car false</html:code>).</html:li>
  <html:li>Different kinds of <html:code>vehicle</html:code> can belong to one list: <html:code>[Bike; Car true; Motorbike 450]</html:code></html:li></html:ul><html:p>OCaml generalises the notion of enumeration type to allow data to be associated
with each constructor.  The constructor <html:code>Bike</html:code> is a vehicle all by itself, but
the other three constructors create vehicles from arguments.</html:p><html:p>Since we might find it hard to remember what the various <html:code>int</html:code> and
<html:code>bool</html:code> components are for, it is wise to include <html:em>comments</html:em> in
complex declarations.  In OCaml, comments are enclosed in the brackets
<html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>. Programmers should comment their code to explain
design decisions and key features of the algorithms (sometimes by citing a
reference work).</html:p><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike of int  (* engine size in CCs *)
               | Car       of bool (* true if a Reliant Robin *)
               | Lorry     of int  (* number of wheels *)
type vehicle = Bike | Motorbike of int | Car of bool | Lorry of int]]></html:pre><html:p>The list <html:code>[Bike; Car true; Motorbike 450]</html:code> represents a bicycle, a Reliant Robin and a large
motorbike.  It can be almost seen as a mixed-type list containing integers and
booleans.  It is actually a list of vehicles; datatypes lessen the impact of
the restriction that all list elements must have the same type.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-wheels/</fr:uri><fr:display-uri>focs-wheels</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-wheels/</fr:route><fr:title
text="A Finer Wheel Computation">A Finer Wheel Computation</fr:title></fr:frontmatter><fr:mainmatter><html:p>We now define a <html:code>wheels</html:code> function to calculate the number of wheels
in any <html:code>vehicle</html:code>. This requires <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matching</fr:link> to retrieve the
constructors and their associated arguments, around which we build the
logic:</html:p><html:pre><![CDATA[# let wheels = function
  | Bike -> 2
  | Motorbike _ -> 2
  | Car robin -> if robin then 3 else 4
  | Lorry w -> w
val wheels : vehicle -> int = <fun>]]></html:pre><html:p>This function consists of four clauses:</html:p><html:ul><html:li>A Bike has two wheels.  This is a constant result.</html:li>
  <html:li>A Motorbike has two wheels. The <html:code>_</html:code> signifies a "wildcard" pattern match that we discard, since the engine size of the bike is not relevant to the number of wheels.</html:li>
  <html:li>A Reliant Robin has three wheels; all other cars have four. We bind <html:code>robin</html:code> to the <html:code>bool</html:code> argument and then use it in the right hand side of the pattern match, much like a <html:code>let</html:code> binding in normal code.</html:li>
  <html:li>A Lorry has the number of wheels stored with its constructor, and we simply return that.</html:li></html:ul><html:p>There is no overlap between the <html:code>Motorbike</html:code> and <html:code>Lorry</html:code> cases.  Although
<html:code>Motorbike</html:code> and <html:code>Lorry</html:code> both hold an integer, OCaml takes the
constructor into account and keeps any <html:code>Motorbike</html:code> distinct from any <html:code>Lorry</html:code>.</html:p><html:p>Vehicles are one example of a concept consisting of several varieties with
distinct features.  Most programming languages can represent such concepts
using something analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatypes</fr:link>.  (They are sometimes called
<html:em>union types</html:em> or <html:em>variant records</html:em> whose <html:em>tag fields</html:em> play the
role of the constructors.)</html:p><html:p>A pattern may be built from the constructors of several datatypes, including
lists. A pattern may also contain integer and string constants. There is no
limit to the size of patterns or the number of clauses in a function
declaration. OCaml performs pattern-matching <fr:link
href="https://dl.acm.org/citation.cfm?id=507641"
type="external">efficiently</fr:link>
(you do not need to understand the details of how it optimises pattern-matching at this stage).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/</fr:uri><fr:display-uri>focs-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-exceptions/</fr:route><fr:title
text="Error Handling: Exceptions">Error Handling: Exceptions</fr:title></fr:frontmatter><fr:mainmatter><html:p>During a computation, what happens if something goes <html:em>wrong?</html:em></html:p><html:ul><html:li>Division by zero</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">Pattern matching</fr:link> failure</html:li></html:ul><html:p><html:em>Exception-handling</html:em> lets us recover gracefully.</html:p><html:ul><html:li>Raising an exception abandons the current computation.</html:li>
  <html:li>Handling the exception attempts an alternative computation.</html:li>
  <html:li>The raising and handling can be far apart in the code.</html:li>
  <html:li>Errors of <html:em>different sorts</html:em> can be handled separately.</html:li></html:ul><html:p>Exceptions are necessary because it is not always possible to tell in advance
whether or not a search will lead to a dead end or whether a numerical
calculation will encounter errors such as overflow or divide by zero. Rather
than just crashing, programs should check whether things have gone wrong, and
perhaps attempt an alternative computation (perhaps using a different algorithm
or higher precision). A number of modern languages provide exception handling.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/</fr:uri><fr:display-uri>focs-ocaml-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/</fr:route><fr:title
text="Exceptions in OCaml">Exceptions in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Failure
exception Failure
# exception NoChange of int
exception NoChange of int
# raise Failure
Exception: Failure.]]></html:pre><html:p>Each <html:code>exception</html:code> declaration introduces a distinct sort of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link>, which can
be handled separately from others. If <fr:tex
display="inline"><![CDATA[E]]></fr:tex> raises an exception, then its
evaluation has failed; <html:em>handling</html:em> an exception means evaluating another
expression and returning its value instead. One exception handler can specify
separate expressions for different sorts of exceptions.</html:p><html:p>Exception names are <html:em>constructors</html:em> of the special <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> <html:code>exn</html:code>.  This is a
peculiarity of OCaml that lets exception-handlers use <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>. Note that
exception <html:code>Failure</html:code> is just an error indication, while <html:code>NoChange n</html:code> carries
further information: the integer <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# try
    print_endline "pre exception";
    raise (NoChange 1);
    print_endline "post exception";
  with
    | NoChange _ ->
        print_endline "handled a NoChange exception"
Line 3, characters 5-23:
Warning 21 [nonreturning-statement]: this statement never returns (or has an unsound type.)
pre exception
handled a NoChange exception

- : unit = ()]]></html:pre><html:p>The effect of <html:code>raise &lt;expr&gt;</html:code> is to jump to the most recently-encountered
handler that matches <html:code>&lt;expr&gt;</html:code>.  The matching handler can only be found
<html:em>dynamically</html:em> (during execution); contrast with how OCaml associates occurrences
of identifiers with their matching declarations, which does not require running
the program.  A handler is introduced via the <html:code>try</html:code> keyword, which executes
the subexpression and dispatches any exceptions encountered to the corresponding
pattern match for exceptions defined in the <html:code>with</html:code> block.</html:p><html:p>This is also the first time that we have encountered the <html:code>unit</html:code> type. This
represents a type that has no values, and is used to indicate that a block
has no meaningful return value.  We will come back to this when learning more
about <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural/"
title="Elements of Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/"
display-uri="focs-procedural"
type="local"><html:em>imperative</html:em> programming</fr:link> later on.  For now, it is sufficient to understand
that <html:code>print_endline</html:code> will print out the argument to the console output, and return
a <html:code>unit</html:code> type.  The semicolon at the end of the expression is a convenient way to
execute sequential statements that return the <html:code>unit</html:code> type.</html:p><html:p>One criticism of OCaml’s exceptions is that—unlike the Java language—nothing
in a function declaration indicates which exceptions it might raise. One
alternative to exceptions is to instead return a value of datatype <html:code>option</html:code>.</html:p><html:pre><![CDATA[# let x = Some 1
val x : int option = Some 1
# let y = None
val y : 'a option = None
# type 'a option = None | Some of 'a
type 'a option = None | Some of 'a]]></html:pre><html:p><html:code>None</html:code> signifies an error, while <html:code>Some x</html:code> returns the solution <fr:tex
display="inline"><![CDATA[x]]></fr:tex>.  This
approach looks clean, but the drawback is that many places in the code would
have to check for <html:code>None</html:code>.  Despite this, there is a builtin <html:code>option</html:code> type
in OCaml as it is so useful. We will see in later lectures how to define our
own version of <html:code>option</html:code> using polymorphic datatype definitions.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:uri><fr:display-uri>focs-change-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:route><fr:title
text="Making Change with Exceptions">Making Change with Exceptions</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Change
  let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise Change
    | c::till, amt -> if amt < 0 then raise Change
                      else try c :: change (c::till) (amt - c)
                           with Change -> change till amt
exception Change
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>In the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">Lists lectures</fr:link>, we considered the problem of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.  The greedy
algorithm presented there could not express “6 using 5 and 2” because it always
took the largest coin.  Returning <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">the list of all possible solutions</fr:link> avoids
that problem rather expensively: we only need one solution.</html:p><html:p>Using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>, we can code a <html:em>backtracking</html:em> algorithm: one that can undo
past decisions if it comes to a dead end.  The exception <html:code>Change</html:code> is raised if
we run out of coins (with a non-zero amount) or if the amount goes negative.
We always try the largest coin, but enclose the recursive call in an exception
handler, which undoes the choice if it goes wrong.</html:p><html:p>Carefully observe how exceptions interact with <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  The exception
handler always undoes the <html:em>most recent</html:em> choice, leaving others possibly to
be undone later.  If making change really is impossible, then eventually
<html:code>exception Change</html:code> will be raised with no handler to catch it, and it
will be reported at top level.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-trace/</fr:uri><fr:display-uri>focs-change-trace</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-trace/</fr:route><fr:title
text="Making Change: A Trace">Making Change: A Trace</fr:title></fr:frontmatter><fr:mainmatter><html:p>Here is the full execution. Observe how the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception handlers</fr:link> nest and how
they drop away once the given expression has returned a value.</html:p><fr:tex
display="block"><![CDATA[\begin{aligned}
\text{change [5; 2] 6}
  \Rightarrow &\; \text{try 5::change [5; 2] 1}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{try 5::(try 5::change [5; 2] (-4)}\\
              &\; \text{with Change -> change [2] 1)}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{5::(change [2] 1)}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{try 5::(try 2::change [2] (-1)}\\
              &\; \text{with Change -> change [] 1)}\\
              &\; \text{with Change -> change [2] 6} \\
  \Rightarrow &\; \text{try 5::(change [] 1)}\\
              &\; \text{with Change -> change [2] 6} \\
  \Rightarrow &\; \text{change [2] 6} \\
  \Rightarrow &\; \text{try 2::change [2] 4}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::change [2] 2}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::(try 2::change [2] 0 }\\
              &\; \text{with Change -> change [] 2)}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::[2]}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::[2; 2]}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{[2; 2; 2]}
\end{aligned}]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:uri><fr:display-uri>focs-binary-trees</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:route><fr:title
text="Binary Trees, a Recursive Datatype">Binary Trees, a Recursive Datatype</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a tree =
    Lf
  | Br of 'a * 'a tree * 'a tree
type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmihauytafmmc5evdkkihzsaxper2thnogxohktuubaoxtrpw24qazu.svg" /></html:figure><html:pre><![CDATA[# Br(1, Br(2, Br(4, Lf, Lf),
              Br(5, Lf, Lf)),
        Br(3, Lf, Lf))
- : int tree = Br (1, Br (2, Br (4, Lf, Lf), Br (5, Lf, Lf)), Br (3, Lf, Lf))]]></html:pre><html:p>A data structure with multiple branching is called a “tree”.  Trees can
represent mathematical expressions, logical formulae, computer programs, the
phrase structure of English sentences, etc.</html:p><html:p><html:em>Binary trees</html:em> are nearly as fundamental as lists.  They can provide
efficient storage and retrieval of information.  In a binary tree, each node
is empty (<fr:tex
display="inline"><![CDATA[Lf]]></fr:tex>), or is a branch (<fr:tex
display="inline"><![CDATA[Br]]></fr:tex>) with a label and two subtrees.</html:p><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">OCaml lists</fr:link> are a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> and could be declared as follows:</html:p><html:pre><![CDATA[# type 'a mylist =
  | Nil
  | Cons of 'a * 'a mylist
type 'a mylist = Nil | Cons of 'a * 'a mylist]]></html:pre><html:p>We could even declare <html:code>::</html:code> as an infix constructor.  The only
thing we could not define is the <html:code>[...]</html:code> notation, which is
part of the OCaml grammar (although there does exist a mechanism
to use a <html:em>similar</html:em> syntax for custom indexed datatypes).</html:p><html:p>A <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> type does not have to be <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.
For example, here is a simple datatype of tree shapes with no attached data
that is recursive but not polymorphic.</html:p><html:pre><![CDATA[# type shape =
  | Null
  | Join of shape * shape
type shape = Null | Join of shape * shape]]></html:pre><html:p>The datatype <html:code>'a option</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">mentioned above</fr:link>) is the opposite – it is
polymorphic, but not recursive.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-properties/</fr:uri><fr:display-uri>focs-tree-properties</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-properties/</fr:route><fr:title
text="Basic Properties of Binary Trees">Basic Properties of Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec count = function
  | Lf -> 0  (* number of branch nodes *)
  | Br (v, t1, t2) -> 1 + count t1 + count t2
val count : 'a tree -> int = <fun>
# let rec depth = function
  | Lf -> 0  (* length of longest path *)
  | Br (v, t1, t2) -> 1 + max (depth t1) (depth t2)
val depth : 'a tree -> int = <fun>]]></html:pre><html:p>The invariant <fr:tex
display="inline"><![CDATA[\texttt {count}(t)\le  2^{\texttt {depth}(t)} - 1]]></fr:tex> holds in the functions above.</html:p><html:p>Functions on trees are expressed recursively using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.  Both
functions above are analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-length/"
title="Efficiently Computing the Length of a List"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/"
display-uri="focs-length"
type="local"><fr:tex
display="inline"><![CDATA[\texttt {length}]]></fr:tex> on lists</fr:link>.  Here is a third
measure of a tree’s size:</html:p><html:pre><![CDATA[# let rec leaves = function
  | Lf -> 1
  | Br (v, t1, t2) -> leaves t1 + leaves t2
val leaves : 'a tree -> int = <fun>]]></html:pre><html:p>This function is redundant because of a basic fact about trees, which can be
proved by induction: for every tree <fr:tex
display="inline"><![CDATA[t]]></fr:tex>, we have <fr:tex
display="inline"><![CDATA[\texttt {leaves}(t) =
\texttt {count}(t)+1]]></fr:tex>.  The invariant <fr:tex
display="inline"><![CDATA[\texttt {count}(t)\le  2^{\texttt {depth}(t)} - 1]]></fr:tex> stated above also has an elementary
proof by induction.</html:p><html:p>A tree of depth 20 can store <fr:tex
display="inline"><![CDATA[2^{20}-1]]></fr:tex> or approximately one million elements.
The access paths to these elements are short, particularly when compared with
a million-element list!</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/</fr:uri><fr:display-uri>focs-ex-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:uri><fr:display-uri>focs-ex-6-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:route><fr:title
text="Days of the week type">Days of the week type</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for the days of the week. Comment on the practicality of such
a type in a calendar application.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:uri><fr:display-uri>focs-ex-6-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:route><fr:title
text="Summing tree labels">Summing tree labels</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write an OCaml function taking a binary tree labelled with integers and returning their sum.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:uri><fr:display-uri>focs-ex-6-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:route><fr:title
text="What ftree builds">What ftree builds</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">definition of <html:code>'a tree</html:code></fr:link> from before:</html:p><html:pre><![CDATA[type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:p>Examine the following function declaration. What does <html:code>ftree (1, n)</html:code> accomplish?</html:p><html:pre><![CDATA[let rec ftree k n =
  if n = 0 then Lf
  else Br (k, ftree (2 * k) (n - 1), ftree (2 * k + 1) (n - 1))]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:uri><fr:display-uri>focs-ex-6-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:route><fr:title
text="A type for arithmetic expressions">A type for arithmetic expressions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for arithmetic expressions that have the following
possibilities: floating-point numbers, variables (represented by strings), or expressions of the form <fr:tex
display="inline"><![CDATA[-E]]></fr:tex>,
<fr:tex
display="inline"><![CDATA[E+E]]></fr:tex>, <fr:tex
display="inline"><![CDATA[E\times  E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:uri><fr:display-uri>focs-ex-6-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:route><fr:title
text="Evaluating expressions with exceptions">Evaluating expressions with exceptions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, write a function that evaluates an expression. If the expression
contains any variables, your function should raise an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> indicating the variable name.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionaries/</fr:uri><fr:display-uri>focs-dictionaries</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dictionaries/</fr:route><fr:title
text="Dictionaries and Functional Arrays">Dictionaries and Functional Arrays</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:uri><fr:display-uri>focs-dictionary-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:route><fr:title
text="Dictionaries">Dictionaries</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>lookup: find an item in the dictionary</html:li>
<html:li>update (insert): replace (store) an item in the dictionary</html:li>
<html:li>delete: remove an item from the dictionary</html:li>
<html:li>empty: the null dictionary</html:li>
<html:li>Missing: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> for errors in <html:code>lookup</html:code> and <html:code>delete</html:code></html:li></html:ul><html:p>Ideally, an <html:em>abstract type</html:em> should provide these operations and hide the internal data structures.</html:p><html:p>A dictionary attaches values to identifiers, called “keys”.  Before choosing
the internal representation for a data structure, you need to specify the full
set of operations. In fact, here we only consider <html:code>update</html:code> (associating a
value with an identifier) and <html:code>lookup</html:code> (retrieving such a value). Deletion
is more difficult and would limit our choices. Some applications may need
additional operations, such as <html:code>merge</html:code> (combining two dictionaries). We
shall see that update can be done efficiently in a functional style, without
excessive copying.</html:p><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent dictionaries. Abstract
types can be declared in any modern programming language. Java’s <html:em>objects</html:em>
serve this role, as do OCaml’s modules. This course does not cover modules, and we
simply declare the dictionary operations individually.</html:p><html:p>An <html:em>association list</html:em> (a list of pairs) is the simplest dictionary representation.
Lookup is by <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link>, and therefore slow: <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>. Association lists are
only usable if there are few keys in use. However, they are general in that the
keys do not need a concept of ordering, only equality.</html:p><html:pre><![CDATA[# exception Missing
exception Missing
# let rec lookup a = function
  | [] -> raise Missing
  | (x, y) :: pairs ->
      if a = x then y
      else lookup a pairs
val lookup : 'a -> ('a * 'b) list -> 'b = <fun>
# let update (l, b, y) = (b, y) :: l
val update : ('a * 'b) list * 'a * 'b -> ('a * 'b) list = <fun>]]></html:pre><html:p>To enter a new <html:code>(key, value)</html:code> pair, simply “cons” it to the list with <html:code>update</html:code>.
This takes constant time, which is the best we could hope for.  But the space
requirement is huge: linear in the number of updates, not in the number of
distinct keys. Obsolete entries are never deleted: that would require first
finding them, increasing the update time from <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/</fr:uri><fr:display-uri>focs-bst</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst/</fr:route><fr:title
text="Binary Search Trees">Binary Search Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>dictionary</html:em> associates <html:em>values</html:em> (here, numbers) with <html:em>keys</html:em>.</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifkdrvs6ut5buyf724655gdcinx637uevqiaejsmb2jgu36gaf4wq.svg" /></html:figure><html:p>Binary search trees are an important application of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>.  They work
for keys that have a total ordering, such as strings.  Each branch of the tree
carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree holds smaller keys; the right
subtree holds greater keys.  If the tree remains reasonably balanced, then
update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  These times
hold in the average case; given random data, the tree is likely to remain
balanced.</html:p><html:p>At a given node, all keys in the left subtree are smaller (or equal) while all
trees in the right subtree are greater.</html:p><html:p>An unbalanced tree has a linear access time in the worst case.  Examples
include building a tree by repeated insertions of elements in increasing or
decreasing order; there is a close resemblance to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>.  Building a binary
search tree, then converting it to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">inorder</fr:link>, yields a sorting algorithm called
<html:em>treesort</html:em>.</html:p><html:p>Self-balancing trees, such as Red-Black trees, attain <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> in the worst
case.  They are complicated to implement.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:uri><fr:display-uri>focs-bst-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:route><fr:title
text="Lookup: Seeks Left or Right">Lookup: Seeks Left or Right</fr:title><fr:meta
name="ocaml-deps">focs-binary-trees</fr:meta></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Missing of string
exception Missing of string
# let rec lookup b = function
  | Br ((a, x), t1, t2) ->
      if b < a then
        lookup b t1
      else if a < b then
        lookup b t2
      else
        x
  | Lf -> raise (Missing b)
val lookup : string -> (string * 'a) tree -> 'a = <fun>]]></html:pre><html:p>This has guaranteed <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> access time <html:em>if</html:em> the tree is balanced!</html:p><html:p>Lookup in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
title="Binary search tree"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
display-uri="focs-def-binary-search-tree"
type="local">binary search tree</fr:link> goes to the left subtree if the desired
key is smaller than the current one and to the right if it is greater.
It raises <html:code>Missing</html:code> if it encounters an empty tree.</html:p><html:p>Since an ordering is involved, we have to declare the functions for a specific
type, here <html:code>string</html:code>.  Now <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Missing</html:code> mentions that type: if lookup
fails, the exception returns the missing key.  The exception could be
eliminated using type <html:code>option</html:code> of our earlier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-datatypes/"
title="Datatypes and Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-datatypes/"
display-uri="focs-datatypes"
type="local">Datatypes lecture</fr:link>, using the
constructor <html:code>None</html:code> for failure.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:uri><fr:display-uri>focs-bst-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:route><fr:title
text="Update">Update</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update k v = function
  | Lf -> Br ((k, v), Lf, Lf)
  | Br ((a, x), t1, t2) ->
      if k < a then
        Br ((a, x), update k v t1, t2)
      else if a < k then
        Br ((a, x), t1, update k v t2)
      else (* a = k *)
        Br ((a, v), t1, t2)
val update : 'a -> 'b -> ('a * 'b) tree -> ('a * 'b) tree = <fun>]]></html:pre><html:p>This is also <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> as it copies the path only, and <html:em>not whole subtrees!</html:em></html:p><html:p>If you are familiar with the usual update operation for this sort of tree, you
may wonder whether it can be implemented in OCaml, where there is no direct way to
replace part of a data structure by something else.</html:p><html:p>The update operation is a nice piece of functional programming.  It searches
in the same manner as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
title="Lookup: Seeks Left or Right"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
display-uri="focs-bst-lookup"
type="local"><html:code>lookup</html:code></fr:link>, but the recursive calls reconstruct a
new tree around the result of the update.  One subtree is updated and the
other left unchanged.  The internal representation of trees ensures that
unchanged parts of the tree are not copied, but <html:em>shared</html:em>.
Therefore, update copies only the path from the root to the new
node.  Its time and space requirements, for a reasonably balanced tree, are
both <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.</html:p><html:p>The comparison between <fr:tex
display="inline"><![CDATA[b]]></fr:tex> and <fr:tex
display="inline"><![CDATA[a]]></fr:tex> allows three cases:</html:p><html:ul><html:li>smaller: update the left subtree; share the right</html:li>
<html:li>greater: update the right subtree; share the left</html:li>
<html:li>equal: update the label and share both subtrees</html:li></html:ul><html:p>Note: in the function definition, <html:code>(* a = k *)</html:code> is a comment.  Comments
in OCaml are enclosed in the brackets <html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:uri><fr:display-uri>focs-tree-traversal</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:route><fr:title
text="Aside: Traversing Trees (3 Methods)">Aside: Traversing Trees (3 Methods)</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec preorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      [v] @ preorder t1 @ preorder t2
val preorder : 'a tree -> 'a list = <fun>
# let rec inorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      inorder t1 @ [v] @ inorder t2
val inorder : 'a tree -> 'a list = <fun>
# let rec postorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      postorder t1 @ postorder t2 @ [v]
val postorder : 'a tree -> 'a list = <fun>]]></html:pre><html:p><html:em>Tree traversal</html:em> means examining each node of a tree in some order.  <fr:link
href="https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming"
type="external">D. E.
Knuth</fr:link> has
identified three forms of tree traversal: preorder, inorder and
postorder.  We can code these “visiting orders” as functions
that convert trees into lists of labels.  Algorithms based on these notions
typically perform some action at each node; the functions above simply copy
the nodes into lists.  Consider the tree:</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmic3wbal56lpqlso6xcqsl6jfrutwygavrn3xds7c6ieywfjr7qdhm.svg" /></html:figure><html:ul><html:li><html:code>preorder</html:code> visits the label first (“Polish notation”), yielding <html:code>ABDECFG</html:code></html:li>
<html:li><html:code>inorder</html:code> visits the label midway, yielding <html:code>DBEAFCG</html:code></html:li>
<html:li><html:code>postorder</html:code> visits the label last (“Reverse Polish”), yielding <html:code>DEBFGCA</html:code>. You might be familiar with this concept if you own an ancient RPN calculator!</html:li></html:ul><html:p>What is the use of <html:code>inorder</html:code>? Consider applying it to a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>: the
result is a sorted list of pairs. We could use this, for example, to merge two
binary search trees. It is not difficult to transform a sorted list of pairs
into a binary search tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:uri><fr:display-uri>focs-tree-traversal-efficient</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:route><fr:title
text="Efficiently Traversing Trees">Efficiently Traversing Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>Unfortunately, the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">traversal functions</fr:link> are quadratic in the
worst case: the appends in the recursive calls are inefficient.  To correct
that problem, we (as usual) add an accumulating argument.  Observe how
each function constructs its result list and compare with how appends were
eliminated from <html:code>quicksort</html:code> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">Sorting lecture</fr:link>.</html:p><html:pre><![CDATA[# let rec preord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      v :: preord (t1, preord (t2, vs))
val preord : 'a tree * 'a list -> 'a list = <fun>
# let rec inord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      inord (t1, v::inord (t2, vs))
val inord : 'a tree * 'a list -> 'a list = <fun>
# let rec postord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      postord (t1, postord (t2, v::vs))
val postord : 'a tree * 'a list -> 'a list = <fun>]]></html:pre><html:p>One can prove equations relating each of these functions to its counterpart on
the previous section.  For example:</html:p><fr:tex
display="block"><![CDATA[\texttt {inord}(t, vs) = \texttt {inorder}(t) @ vs]]></fr:tex><html:p>These three types of tree traversal are related in that all are depth-first.
They each traverse the left subtree in full before traversing the right
subtree.  Breadth-first search (from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queues/"
title="Queues and Search Strategies"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queues/"
display-uri="focs-queues"
type="local">Queues lecture</fr:link>) is another
possibility.  That involves going through the levels of a tree one at a time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-arrays/</fr:uri><fr:display-uri>focs-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-arrays/</fr:route><fr:title
text="Arrays">Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>A conventional array is an indexed storage area.
  <html:ul><html:li>It is updated <html:em>in place</html:em> by the command <html:code>a.(k) &lt;- x</html:code></html:li>
  <html:li>The concept is inherently <html:em>imperative</html:em>.</html:li></html:ul></html:li>
<html:li>A <html:em>functional array</html:em> is a finite map from integers to data.
  <html:ul><html:li>Updating implies <html:em>copying</html:em> to return <html:code>update(A, k, x)</html:code></html:li>
  <html:li>The new array equals <html:code>A</html:code> except that <html:code>A.(k) = x</html:code>.</html:li></html:ul></html:li>
<html:li>Can we do updates efficiently?</html:li></html:ul><html:p>The elements of a list can only be reached by counting from the front.
Elements of a tree are reached by following a path from the root.  An
<html:em>array</html:em> hides such structural matters; its elements are uniformly
designated by number.  Immediate access to arbitrary parts of a data structure
is called <html:em>random access</html:em>.</html:p><html:p>Arrays are the dominant data structure in conventional programming languages.
The ingenious use of arrays is the key to many of the great classical
algorithms, such as Hoare’s original <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link> (the partition step) and
Warshall’s transitive-closure algorithm.</html:p><html:p>The drawback is that subscripting is a chief cause of programmer error.  That
is why arrays play little role in this introductory course.</html:p><html:p>Functional arrays are described below in order to illustrate another way of
using trees to organise data.  Here is a summary of basic dictionary data
structures in order of decreasing generality and increasing efficiency:</html:p><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link>: Most general, needing only equality on keys, but inefficient: linear time.</html:li>
<html:li>Binary search: Needs an ordering on keys.  Logarithmic access time in the average case, but our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link> are linear in the worst case.</html:li>
<html:li>Array subscripting: Least general, requiring keys to be integers, but even worst-case time is logarithmic.</html:li></html:ul></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:uri><fr:display-uri>focs-functional-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:route><fr:title
text="Functional Arrays as Binary Trees">Functional Arrays as Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>The path to element <fr:tex
display="inline"><![CDATA[i]]></fr:tex> follows the <html:em>binary code</html:em> for <fr:tex
display="inline"><![CDATA[i]]></fr:tex> (its “subscript”).</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifetc2v73r7qxnzo6bthiblab2tezbaqvmovq7e4q6vgdl5ewr3wi.svg" /></html:figure><html:p>This simple representation (credited to W. Braun) ensures that the tree is
balanced.  Complexity of access is always <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>, which is optimal.  For
actual running time, access to conventional arrays is much faster: it requires
only a few hardware instructions.  Array access is often taken to be <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>,
which (as always) presumes that hardware limits are never exceeded.</html:p><html:p>The lower bound for array subscripts (or “indices”) is one.  The upper bound starts at zero
(which signifies the empty array) and can grow without limit.  Inspection of
the diagram above should make it clear that these trees are always balanced:
the left subtree can have at most one node more than the right subtree,
recursively all the way down.  (This assumes that the array is defined for
subscripts <fr:tex
display="inline"><![CDATA[1\ldots  n]]></fr:tex> with no gaps; an array defined only for odd numbers, for
example, would obviously be unbalanced.)</html:p><html:p>The numbers in the diagram above are not the labels of branch nodes, but
indicate the positions of array elements. For example, the label corresponding
to <fr:tex
display="inline"><![CDATA[A[2]]]></fr:tex> is at the position shown. The nodes of a functional array are
labelled with the data we want to store, not with these integers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:uri><fr:display-uri>focs-funarray-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:route><fr:title
text="The Lookup Function">The Lookup Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Subscript
  let rec sub = function
  | Lf, _ -> raise Subscript  (* Not found *)
  | Br (v, t1, t2), k ->
      if k = 1 then v
      else if k mod 2 = 0 then
        sub (t1, k / 2)
      else
        sub (t2, k / 2)
exception Subscript
val sub : 'a tree * int -> 'a = <fun>
# let rec sub = function (* Alternative implementation *)
  | Lf, _ -> raise Subscript
  | Br (v, t1, t2), 1 -> v
  | Br (v, t1, t2), k when k mod 2 = 0 -> sub (t1, k / 2)
  | Br (v, t1, t2), k -> sub (t2, k / 2)
val sub : 'a tree * int -> 'a = <fun>]]></html:pre><html:p>Notice that we have used a new keyword <html:code>when</html:code> above, which changes
pattern clauses to be only matched if the expression evalutes to true.
This can be equivalently expressed by moving the corresponding
checks into an <html:code>if</html:code> clause on the right hand side of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern match</fr:link>,
but is often more readable using <html:code>when</html:code> (as above).</html:p><html:p>The lookup function <html:code>sub</html:code>, divides the subscript by 2 until 1 is
reached.  If the remainder is 0 then the function follows the left subtree,
otherwise the right.  If it reaches a leaf, it signals error by raising
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Subscript</html:code>.</html:p><html:p>Array access can also be understood in terms of the subscript’s binary code.
Because the subscript must be a positive integer, in binary it has a leading
one.  Discard this one and reverse the remaining bits.  Interpreting zero
as <html:em>left</html:em> and one as <html:em>right</html:em> yields the path from the root to the
subscript.</html:p><html:p>Popular literature often explains the importance of binary as being led by
hardware: because a circuit is either on or off.  The truth is almost the
opposite.  Designers of digital electronics go to a lot of trouble to suppress
the continuous behaviour that would naturally arise.  The real reason why
binary is important is its role in algorithms: an <html:code>if-then-else</html:code> decision leads
to binary branching.</html:p><html:p>Data structures, such as trees, and algorithms, such as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link>, use binary
branching in order to reduce a cost from <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  Two is the
smallest integer divisor that achieves this reduction.  (Larger divisors are
only occasionally helpful, as in the case of B-trees, where they reduce the
constant factor.)  The simplicity of binary arithmetic compared with decimal
arithmetic is just another instance of the simplicity of algorithms based on
binary choices.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:uri><fr:display-uri>focs-funarray-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:route><fr:title
text="The Update Function">The Update Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update = function
  | Lf, k, w ->
      if k = 1 then
        Br (w, Lf, Lf)
      else
        raise Subscript  (* Gap in tree *)
  | Br (v, t1, t2), k, w ->
      if k = 1 then
        Br (w, t1, t2)
      else if k mod 2 = 0 then
        Br (v, update (t1, k / 2, w), t2)
      else
        Br (v, t1, update (t2, k / 2, w))
val update : 'a tree * int * 'a -> 'a tree = <fun>]]></html:pre><html:p>The <html:code>update</html:code> function also divides the subscript repeatedly by two.  When it
reaches a value of one, it has identified the element position.  Then it
replaces the branch node by another branch with the new label.</html:p><html:p>A leaf may be replaced by a branch, extending the array, provided no
intervening nodes have to be generated.  This suffices for arrays without gaps
in their subscripting.  (The data structure can be modified to allow <html:em>sparse</html:em>
arrays, where most subscript positions are undefined.) Exception <fr:link
href="/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
title="The Lookup Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
display-uri="focs-funarray-lookup"
type="local"><html:code>Subscript</html:code></fr:link>
indicates that the subscript position does not exist and cannot be created.
This use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link> is not easily replaced by <html:code>None</html:code> and <html:code>Some</html:code>.</html:p><html:p>Note that there are two tests involving <fr:tex
display="inline"><![CDATA[k=1]]></fr:tex>.  If we have reached a leaf,
it returns a branch, extending the array by one.  If we are still at a branch
node, then the effect is to update an existing array element.</html:p><html:p>A similar function can <html:em>shrink</html:em> an array by one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/</fr:uri><fr:display-uri>focs-ex-7</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:uri><fr:display-uri>focs-ex-7-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:route><fr:title
text="Insertion order in search trees">Insertion order in search trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Draw the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link> that arises from successively inserting the following pairs into the
empty tree: <html:code>("Alice", 6)</html:code>, <html:code>("Tobias", 2)</html:code>, <html:code>("Gerald", 8)</html:code>, <html:code>("Lucy", 9)</html:code>. Then repeat this
task using the order <html:code>("Gerald", 8)</html:code>, <html:code>("Alice", 6)</html:code>, <html:code>("Lucy", 9)</html:code>, <html:code>("Tobias", 2)</html:code>. Why are
results different?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:uri><fr:display-uri>focs-ex-7-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:route><fr:title
text="Insertion with collision detection">Insertion with collision detection</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an insertion function for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link>. It should resemble the existing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-update/"
title="Update"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/"
display-uri="focs-bst-update"
type="local"><html:code>update</html:code></fr:link>
function except that it should raise the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Collision</html:code> if the item to be inserted is already
present.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:uri><fr:display-uri>focs-ex-7-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:route><fr:title
text="Returning the old value on collision">Returning the old value on collision</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, it would be natural for exceptional <html:code>Collision</html:code> to return the
value previously stored in the dictionary. Why is that goal difficult to achieve?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:uri><fr:display-uri>focs-ex-7-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:route><fr:title
text="Deleting from a search tree">Deleting from a search tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Describe an algorithm for deleting an entry from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>. Comment on the suitability of
your approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:uri><fr:display-uri>focs-ex-7-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:route><fr:title
text="Implementing deletion">Implementing deletion</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the delete function outlined in the previous exercise.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:uri><fr:display-uri>focs-ex-7-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:route><fr:title
text="Quadratic traversals">Quadratic traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>preorder</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>postorder</html:code></fr:link> all require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time in the worst
case, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the size of the tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:uri><fr:display-uri>focs-ex-7-7</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:route><fr:title
text="Linear traversals">Linear traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>preord</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>inord</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>postord</html:code></fr:link> all take linear time in the size of the
tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:uri><fr:display-uri>focs-ex-7-8</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:route><fr:title
text="Shifting a functional array">Shifting a functional array</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to remove the first element from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional array</fr:link>. All the other elements are to
have their subscripts reduced by one. The cost of this operation should be linear in the size of the
array.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/</fr:uri><fr:display-uri>focs-functions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functions/</fr:route><fr:title
text="Functions as Values">Functions as Values</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><html:p>In OCaml, functions can be</html:p><html:ul><html:li>passed as arguments to other functions,</html:li>
  <html:li>returned as results,</html:li>
  <html:li>put into lists, trees, etc.,</html:li>
  <html:li>but <html:em>not</html:em> tested for equality.</html:li></html:ul><html:pre><![CDATA[# [(fun n -> n * 2);
   (fun n -> n * 3);
   (fun n -> n + 1)]
- : (int -> int) list = [<fun>; <fun>; <fun>]]]></html:pre><html:p>Progress in programming languages can be measured by what abstractions they
admit.  Conditional expressions (descended from conditional jumps based
on the sign of some numeric variable) and parametric types such as
<fr:tex
display="inline"><![CDATA[\alpha \,\texttt {list}]]></fr:tex> are examples.  The idea that functions could be used
as values in a computation arose early, but it took some time before the idea
was fully realised.  For decades, many programming languages let functions be passed as
arguments to other functions, but few took the trouble needed to allow
functions to be returned as results, since this requires packaging a function
together with the variables it refers to in a <html:em>closure</html:em>.  Today the idea,
pioneered by languages such as Scheme and ML, is everywhere: Python,
JavaScript, Java (since version 8), C++ (since C++11), Rust, Swift and Kotlin
all let anonymous functions be passed around and returned like any other value.</html:p><html:p>In mathematics, a <html:em>functional</html:em> or <html:em>higher-order function</html:em> is a
function that operates on other functions.  Many functionals are familiar from
mathematics: for example, the differential operator maps functions to their
derivatives, which are also functions.  To a mathematician, a function is
typically an infinite, uncomputable object.  We use OCaml functions to represent
algorithms.  Sometimes they represent infinite collections of data given by
computation rules.</html:p><html:p>Functions cannot be compared for equality. We could compare the machine
addresses of the compiled code, but that would merely be a test of identity: it
would regard any two separate functions as unequal even if they were compiled
from identical pieces of source code.  Such a low-level feature has no place in
a principled language.</html:p><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-anonymous-functions/</fr:uri><fr:display-uri>focs-anonymous-functions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-anonymous-functions/</fr:route><fr:title
text="Functions Without Names">Functions Without Names</fr:title></fr:frontmatter><fr:mainmatter><html:p>If functions are to be regarded as computational values, then we need a
notation for them.  The <html:code>fun</html:code> notation expresses a non-recursive function
value without giving the function a name.</html:p><html:p><fr:tex
display="inline"><![CDATA[\tt  fun\;x\;\rightarrow  E]]></fr:tex> is the function <fr:tex
display="inline"><![CDATA[f]]></fr:tex> such that <fr:tex
display="inline"><![CDATA[f(x)=E]]></fr:tex>.
The function <html:code>fun n -&gt; n*2</html:code> is a <html:em>doubling function</html:em>.</html:p><html:pre><![CDATA[# fun n -> n * 2
- : int -> int = <fun>
# (fun n -> n * 2) 17
- : int = 34]]></html:pre><html:p>The main purpose of <html:code>fun</html:code>-notation is to package up small expressions that are to be
applied repeatedly using some other function.
The expression <html:code>fun n -&gt; n*2</html:code> has the same value as the identifier
<html:code>double</html:code>, declared as follows:</html:p><html:pre><![CDATA[# let double n = n * 2
val double : int -> int = <fun>]]></html:pre><html:p>The <html:code>fun</html:code> notation can also do <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matching</fr:link>, and the <html:code>function</html:code> keyword
adds an anonymous variable name to pattern match against.  The following functions
are all equivalent, with the latter definitions bound to the <html:code>is_zero</html:code> value and the earlier ones anonymous:</html:p><html:pre><![CDATA[# fun x -> match x with 0 -> true | _ -> false
- : int -> bool = <fun>
# function 0 -> true | _ -> false
- : int -> bool = <fun>
# let is_zero = fun x -> match x with 0 -> true | _ -> false
val is_zero : int -> bool = <fun>
# let is_zero = function 0 -> true | _ -> false
val is_zero : int -> bool = <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/</fr:uri><fr:display-uri>focs-currying</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-currying/</fr:route><fr:title
text="Curried Functions">Curried Functions</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>curried function</html:em> returns another function as its result. We use
the string concatenation operator <html:code>(^)</html:code> to illustrate how this works.</html:p><html:pre><![CDATA[# (^)
- : string -> string -> string = <fun>
# let prefix = fun a -> fun b -> a ^ b
val prefix : string -> string -> string = <fun>
# let promote = prefix "Senior "
val promote : string -> string = <fun>
# prefix "Junior " "Professor"
- : string = "Junior Professor"
# promote "Professor"
- : string = "Senior Professor"]]></html:pre><html:p>A short form for the definition of <html:code>prefix</html:code> is simply to pass multiple
arguments to the function definition.  The following two definitions
are equivalent in OCaml:</html:p><html:pre><![CDATA[# let prefix = fun a -> fun b -> a ^ b
val prefix : string -> string -> string = <fun>
# let prefix a b = a ^ b
val prefix : string -> string -> string = <fun>]]></html:pre><html:p>Currying is the technique of expressing a function taking multiple arguments as nested functions, each taking a single argument.
The <html:code>fun</html:code>-notation lets us package <html:code>n*2</html:code> as the function
<html:code>fun n -&gt; n * 2</html:code>, but what if there are several variables, as in
<html:code>fun n -&gt; n * 2 + k</html:code>?  A function of two arguments could be coded using
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link> on pairs, writing <html:code>fun (n, k) -&gt; n * 2 + k</html:code>.</html:p><html:p>Currying is an alternative, where we <html:em>nest</html:em> the <html:code>fun</html:code>-notation:</html:p><html:pre><![CDATA[# fun k -> fun n -> n * 2 + k
- : int -> int -> int = <fun>]]></html:pre><html:p>Applying this curried function to the argument 1 yields another function, in which <html:code>k</html:code> has been replaced by 1:</html:p><html:pre><![CDATA[# let fn = fun k -> fun n -> n * 2 + k
val fn : int -> int -> int = <fun>
# let fn' = fn 1 (* n * 2 + 1 *)
val fn' : int -> int = <fun>
# fn' 3  (* 3 * 2 + 1 *)
- : int = 7]]></html:pre><html:p>And this function, when applied to 3, yields the result 7. The two arguments are supplied one after another.</html:p><html:p>The earlier <html:code>prefix</html:code> example is similar and uses the expression <html:code>a ^ b</html:code>,
where <html:code>^</html:code> is the infix operator for string concatenation. Function <html:code>promote</html:code> binds the first argument of <html:code>prefix</html:code> to
<html:code>"Senior "</html:code>; the resulting function prefixes that title
to any string to which it is applied.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-curry-shorthand/</fr:uri><fr:display-uri>focs-curry-shorthand</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-curry-shorthand/</fr:route><fr:title
text="Shorthand for Curried Functions">Shorthand for Curried Functions</fr:title></fr:frontmatter><fr:mainmatter><html:p>A function-returning function is just a function of two arguments.</html:p><html:p>This <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link> syntax is nicer than nested <html:code>fun</html:code> binders:</html:p><html:pre><![CDATA[# let prefix a b = a ^ b
val prefix : string -> string -> string = <fun>
# let dub = prefix "Sir "
val dub : string -> string = <fun>]]></html:pre><html:p>Curried functions allows <html:em>partial application</html:em> (to the first argument).</html:p><html:p>In OCaml, an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-argument curried function <html:code>f</html:code> can be declared using the syntax:</html:p><fr:tex
display="block"><![CDATA[\tt  let \; f \; x_1 \: \ldots  \: x_{n} \: = \: E]]></fr:tex><html:p>and applied using the syntax:</html:p><fr:tex
display="block"><![CDATA[\tt  \; E_1 \; \ldots  \; E_n]]></fr:tex><html:p>If <html:code>f</html:code> is not recursive, then it is equivalent to the function expressed via nesting as follows:</html:p><fr:tex
display="block"><![CDATA[\tt  fun \; x_1 \; \rightarrow  \cdots  \rightarrow  fun \; x_{n} \rightarrow  E ]]></fr:tex><html:p>We now have two ways of expressing functions of multiple arguments: either by
passing a pair of arguments or by currying.  Currying allows <html:em>partial application</html:em>
which is useful when fixing the first argument yields a function
that is interesting in its own right.  An example from mathematics is the
function <fr:tex
display="inline"><![CDATA[x^y]]></fr:tex>, where fixing <fr:tex
display="inline"><![CDATA[y=2]]></fr:tex> yields a function in <fr:tex
display="inline"><![CDATA[x]]></fr:tex> alone, namely
squaring. Similarly, <fr:tex
display="inline"><![CDATA[y=3]]></fr:tex> yields cubing, while <fr:tex
display="inline"><![CDATA[y=1]]></fr:tex> yields the identity
function.</html:p><html:p>Though the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local"><html:code>hd</html:code></fr:link> (which returns the head of a list) is not
curried, it may be used with the curried application syntax in some
expressions:</html:p><html:pre><![CDATA[# List.hd [dub; promote] "Hamilton"
- : string = "Sir Hamilton"]]></html:pre><html:p>Here <html:code>List.hd</html:code> is applied to a list of functions, and the resulting function
<html:code>dub</html:code> is then applied to the string <html:code>"Hamilton"</html:code>.  The idea of
executing code stored in data structures reaches its full development in
<html:em>object-oriented</html:em> programming, like in Java.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/</fr:uri><fr:display-uri>focs-partial-application</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-partial-application/</fr:route><fr:title
text="Partial Application: A Curried Insertion Sort">Partial Application: A Curried Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let insort lessequal =
    let rec ins x = function
      | [] -> [x]
      | y::ys -> if lessequal x y then x :: y :: ys
                 else y :: ins x ys
    in
    let rec sort = function
      | [] -> []
      | x::xs -> ins x (sort xs)
    in
    sort
val insort : ('a -> 'a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">sorting functions</fr:link> we discussed in earlier lectures are coded to sort floating-point
numbers.  They can be generalised to an arbitrary ordered type by passing the
ordering predicate <html:code>lessequal</html:code> as an argument.</html:p><html:p>Functions <html:code>ins</html:code> and <html:code>sort</html:code> are declared locally, referring to <html:code>lessequal</html:code>.
Though it may not be obvious, <html:code>insort</html:code> is a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link>.  Given its first
argument, a predicate for comparing some particular type of items, it returns
the function <html:code>sort</html:code> for sorting lists of that type of items.</html:p><html:p>Some examples of its use:</html:p><html:pre><![CDATA[# insort (<=) [5; 3; 9; 8]
- : int list = [3; 5; 8; 9]
# insort (<=) ["bitten"; "on"; "a"; "bee"]
- : string list = ["a"; "bee"; "bitten"; "on"]
# insort (>=) [5; 3; 9; 8]
- : int list = [9; 8; 5; 3]]]></html:pre><html:p>An obscure point: the syntax <html:code>(&lt;=)</html:code> denotes the comparison operator as a
function, which is then given to <html:code>insort</html:code>.  Passing the relation <fr:tex
display="inline"><![CDATA[\geq ]]></fr:tex> for
<html:code>lessequal</html:code> gives a decreasing sort.  This is no coding trick; it is justified
in mathematics, since if <fr:tex
display="inline"><![CDATA[\leq ]]></fr:tex> is a partial ordering then so is <fr:tex
display="inline"><![CDATA[\geq ]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/</fr:uri><fr:display-uri>focs-map</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-map/</fr:route><fr:title
text="map: the “Apply to All” Function">map: the “Apply to All” Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec map f = function
    | [] -> []
    | x::xs -> (f x) :: map f xs
val map : ('a -> 'b) -> 'a list -> 'b list = <fun>
# map (fun s -> s ^ "ppy") ["Hi"; "Ho"]
- : string list = ["Hippy"; "Hoppy"]
# map (map double) [[1]; [2; 3]]
- : int list list = [[2]; [4; 6]]]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>map</html:code> applies a function to every element of a list,
returning a list of the function’s results.  “Apply to all” is a fundamental
operation and we shall see several applications of it below.  We
again see the advantages of <html:code>fun</html:code>-notation, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">currying</fr:link> and
<html:code>map</html:code>.  If we did not have them, the first use of <html:code>map</html:code> in the above code block
would require a preliminary function declaration:</html:p><html:pre><![CDATA[# let rec sillylist = function
    | [] -> []
    | s::ss -> (s ^ "ppy") :: sillylist ss
val sillylist : string list -> string list = <fun>]]></html:pre><html:p>An expression containing several applications of functionals—such as our
second example—can abbreviate a long series of declarations.  Sometimes this
coding style is cryptic, but it can be clear as crystal.  Treating functions
as values lets us capture common program structures once and for all.</html:p><html:p>In the second example, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-anonymous-functions/"
title="Functions Without Names"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-anonymous-functions/"
display-uri="focs-anonymous-functions"
type="local"><html:code>double</html:code></fr:link> is the obvious integer doubling function we
defined earlier.  Note that <html:code>map</html:code> is a built-in OCaml function in the
form of <html:code>List.map</html:code>.  OCaml’s standard library includes, among much else, many
list functions.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/</fr:uri><fr:display-uri>focs-transpose</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-transpose/</fr:route><fr:title
text="Example: Matrix Transpose">Example: Matrix Transpose</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {pmatrix}
           a   & b & c \\
           d   & e & f
   \end {pmatrix}^T =
   \begin {pmatrix}
        a & d     \\
        b & e     \\
        c & f
\end {pmatrix}
]]></fr:tex><html:pre><![CDATA[# let rec transp = function
    | []::_ -> []
    | rows -> (map List.hd rows) ::
              (transp (map List.tl rows))
val transp : 'a list list -> 'a list list = <fun>]]></html:pre><html:p>A matrix can be viewed as a list of rows, each row a list of matrix elements.
This representation is not especially efficient compared with the conventional
one (using arrays).  Lists of lists turn up often, though, and we can see how
to deal with them by taking familiar matrix operations as examples.
<html:em>ML for the Working Programmer</html:em> goes as far as Gaussian elimination,
which presents surprisingly few difficulties.</html:p><html:p>The transpose of the matrix
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix} a & b & c \\
                           d & e & f\end {smallmatrix}\right )]]></fr:tex>
is
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix}
        a & d     \\
        b & e     \\
        c & f
   \end {smallmatrix}\right )]]></fr:tex>,
which in OCaml corresponds to the following transformation on lists of lists:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {[[a; b; c]; [d; e; f]]} \Rightarrow & \text { [[a; d]; [b; e]; [c; f]]}
\end {aligned}
]]></fr:tex><html:p>The workings of function <html:code>transp</html:code> are simple.  If <html:code>rows</html:code> is the
matrix to be transposed, then <html:code>map hd</html:code> extracts its first column and
<html:code>map tl</html:code> extracts its second column:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {map hd rows} \Rightarrow  & \text { [a; d]}\\
\text {map tl rows} \Rightarrow  & \text { [[b; c]; [e; f]]}
\end {aligned}
]]></fr:tex><html:p>A recursive call transposes the latter matrix, which is then given the column
<html:code>[a; d]</html:code> as its first row.
The two functions expressed using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> would otherwise have to be declared
separately.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-matrix-multiplication/</fr:uri><fr:display-uri>focs-matrix-multiplication</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-matrix-multiplication/</fr:route><fr:title
text="Review of Matrix Multiplication">Review of Matrix Multiplication</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {pmatrix} A_1 & \cdots  & A_k \end {pmatrix}  \cdot 
   \begin {pmatrix}
        B_1 \\ \vdots  \\ B_k
   \end {pmatrix}   =
   \begin {pmatrix}
        A_1 B_1 + \cdots  + A_k B_k
   \end {pmatrix}
]]></fr:tex><html:p>The right side is the <html:em>vector dot product</html:em> <fr:tex
display="inline"><![CDATA[\vec {A}\cdot  \vec {B}]]></fr:tex>.
Repeat for each <html:em>row</html:em> of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> and <html:em>column</html:em> of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><html:p>The <html:em>dot product</html:em> of two vectors is</html:p><fr:tex
display="block"><![CDATA[ (a_1,\ldots ,a_k) \cdot  (b_1,\ldots ,b_k) = a_1b_1 + \cdots  + a_kb_k ]]></fr:tex><html:p>A simple case of matrix multiplication is when <fr:tex
display="inline"><![CDATA[A]]></fr:tex> consists of a single row
and <fr:tex
display="inline"><![CDATA[B]]></fr:tex> consists of a single column.  Provided <fr:tex
display="inline"><![CDATA[A]]></fr:tex> and <fr:tex
display="inline"><![CDATA[B]]></fr:tex> contain the same
number <fr:tex
display="inline"><![CDATA[k]]></fr:tex> of elements, multiplying them yields a <fr:tex
display="inline"><![CDATA[1\times 1]]></fr:tex> matrix whose
single element is the dot product shown above.</html:p><html:p>If <fr:tex
display="inline"><![CDATA[A]]></fr:tex> is an <fr:tex
display="inline"><![CDATA[m\times  k]]></fr:tex> matrix and <fr:tex
display="inline"><![CDATA[B]]></fr:tex> is a <fr:tex
display="inline"><![CDATA[k\times  n]]></fr:tex> matrix
then <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is an <fr:tex
display="inline"><![CDATA[m\times  n]]></fr:tex> matrix.
For each <fr:tex
display="inline"><![CDATA[i]]></fr:tex> and <fr:tex
display="inline"><![CDATA[j]]></fr:tex>, the <fr:tex
display="inline"><![CDATA[(i,j)]]></fr:tex> element of <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is the dot
product of row <fr:tex
display="inline"><![CDATA[i]]></fr:tex> of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> with column <fr:tex
display="inline"><![CDATA[j]]></fr:tex> of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><fr:tex
display="block"><![CDATA[
\begin {pmatrix}
        2 & 0 \\
        3 &-1 \\
        0 & 1 \\
        1 & 1
   \end {pmatrix}
   \begin {pmatrix}
        1 & 0 & 2 \\
        4 &-1 & 0
   \end {pmatrix}   =
   \begin {pmatrix}
        2 & 0 & 4 \\
       -1 & 1 & 6 \\
        4 &-1 & 0 \\
        5 &-1 & 2
\end {pmatrix}
]]></fr:tex><html:p>The (1, 1) element above is computed by</html:p><fr:tex
display="block"><![CDATA[ (2,0)\cdot (1,4) = 2\times 1 + 0\times 4 = 2. ]]></fr:tex><html:p>Coding matrix multiplication in a conventional programming language usually
involves three nested loops.  It is hard to avoid mistakes in the subscripting,
which often runs slowly due to redundant internal calculations.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:uri><fr:display-uri>focs-matmul-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:route><fr:title
text="Matrix Multiplication in OCaml">Matrix Multiplication in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:p><html:em>Dot product</html:em> of two vectors—a <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link></html:em></html:p><html:pre><![CDATA[# let rec dotprod xs ys =
    match xs, ys with
    | [], [] -> 0.0
    | x::xs, y::ys ->  (x *. y) +. (dotprod xs ys)
Lines 2-4, characters 5-51:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
([], _::_)

val dotprod : float list -> float list -> float = <fun>]]></html:pre><html:p><html:em>Matrix product</html:em></html:p><html:pre><![CDATA[# let rec matprod arows brows =
    let cols = transp brows in
    map (fun row -> map (dotprod row) cols) arows
val matprod : float list list -> float list list -> float list list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local"><html:code>transp brows</html:code></fr:link> converts <fr:tex
display="inline"><![CDATA[B]]></fr:tex> into a list of columns, yielding a
list whose elements are the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Each row of <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is
obtained by multiplying a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><html:p>Because <html:code>dotprod</html:code> is curried, it can be applied to a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The
resulting function is applied to all the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  We have another
example of currying and partial application.</html:p><html:p>The outer <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> applies <html:code>dotprod</html:code> to each row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The inner
<html:code>map</html:code>, using <html:code>fun</html:code>-notation, applies <html:code>dotprod row</html:code> to each
column of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Compare with the version in <html:em>ML for the Working
  Programmer</html:em> (page 89) which does not use <html:code>map</html:code> and requires two
additional function declarations.</html:p><html:p>In the dot product function, the two vectors must have the same length.
Otherwise, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Match_failure</html:code> is raised.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:uri><fr:display-uri>focs-predicate-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:route><fr:title
text="List Functionals for Predicates">List Functionals for Predicates</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec exists p = function
  | [] -> false
  | x::xs -> (p x) || (exists p xs)
val exists : ('a -> bool) -> 'a list -> bool = <fun>
# let rec filter p = function
  | [] -> []
  | x::xs ->
      if p x then
        x :: filter p xs
      else
        filter p xs
val filter : ('a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>A <html:em>predicate</html:em> is a <html:em>boolean-valued</html:em> function.</html:p><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>exists</html:code> transforms a predicate into a predicate over
lists.  Given a list, <html:code>exists p</html:code> tests whether or not some list element
satisfies <html:code>p</html:code> (making it return <html:code>true</html:code>).  If it finds one, it stops
searching immediately, thanks to the behaviour of the lazy <html:code>||</html:code> operator.</html:p><html:p>Dually, we have a functional to test whether all list elements satisfy the
predicate.  If it finds a counterexample then it, too, stops searching.</html:p><html:pre><![CDATA[# let rec all p = function
  | [] -> true
  | x::xs -> (p x) && all p xs
val all : ('a -> bool) -> 'a list -> bool = <fun>]]></html:pre><html:p>The <html:code>filter</html:code> functional, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>, transforms lists.  It applies a
predicate to all the list elements, but instead of returning the
resulting values (which could only be <html:code>true</html:code> or <html:code>false</html:code>), it returns
the list of elements satisfying the predicate.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:uri><fr:display-uri>focs-predicate-applications</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:route><fr:title
text="Applications of the Predicate Functionals">Applications of the Predicate Functionals</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let member y xs =
    exists (fun x -> x=y) xs
val member : 'a -> 'a list -> bool = <fun>
# let inter xs ys =
    filter (fun x -> member x ys) xs
val inter : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Testing whether two lists have no common elements</html:em></html:p><html:pre><![CDATA[# let disjoint xs ys =
    all (fun x -> all (fun y -> x<>y) ys) xs
val disjoint : 'a list -> 'a list -> bool = <fun>]]></html:pre><html:p>The Lists lecture presented the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link>, which tests whether a
specified value can be found as a list element, and <html:code>inter</html:code>, which returns the
“intersection” of two lists: the list of elements they have in common.</html:p><html:p>But remember: the purpose of list <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> is not to replace the
declarations of popular functions, which probably are available already.  It is
to eliminate the need for separate declarations of ad-hoc functions.  When they
are nested, like the calls to <html:code>all</html:code> in <html:code>disjoint</html:code> above, the
inner functions are almost certainly one-offs, not worth declaring separately.</html:p><html:p>Our primitives themselves can be seen as a programming language.  Part of the
task of programming is to extend our programming language with notation for
solving the problem at hand.  The levels of notation that we define should
correspond to natural <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">levels of abstraction</fr:link> in the problem domain.</html:p><html:p>Historical Note:
Alonzo Church’s <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus gave a simple syntax, <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-notation,
for expressing functions.  It is the direct precursor of OCaml’s
<html:code>fun</html:code>-notation.  It was soon shown that his system was equivalent in
computational power to Turing machines, and <html:em>Church’s thesis</html:em> states that
this defines precisely the set of functions that can be computed effectively.</html:p><html:p>The <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus had a tremendous influence on the design of functional
programming languages.  McCarthy’s Lisp was something of a false start; it
interpreted variable binding incorrectly, an error that stood for some 20
years.  But in 1966, Peter Landin (of Queen Mary College, University of London)
sketched out the main features of functional languages.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/</fr:uri><fr:display-uri>focs-ex-8</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-1/</fr:uri><fr:display-uri>focs-ex-8-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-1/</fr:route><fr:title
text="The argument-swapping functional">The argument-swapping functional</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What does the following function do, and what are its uses?</html:p><html:pre><![CDATA[let sw f x y = f y x]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:uri><fr:display-uri>focs-ex-8-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:route><fr:title
text="Lexicographic orderings">Lexicographic orderings</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>There are many ways of combining orderings. The <html:code>lexicographic ordering</html:code> uses two keys for
comparisons. It is specified by</html:p><fr:tex
display="block"><![CDATA[(x',y')<(x,y)\iff  x'<x \vee  (x'=x \wedge  y'<y).]]></fr:tex><html:p>Write an OCaml function to lexicographically combine two orderings, supplied as functions. Explain
how it allows function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-partial-application/"
title="Partial Application: A Curried Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/"
display-uri="focs-partial-application"
type="local"><html:code>insort</html:code></fr:link> to sort a list of pairs.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:uri><fr:display-uri>focs-ex-8-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:route><fr:title
text="Mapping over lists of lists">Mapping over lists of lists</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Without using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> write a function <html:code>map2</html:code> such that <html:code>map2 f</html:code> is equivalent to <html:code>map (map f)</html:code>. The
obvious solution requires declaring two recursive functions. Try to get away with only one by
exploiting nested <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:uri><fr:display-uri>focs-ex-8-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:route><fr:title
text="A map for options">A map for options</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The type <html:code>'a option</html:code>, declared below, can be viewed as a type of lists having at most one element.
(It is typically used as an alternative to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">exceptions</fr:link>.) Declare an analogue of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>
for type <html:code>'a option</html:code>.</html:p><html:pre><![CDATA[type 'a option = None | Some of 'a]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:uri><fr:display-uri>focs-ex-8-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:route><fr:title
text="Making change with map">Making change with map</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Recall the making change function of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">More on Lists</fr:link>:</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Function <html:code>allc</html:code> applies the function ‘cons a <html:code>c</html:code>’ to every element of a list. Eliminate it by
declaring a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried</fr:link> cons function and applying <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sequences/</fr:uri><fr:display-uri>focs-sequences</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sequences/</fr:route><fr:title
text="Sequences, or Lazy Lists">Sequences, or Lazy Lists</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-pipeline/</fr:uri><fr:display-uri>focs-pipeline</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-pipeline/</fr:route><fr:title
text="A Pipeline">A Pipeline</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\fbox {\textit {Producer}} \to  \fbox {\textit {Filter}} \to \cdots \to 
 \fbox {\textit {Filter}} \to  \fbox {\textit {Consumer}}
]]></fr:tex><html:ul><html:li>Produce sequence of items</html:li>
  <html:li>Filter sequence in stages</html:li>
  <html:li>Consume results as needed</html:li>
  <html:li><html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">Lazy lists</fr:link></html:em> join the stages together</html:li></html:ul><html:p>Two types of program can be distinguished.  A sequential program
accepts a problem to solve, processes for a while, and finally terminates
with its result.  A typical example is the huge numerical simulations that are
run on supercomputers.  Most of our OCaml functions also fit this model.</html:p><html:p>At the other extreme are <html:em>reactive</html:em> programs, whose job is to interact
with the environment.  They communicate constantly during their operation and
run for as long as is necessary.  A typical example is the software that
controls many modern aircraft.  Reactive programs often consist of
<html:em>concurrent processes</html:em> running at the same time and communicating with
one another.</html:p><html:p>Concurrency is too difficult to consider in this course, but we can model
simple pipelines such as that shown above.  The <html:em>Producer</html:em> represents one
or more sources of data, which it outputs as a stream.  The <html:em>Filter</html:em>
stages convert the input stream to an output stream, perhaps consuming several
input items to yield a single output item.  The <html:em>Consumer</html:em> takes as many
elements as necessary.</html:p><html:p>The Consumer drives the pipeline: nothing is computed except in response to
its demand for an additional datum.  Execution of the Filter stages is
interleaved as required for the computation to go through.  The programmer
sets up the data dependencies but has no clear idea of what happens when.  We
have the illusion of concurrent computation.</html:p><html:p>The Unix operating system provides similar ideas through its <html:em>pipes</html:em> that
link processes together.  In OCaml, we can model pipelines using <html:em>lazy lists</html:em>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-lists/</fr:uri><fr:display-uri>focs-lazy-lists</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-lists/</fr:route><fr:title
text="Lazy Lists (or Streams)">Lazy Lists (or Streams)</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Lists of possibly <html:em>infinite</html:em> length</html:li>
  <html:li>Elements <html:em>computed upon demand</html:em></html:li>
  <html:li><html:em>Avoids waste</html:em> if there are many solutions</html:li>
  <html:li><html:em>Infinite</html:em> values are a useful abstraction</html:li></html:ul><html:p>In OCaml, we can implement laziness by <html:em>delaying evaluation</html:em> of the tail of
the list.</html:p><html:p>Lazy lists have practical uses.  Some algorithms, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>, can
yield many solutions when only a few are required.  Sometimes the original
problem concerns infinite series: with lazy lists, we can pretend they really
exist!</html:p><html:p>We are now dealing with <html:em>infinite</html:em> (or at least unbounded) computations.
A potentially infinite source of data is processed one element at a time, upon
demand.  Such programs are harder to understand than terminating ones and have
more ways of going wrong.</html:p><html:p>Some purely functional languages, such as Haskell, use lazy evaluation
everywhere.  Even the if-then-else construct can be a function, and all lists
are lazy.  In OCaml, we can declare a type of lists such that evaluation of the
tail does not occur until demanded.  <html:em>Delayed</html:em> evaluation is weaker than
<html:em>lazy</html:em> evaluation, but it is good enough for our purposes and often the
best compromise for performance and memory usage.</html:p><html:p>The traditional word “stream” is reserved in OCaml parlance for
input/output channels.  Let us call lazy lists <html:em>sequences</html:em> instead.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:uri><fr:display-uri>focs-lazy-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:route><fr:title
text="Lazy Lists in OCaml">Lazy Lists in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>The empty tuple <html:code>()</html:code> and its <html:em>type</html:em> <html:code>unit</html:code></html:li>
  <html:li>Delayed version of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> is <html:code>fun () -&gt; E</html:code></html:li></html:ul><html:pre><![CDATA[# type 'a seq =
  | Nil
  | Cons of 'a * (unit -> 'a seq)
type 'a seq = Nil | Cons of 'a * (unit -> 'a seq)
# let head (Cons (x, _)) = x
Line 1, characters 10-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val head : 'a seq -> 'a = <fun>
# let tail (Cons (_, xf)) = xf ()
Line 1, characters 10-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val tail : 'a seq -> 'a seq = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[\tt  Cons(x, xf)]]></fr:tex> has <html:em>head</html:em> <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and <html:em>tail function</html:em> <fr:tex
display="inline"><![CDATA[xf]]></fr:tex></html:p><html:p>The primitive OCaml type <html:code>unit</html:code> has one element, which is
written <html:code>()</html:code>.  This element may be regarded as a 0-tuple, and
<html:code>unit</html:code> as the nullary Cartesian product.  (Think of the connection
between multiplication and the number 1.)</html:p><html:p>The empty tuple serves as a placeholder in situations where no information is
required.  It may:</html:p><html:ul><html:li>appear in a data structure.  For example, a <html:code>unit</html:code>-valued <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">dictionary</fr:link> represents a set of keys.</html:li>
  <html:li>be the argument of a function, where its effect is to <html:em>delay evaluation</html:em>.</html:li>
  <html:li>be the argument or result of a procedure. (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
title="Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
display-uri="focs-procedural-programming"
type="local">Procedural Programming section</fr:link>)</html:li></html:ul><html:p>The empty tuple, like all tuples, is a constructor and is allowed in patterns;
for example: <html:code>let f () = ...</html:code></html:p><html:p>In particular <fr:tex
display="inline"><![CDATA[\tt  fun \, () \rightarrow  E]]></fr:tex> is the function that takes an argument of
type <html:code>unit</html:code> and returns the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as its result.  Expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>
is not evaluated until the function is called, even though the only possible
argument is <html:code>()</html:code>.  The function simply delays the evaluation of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-infinite-sequence/</fr:uri><fr:display-uri>focs-infinite-sequence</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-infinite-sequence/</fr:route><fr:title
text="The Infinite Sequence: k, k+1, k+2, …">The Infinite Sequence: <fr:tex
display="inline"><![CDATA[k]]></fr:tex>, <fr:tex
display="inline"><![CDATA[k+1]]></fr:tex>, <fr:tex
display="inline"><![CDATA[k+2]]></fr:tex>, …</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec from k = Cons (k, fun () -> from (k+1))
val from : int -> int seq = <fun>
# let it = from 1
val it : int seq = Cons (1, <fun>)
# let it = tail it
val it : int seq = Cons (2, <fun>)
# let it = tail it
val it : int seq = Cons (3, <fun>)]]></html:pre><html:p>Function <html:code>from</html:code> constructs the infinite sequence of integers starting
from <fr:tex
display="inline"><![CDATA[k]]></fr:tex>.  Execution terminates because of the <html:code>fun</html:code> enclosing the
recursive call.  OCaml displays the tail of a sequence as <html:code>fun</html:code>, which
stands for some function value.  Each call to <html:code>tail</html:code> generates the next
sequence element.  We could do this forever.</html:p><html:p>This example is of little practical value because the cost of computing a
sequence element will be dominated by that of creating the dummy function.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">Lazy lists</fr:link> tend to have high overheads.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:uri><fr:display-uri>focs-seq-consume</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:route><fr:title
text="Consuming a Sequence">Consuming a Sequence</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec get n s =
    match n, s with
    | 0, _            -> []
    | n, Nil          -> []
    | n, Cons (x, xf) -> x :: get (n-1) (xf ())
val get : int -> 'a seq -> 'a list = <fun>]]></html:pre><html:p>The above code gets the first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements as a list.
<html:code>xf ()</html:code> <html:em>forces</html:em> evaluation.</html:p><html:p>The function <html:code>get</html:code> converts a sequence to a list.  It takes the
first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements; it takes all of them if <fr:tex
display="inline"><![CDATA[n<0]]></fr:tex>, which can terminate only if
the sequence is finite.</html:p><html:p>In the last line of <html:code>get</html:code>, the expression <html:code>xf()</html:code> calls the tail
function, demanding evaluation of the next element.  This operation is called
<html:em>forcing</html:em> the sequence.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-evaluation/</fr:uri><fr:display-uri>focs-seq-evaluation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-evaluation/</fr:route><fr:title
text="Sample Evaluation">Sample Evaluation</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {aligned}
\tt  get(2,\, from \; 6) \\
\tt  get(2,\, Cons(6, fun \; () \rightarrow  from \; (6+1))) \\
\tt  6 :: get(1,\, from \; (6+1)) \\
\tt  6 :: get(1,\, Cons \; (7,\, fun \; () \rightarrow  from \; (7+1))) \\
\tt  6 :: 7 :: get(0,\, Cons \; (8,\, fun \; () \rightarrow  from \; (8+1))) \\
\tt  6 :: 7 :: [] \\
\tt  [6; 7]
\end {aligned}
]]></fr:tex><html:p>Here we ask for two elements of the infinite sequence.  In fact, three
elements are computed: 6, 7 and 8.  Our implementation is slightly too eager.
A more complicated <html:code>type</html:code> declaration could avoid this problem.
Another problem is that if one repeatedly examines some particular list
element using forcing, that element is repeatedly evaluated.  In a lazy
programming language, the result of the first evaluation would be stored for
later reference.  To get the same effect in OCaml requires the use of
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local">references</fr:link>.</html:p><html:p>We should be grateful that the potentially infinite computation is kept
finite.  The tail of the original sequence even contains the unevaluated
expression 6+1.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:uri><fr:display-uri>focs-seq-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:route><fr:title
text="Joining Two Sequences">Joining Two Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec appendq xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons(x, fun () -> appendq (xf ()) yq)
val appendq : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>A more fair alternative:</html:p><html:pre><![CDATA[# let rec interleave xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons (x, fun () -> interleave yq (xf ()))
val interleave : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>Most list functions and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> have analogues on sequences, but strange
things can happen.  Can an infinite list be reversed?</html:p><html:p>Function <html:code>appendq</html:code> is precisely the same idea as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>
from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">Lists lecture</fr:link>; it concatenates two sequences.  If the first
argument is infinite, then <html:code>appendq</html:code> never gets to its second argument,
which is lost.  Concatenation of infinite sequences is not terribly
interesting.</html:p><html:p>The function <html:code>interleave</html:code> avoids this problem by exchanging the two
arguments in each recursive call.  It combines the two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, losing no
elements.  Interleaving is the right way to combine two potentially infinite
information sources into one.</html:p><html:p>In both function declarations, observe that each <html:code>xf ()</html:code> is enclosed
within a <fr:tex
display="inline"><![CDATA[{\tt  fun () \rightarrow  \ldots }]]></fr:tex>.  Each <html:em>force</html:em> is enclosed within a
<html:em>delay</html:em>.  This practice makes the functions lazy.  A force not enclosed
in a delay, as in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-seq-consume/"
title="Consuming a Sequence"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/"
display-uri="focs-seq-consume"
type="local"><html:code>get</html:code></fr:link> above, runs the risk of evaluating the sequence
in full.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-functionals/</fr:uri><fr:display-uri>focs-seq-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-functionals/</fr:route><fr:title
text="Functionals for Lazy Lists">Functionals for Lazy Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Filtering <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>:</html:p><html:pre><![CDATA[# let rec filterq p = function
  | Nil -> Nil
  | Cons (x, xf) ->
      if p x then
        Cons (x, fun () -> filterq p (xf ()))
      else
        filterq p (xf ())
val filterq : ('a -> bool) -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>The infinite sequence <fr:tex
display="inline"><![CDATA[x]]></fr:tex>, <fr:tex
display="inline"><![CDATA[f(x)]]></fr:tex>, <fr:tex
display="inline"><![CDATA[f(f(x))]]></fr:tex>, …</html:p><html:pre><![CDATA[# let rec iterates f x =
    Cons (x, fun () -> iterates f (f x))
val iterates : ('a -> 'a) -> 'a -> 'a seq = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>filterq</html:code> demands elements of <html:code>xq</html:code> until it finds
one satisfying <html:code>p</html:code>.  (Recall <fr:link
href="/teaching/2627/FoundsCS/forest/focs-predicate-functionals/"
title="List Functionals for Predicates"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/"
display-uri="focs-predicate-functionals"
type="local"><html:code>filter</html:code></fr:link>, the analogous operation for ordinary lists.)  It
contains a <html:em>force</html:em> not protected by a <html:em>delay</html:em>.  If <html:code>xq</html:code> is
infinite and contains no satisfactory element, then <html:code>filterq</html:code> runs
forever.</html:p><html:p>The functional <html:code>iterates</html:code> generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-infinite-sequence/"
title="The Infinite Sequence: k, k+1, k+2, …"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-infinite-sequence/"
display-uri="focs-infinite-sequence"
type="local"><html:code>from</html:code></fr:link>.  It creates the
next element not by adding one but by calling the function <html:code>f</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-numerical/</fr:uri><fr:display-uri>focs-seq-numerical</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-numerical/</fr:route><fr:title
text="Numerical Computations on Infinite Sequences">Numerical Computations on Infinite Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let next a x = (a /. x +. x) /. 2.0
val next : float -> float -> float = <fun>]]></html:pre><html:p>Close enough?</html:p><html:pre><![CDATA[# let rec within eps = function
  | Cons (x, xf) ->
      match xf () with
      | Cons (y, yf) ->
          if abs_float (x -. y) <= eps then y
          else within eps (Cons (y, yf))
Lines 3-6, characters 7-41:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

Lines 1-6, characters 22-41:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val within : float -> float seq -> float = <fun>]]></html:pre><html:p>Square Roots:</html:p><html:pre><![CDATA[# let root a = within 1e-6 (iterates (next a) 1.0)
val root : float -> float = <fun>]]></html:pre><html:p>The <html:em>Newton-Raphson method</html:em> is widely used for computing square roots.
The infinite series <fr:tex
display="inline"><![CDATA[x_0, (a/x_0+x_0)/2, \ldots {}]]></fr:tex> converges rapidly to <fr:tex
display="inline"><![CDATA[\sqrt {a}]]></fr:tex>.
The initial approximation, <fr:tex
display="inline"><![CDATA[x_0]]></fr:tex>, is typically retrieved from a table, and is accurate enough
that only a few iterations of the method are necessary.
Calling <html:code>iterates (next a) x0</html:code> generates the <html:em>infinite series</html:em> of
approximations to the square root of <fr:tex
display="inline"><![CDATA[a]]></fr:tex> using the Newton-Raphson method.
To compute <fr:tex
display="inline"><![CDATA[\sqrt 2]]></fr:tex>, the resulting series begins 1, 1.5, 1.41667, 1.4142157, 1.414213562, …,
and this last figure is already accurate to 10 significant digits!</html:p><html:p>Function <html:code>within</html:code> searches down the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy list</fr:link> for two points whose
difference is less than <html:code>eps</html:code>.  It tests their absolute difference.
Relative difference and other “close enough” tests can be coded.  Such
components can be used to implement other numerical functions directly as
functions over sequences.  The point is to build programs from small,
interchangeable parts.</html:p><html:p>Function <html:code>root</html:code> uses <html:code>within</html:code>, <html:code>iterates</html:code> and <html:code>next</html:code> to
to apply Newton-Raphson with a tolerance of <fr:tex
display="inline"><![CDATA[10^{-6}]]></fr:tex>
and a (poor) initial approximation of 1.0.</html:p><html:pre><![CDATA[# root 2.0;;
- : float = 1.41421356237309492]]></html:pre><html:p>This treatment of numerical computation has received some attention in the
research literature; a recurring example is Richardson extrapolation.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/</fr:uri><fr:display-uri>focs-ex-9</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:uri><fr:display-uri>focs-ex-9-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:route><fr:title
text="A map for sequences">A map for sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an analogue of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> for sequences.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:uri><fr:display-uri>focs-ex-9-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:route><fr:title
text="Concatenating infinite sequences">Concatenating infinite sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the list function <html:code>concat</html:code>, which concatenates a list of lists to form a single list. Can
it be generalised to concatenate a sequence of sequences? What can go wrong?</html:p><html:pre><![CDATA[let rec concat = function
| [] -> []
| l::ls -> l @ concat ls]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:uri><fr:display-uri>focs-ex-9-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:route><fr:title
text="Making change lazily">Making change lazily</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">make change</fr:link> using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, delivering the sequence of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all possible ways of
making change</fr:link>. Using sequences allows us to compute solutions one at a time when there exists an
astronomical number. Represent lists of coins using ordinary lists. (<html:em>Hint</html:em>: to  benefit from
laziness you may need to pass around the sequence of alternative solutions as a function of type
<html:code>unit -&gt; (int list) seq</html:code>.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:uri><fr:display-uri>focs-ex-9-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:route><fr:title
text="Lazy binary trees">Lazy binary trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A <html:em>lazy binary tree</html:em> is either empty or is a branch containing a label and two lazy <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>,
possibly to infinite depth. Present an OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> to represent lazy binary trees, along with a
function that accepts a lazy binary tree and produces a lazy list that contains all of the tree’s
labels. (Taken from the exam question 2008 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:uri><fr:display-uri>focs-ex-9-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:route><fr:title
text="All lists of zeroes and ones">All lists of zeroes and ones</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the lazy list whose elements are all ordinary lists of zeroes and ones, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 1]; [1; 0]; [1; 1]; [0; 0; 0]; </html:code>….  (Taken from the exam question
2003 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:uri><fr:display-uri>focs-ex-9-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:route><fr:title
text="Enumerating palindromes">Enumerating palindromes</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>(Continuing the previous exercise.)
A <html:em>palindrome</html:em> is a list that equals its own reverse. Code the lazy list whose elements are all
palindromes of 0s and 1s, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 0; 0]; [0; 1; 0]; [1; 1]; [1; 0; 1]; [1; 1; 1]; [0; 0; 0; 0]; </html:code>, …. You
may take the reversal function <html:code>List.rev</html:code> as given.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queues/</fr:uri><fr:display-uri>focs-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-queues/</fr:route><fr:title
text="Queues and Search Strategies">Queues and Search Strategies</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/</fr:uri><fr:display-uri>focs-bfs-dfs</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-dfs/</fr:route><fr:title
text="Breadth-First v Depth-First Tree Traversal">Breadth-First v Depth-First Tree Traversal</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>binary trees as <html:em>decision trees</html:em></html:li>
  <html:li>look for <html:em>solution nodes</html:em>
    <html:ul><html:li>Depth-first: search one subtree in full before moving on</html:li>
      <html:li>Breadth-first: search all nodes at level <fr:tex
display="inline"><![CDATA[k]]></fr:tex> before moving to <fr:tex
display="inline"><![CDATA[k+1]]></fr:tex></html:li></html:ul></html:li>
  <html:li>finds <html:em>all</html:em> solutions — nearest first!</html:li></html:ul><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">Preorder, inorder and postorder tree traversals</fr:link> all have something in common:
they are depth-first.  At each node, the left subtree is entirely
traversed before the right subtree.  Depth-first traversals are easy to code
and can be efficient, but they are ill-suited for some problems.</html:p><html:p>Suppose the tree represents the possible moves in a puzzle, and the purpose
of the traversal is to search for a node containing a solution.  Then a
depth-first traversal may find one solution node deep in the left subtree,
when another solution is at the very top of the right subtree.  Often we
want the shortest path to a solution.</html:p><html:p>Suppose the tree is <html:em>infinite</html:em> or simply extremely large.  Depth-first search
is almost useless with such trees, for if the left subtree is infinite then the
search will never reach the right subtree.  OCaml can represent infinite trees by
the means discussed in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sequences/"
title="Sequences, or Lazy Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sequences/"
display-uri="focs-sequences"
type="local">lecture on laziness</fr:link>. Another tree representation (suitable
for solving solitaire, for example) is by a function <html:code>next : pos -&gt; pos list</html:code>,
which maps a board position to a list of the positions possible after
the next move.  For simplicity, the examples below use the OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link>
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local"><html:code>tree</html:code></fr:link>, which has only finite trees.</html:p><html:p>A <html:em>breadth-first</html:em> traversal explores the nodes horizontally rather than
vertically.  When visiting a node, it does not traverse the subtrees until
it has visited all other nodes at the current depth.  This is easily
implemented by keeping a list of trees to visit.  Initially, this list
consists of one element: the entire tree.  Each iteration removes a tree
from the head of the list and adds its subtrees after the end of the
list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:uri><fr:display-uri>focs-bfs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Append">Breadth-First Tree Traversal — Using Append</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nbreadth = function
  | [] -> []
  | Lf :: ts -> nbreadth ts
  | Br (v, t, u) :: ts ->
      v :: nbreadth (ts @ [t; u])
val nbreadth : 'a tree list -> 'a list = <fun>]]></html:pre><html:p>Keeps an <html:em>enormous queue</html:em> of nodes of search, and is a wasteful use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.</html:p><html:p>Breadth-first search can be inefficient, this naive implementation especially
so.  When the search is at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> of the tree, the list contains all the
remaining trees at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex>, followed by the subtrees (all at depth <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>) of
the trees that have already been visited.  At depth 10, the list could already
contain 1024 elements.  It requires a lot of space, and aggravates this with a
gross misuse of append.  Evaluating <html:code>ts@[t, u]</html:code> copies the long list
<html:code>ts</html:code> just to insert two elements.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/</fr:uri><fr:display-uri>focs-queue-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-queue-adt/</fr:route><fr:title
text="An Abstract Data Type: Queues">An Abstract Data Type: Queues</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><html:code>qempty</html:code> is the <html:em>empty queue</html:em></html:li>
  <html:li><html:code>qnull</html:code> <html:em>tests</html:em> whether a queue is empty</html:li>
  <html:li><html:code>qhd</html:code> <html:em>returns</html:em> the element at the <html:em>head</html:em> of a queue</html:li>
  <html:li><html:code>deq</html:code> <html:em>discards</html:em> the element at the <html:em>head</html:em> of a queue</html:li>
  <html:li><html:code>enq</html:code> <html:em>adds</html:em> an element at the <html:em>end</html:em> of a queue</html:li></html:ul><html:p>Breadth-first search becomes much faster if we replace the lists by
<html:em>queues</html:em>.  A queue represents a sequence, allowing elements to be taken
from the head and added to the tail.  This is a First-In-First-Out (FIFO)
discipline: the item next to be removed is the one that has been in the queue
for the longest time.  Lists can implement queues, but <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link> is a poor means
of adding elements to the tail.</html:p><html:p>Our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional arrays</fr:link> are suitable, provided we
augment them with a function to delete the first array element.  (See <html:em>ML
  for the Working Programmer</html:em> page 156.)  Each operation would take <fr:tex
display="inline"><![CDATA[O(\log 
n)]]></fr:tex> time for a queue of length <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>We shall describe a representation of queues that is purely functional, based
upon lists, and efficient.  Operations take <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> time when “amortized”:
averaged over the lifetime of a queue.</html:p><html:p>A conventional programming technique is to represent a queue by an array.  Two
indices point to the front and back of the queue, which may wrap around the
end of the array.  The coding is somewhat tricky.  Worse, the length of the
queue must be given a fixed upper bound.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:uri><fr:display-uri>focs-functional-queues-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:route><fr:title
text="Efficient Functional Queues: Idea">Efficient Functional Queues: Idea</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Represent the queue <fr:tex
display="inline"><![CDATA[x_1\; x_2\; \ldots \; x_m\; y_n\; \ldots \; y_1]]></fr:tex> by any <html:em>pair of lists</html:em>
    <fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \; [y_1,y_2,\ldots ,y_n])]]></fr:tex></html:li>
  <html:li>Add new items to the <html:em>rear list</html:em></html:li>
  <html:li>Remove items from <html:em>front list</html:em> and if empty move <html:em>rear</html:em> to <html:em>front</html:em></html:li>
  <html:li><html:em>Amortized</html:em> time per operation is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p>Queues require efficient access at both ends: at the front, for removal, and
at the back, for insertion.  Ideally, access should take constant time,
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.  It may appear that lists cannot provide such access.  If
<html:code>enq(q, x)</html:code> performs <html:code>q@[x]</html:code>, then this operation will be <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  We
could represent queues by reversed lists, implementing <html:code>enq(q, x)</html:code> by
<html:code>x::q</html:code>, but then the <html:code>deq</html:code> and <html:code>qhd</html:code> operations would be
<fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Linear time is intolerable: a series of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> queue operations
could then require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time.</html:p><html:p>The solution is to represent a queue by a pair of lists, where</html:p><fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \, [y_1,y_2,\ldots ,y_n])]]></fr:tex><html:p>represents the queue <fr:tex
display="inline"><![CDATA[x_1 x_2 \ldots  x_m y_n \ldots  y_1]]></fr:tex>.</html:p><html:p>The front part of the queue is stored in order, and the rear part is stored in
reverse order.  The <html:code>enq</html:code> operation adds elements to the rear part
using cons, since this list is reversed; thus, <html:code>enq</html:code> takes constant
time.  The <html:code>deq</html:code> and <html:code>qhd</html:code> operations look at the front part,
which normally takes constant time, since this list is stored in order.  But
sometimes <html:code>deq</html:code> removes the last element from the front part; when this
happens, it reverses the rear part, which becomes the new front part.</html:p><html:p><html:em>Amortized</html:em> time refers to the cost per operation averaged over the
lifetime of any complete execution.  Even for the worst possible execution,
the average cost per operation turns out to be constant; see the analysis
below.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:uri><fr:display-uri>focs-functional-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:route><fr:title
text="Efficient Functional Queues: Code">Efficient Functional Queues: Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a queue =
  | Q of 'a list * 'a list
type 'a queue = Q of 'a list * 'a list
# let norm = function
  | Q ([], tls) -> Q (List.rev tls, [])
  | q -> q
val norm : 'a queue -> 'a queue = <fun>
# let qnull = function
  | Q ([], []) -> true
  | _ -> false
val qnull : 'a queue -> bool = <fun>
# let enq (Q (hds, tls)) x = norm (Q (hds, x::tls))
val enq : 'a queue -> 'a -> 'a queue = <fun>
# exception Empty
exception Empty
# let deq = function
  | Q (x::hds, tls) -> norm (Q (hds, tls))
  | _ -> raise Empty
val deq : 'a queue -> 'a queue = <fun>
# let qempty = Q ([], [])
val qempty : 'a queue = Q ([], [])
# let qhd = function
  | Q (x::_, _) -> x
  | _ -> raise Empty
val qhd : 'a queue -> 'a = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> of queues prevents confusion with other pairs of lists.  The empty
queue has both parts empty.</html:p><html:p>The function <html:code>norm</html:code> puts a queue into normal form, ensuring that the front part
is never empty unless the entire queue is empty.  Functions <html:code>deq</html:code> and <html:code>enq</html:code>
call <html:code>norm</html:code> to normalise their result.</html:p><html:p>Because queues are in normal form, their head is certain to be in their
front part, so <html:code>qhd</html:code> looks there.</html:p><html:p>Let us analyse the cost of an execution comprising (in any possible order) <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
<html:code>enq</html:code> operations and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> <html:code>deq</html:code> operations, starting with an
empty queue.  Each <html:code>enq</html:code> operation will perform one cons, adding an
element to the rear part.  Since the final queue must be empty, each element
of the rear part gets transferred to the front part.  The corresponding
reversals perform one cons per element.  Thus, the total cost of the series of
queue operations is <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> cons operations, an average of 2 per operation.  The
amortized time is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p><html:p>There is a catch.  The conses need not be distributed evenly; reversing a long
list could take up to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> of them.  Unpredictable delays make the approach
unsuitable for <html:em>real-time programming</html:em> where deadlines must be met.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:uri><fr:display-uri>focs-bfs-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Queues">Breadth-First Tree Traversal — Using Queues</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec breadth q =
    if qnull q then []
    else
      match qhd q with
      | Lf -> breadth (deq q)
      | Br (v, t, u) -> v :: breadth (enq (enq (deq q) t) u)
val breadth : 'a tree queue -> 'a list = <fun>]]></html:pre><html:p>This function implements the same algorithm as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-append/"
title="Breadth-First Tree Traversal — Using Append"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/"
display-uri="focs-bfs-append"
type="local"><html:code>nbreadth</html:code></fr:link> but uses a different
data structure.  It represents queues using type <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-queues/"
title="Efficient Functional Queues: Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/"
display-uri="focs-functional-queues"
type="local"><html:code>queue</html:code></fr:link> instead of type
<html:code>list</html:code>.</html:p><html:p>To compare their efficiency, I applied both functions to the full binary tree
of depth 12, which contains 4095 labels.  The function <html:code>nbreadth</html:code> took 30
seconds while <html:code>breadth</html:code> took only 0.15 seconds: faster by a factor of 200.</html:p><html:p>For larger trees, the speedup would be greater.  Choosing the right data
structure pays handsomely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:uri><fr:display-uri>focs-iterative-deepening</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:route><fr:title
text="Iterative deepening: Another Exhaustive Search">Iterative deepening: Another Exhaustive Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Breadth-first search examines <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> nodes:
    <fr:tex
display="block"><![CDATA[1 + b + \cdots  + b^d = {b^{d+1}-1 \over  b-1}
  \qquad  \begin {array}{rl}
            b & {} = \hbox {branching factor}\\
            d & {} = \hbox {depth}
          \end {array}]]></fr:tex></html:li>
  <html:li>Recompute nodes at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> instead of storing them</html:li>
  <html:li>Time factor is <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>; complexity is still <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex></html:li>
  <html:li>Space required at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> drops from <fr:tex
display="inline"><![CDATA[b^d]]></fr:tex> to <fr:tex
display="inline"><![CDATA[d]]></fr:tex></html:li></html:ul><html:p>Breadth-first search is not practical for infinite trees: it uses too much
space. Large parts of the tree have to be stored.
Consider the slightly more general problem of searching trees whose
branching factor is <fr:tex
display="inline"><![CDATA[b]]></fr:tex> (for binary trees, <fr:tex
display="inline"><![CDATA[b=2]]></fr:tex>).  Then breadth-first search
to depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> examines <fr:tex
display="inline"><![CDATA[(b^{d+1}-1)/(b-1)]]></fr:tex> nodes, which is <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>, ignoring
the constant factor of <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex>.  Since all nodes that are examined are also
stored, the space and time requirements are both <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.</html:p><html:p><html:em>Depth-first iterative deepening</html:em> combines the space efficiency of
depth-first with the “nearest-first” property of breadth-first search.  It
performs repeated depth-first searches with increasing depth bounds, each time
discarding the result of the previous search.  Thus it searches to depth 1,
then to depth 2, and so on until it finds a solution.  We can afford to
discard previous results because the number of nodes is growing exponentially.
There are <fr:tex
display="inline"><![CDATA[b^{d+1}]]></fr:tex> nodes at level <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>; if <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex>, this number actually
exceeds the total number of nodes of all previous levels put together, namely
<fr:tex
display="inline"><![CDATA[(b^{d+1}-1) / (b-1)]]></fr:tex>.</html:p><html:p><fr:link
href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.91.288"
type="external">Korf shows</fr:link> that the time needed for iterative deepening to reach
depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> is only <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> times that for breadth-first search, if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>.
This is a constant factor; both algorithms have the same time complexity,
<fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.  In typical applications where <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex> the extra factor of
<fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> is quite tolerable.  The reduction in the space requirement is
exponential, from <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> for breadth-first to <fr:tex
display="inline"><![CDATA[O(d)]]></fr:tex> for iterative
deepening. Of course, this assumes that the tree itself is not stored in memory.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-stacks/</fr:uri><fr:display-uri>focs-stacks</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-stacks/</fr:route><fr:title
text="Another Abstract Data Type: Stacks">Another Abstract Data Type: Stacks</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><html:code>empty</html:code> is the <html:em>empty stack</html:em></html:li>
  <html:li><html:code>null</html:code> tests whether a stack is empty</html:li>
  <html:li><html:code>top</html:code> returns the element at the <html:em>top</html:em> of a stack</html:li>
  <html:li><html:code>pop</html:code> discards the element at the <html:em>top</html:em> of a stack</html:li>
  <html:li><html:code>push</html:code> adds an element at the <html:em>top</html:em> of a stack</html:li></html:ul><html:p>A <html:em>stack</html:em> is a sequence such that items can be added or removed from the head
only.  A stack obeys a Last-In-First-Out (LIFO) discipline: the item next to be
removed is the one that has been on the stack for the <html:em>shortest</html:em> time.  Lists
can easily implement stacks because both <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local"><html:code>hd</html:code></fr:link> affect the head.  But
unlike lists, stacks are often regarded as an imperative data structure: the
effect of <html:code>push</html:code> or <html:code>pop</html:code> is to change an existing stack, not return a new one.</html:p><html:p>In conventional programming languages, a stack is often implemented by storing
the elements in an array, using a variable (the “stack pointer”) to count them.
Most language processors keep track of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function calls</fr:link> using an
internal stack.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:uri><fr:display-uri>focs-search-methods</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:route><fr:title
text="A Survey of Search Methods">A Survey of Search Methods</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Depth-first: use a <html:em>stack</html:em>  (efficient but incomplete)</html:li>
  <html:li>Breadth-first: use a <html:em>queue</html:em> (uses too much space!)</html:li>
  <html:li>Iterative deepening: use depth-first to get benefits of breadth-first (trades time for space)</html:li>
  <html:li>Best-first: use a <html:em>priority queue</html:em> (heuristic search)</html:li></html:ul><html:p>The data structure determines the search!</html:p><html:p>Search procedures can be classified by the data structure used to store
pending subtrees.  Depth-first search stores them on a stack, which is
implicit in functions like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link>, but can be made explicit.
Breadth-first search stores such nodes in a queue.</html:p><html:p>An important variation is to store the nodes in a priority queue, which
is an ordered sequence.  The priority queue applies some sort of ranking
function to the nodes, placing higher-ranked nodes before lower-ranked ones.
The ranking function typically estimates the distance from the node to a
solution.  If the estimate is good, the solution is located swiftly.  This
method is called best-first search.</html:p><html:p>The priority queue can be kept as a sorted list, although this is slow.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary search trees</fr:link> would be much better on average, and fancier data
structures improve matters further.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/</fr:uri><fr:display-uri>focs-ex-10</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:uri><fr:display-uri>focs-ex-10-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:route><fr:title
text="Tree-based queues">Tree-based queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Suppose that we have an implementation of queues, based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>, such that each operation
takes logarithmic time in the worst case. Outline the advantages and drawbacks of such an
implementation compared with one presented above.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:uri><fr:display-uri>focs-ex-10-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:route><fr:title
text="Array-based circular queues">Array-based circular queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The traditional way to implement queues uses a fixed-length array. Two indices into the array
indicate the start and end of the queue, which wraps around from the end of the array to the start.
How appropriate is such a data structure for implementing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
title="Breadth-First v Depth-First Tree Traversal"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
display-uri="focs-bfs-dfs"
type="local">breadth-first search</fr:link>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:uri><fr:display-uri>focs-ex-10-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:route><fr:title
text="Rewriting breadth with let">Rewriting breadth with let</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
title="Breadth-First Tree Traversal — Using Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
display-uri="focs-bfs-queues"
type="local"><html:code>breadth</html:code></fr:link> using a nested <html:code>let</html:code> construction rather than
<html:code>match</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:uri><fr:display-uri>focs-ex-10-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:route><fr:title
text="Search with a branching factor near one">Search with a branching factor near one</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
title="Iterative deepening: Another Exhaustive Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
display-uri="focs-iterative-deepening"
type="local">Iterative deepening</fr:link> is inappropriate if <fr:tex
display="inline"><![CDATA[b\approx 1]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[b]]></fr:tex> is the branching factor. What search
strategy is appropriate in this case?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:uri><fr:display-uri>focs-ex-10-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:route><fr:title
text="An implicit infinite tree">An implicit infinite tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the following OCaml function.</html:p><html:pre><![CDATA[let next n = [2 * n; 2 * n + 1]]]></html:pre><html:p>If we regard it as representing a tree, where the subtrees are computed from the current label, what
tree does <html:code>next 1</html:code> represent?</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/</fr:uri><fr:display-uri>focs-procedural</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-procedural/</fr:route><fr:title
text="Elements of Procedural Programming">Elements of Procedural Programming</fr:title><fr:taxon>Lecture</fr:taxon><fr:meta
name="external">https://hub.cl.cam.ac.uk/</fr:meta></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural-programming/</fr:uri><fr:display-uri>focs-procedural-programming</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-procedural-programming/</fr:route><fr:title
text="Procedural Programming">Procedural Programming</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Procedural programs can change the machine state.</html:li>
  <html:li>They can interact with its environment</html:li>
  <html:li>They use control structures like branching, iteration and procedures.</html:li></html:ul><html:p>They use data abstractions of the computer’s memory:</html:p><html:ul><html:li><html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link></html:em> to memory cells</html:li>
  <html:li><html:em>arrays</html:em> that are blocks of memory cells</html:li>
  <html:li><html:em>linked structures</html:em> such as <html:em>linked lists</html:em></html:li></html:ul><html:p>Procedural programming is programming in the traditional sense of the word.  A
program <html:em>state</html:em> is repeatedly transformed by the execution of
<html:em>commands</html:em> or <html:em>statements</html:em>.  A state change might be local to the
machine and consist of updating a variable or array.  A state change might
consist of sending data to the outside world.  Even reading data counts as a
state change, since this act normally removes the data from the environment.</html:p><html:p>Procedural programming languages provide primitive commands and control
structures for combining them.  The primitive commands include
<html:em>assignment</html:em> for updating variables, and various <html:em>input/output</html:em>
commands for communication.  Control structures include <html:code>if</html:code> and
<html:code>match</html:code> constructs for conditional execution, and repetitive constructs
such as <html:code>while</html:code>.  Programmers can package up their own commands as
<html:em>procedures</html:em> taking arguments.  The need for such “subroutines” was
evident from the earliest days; they represent one of the first
examples of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstraction</fr:link> in programming languages.</html:p><html:p>OCaml makes no distinction between commands and expressions. OCaml provides built-in
‘functions’ to perform assignment and communication, and these can be used
in the traditional (procedural) style. OCaml programmers often follow a
functional style for most internal computations and use imperative features
mainly for communication with the outside world.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/</fr:uri><fr:display-uri>focs-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references/</fr:route><fr:title
text="OCaml Primitives for References">OCaml Primitives for References</fr:title></fr:frontmatter><fr:mainmatter><html:table>
  <html:tr><html:th>Syntax</html:th><html:th>Effect</html:th></html:tr>
  <html:tr><html:td><html:code>ref E</html:code></html:td><html:td><html:em>create</html:em> a reference with <html:em>initial contents</html:em> = value of <html:code>E</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>!P</html:code></html:td><html:td>return <html:em>current contents</html:em> of reference <html:code>P</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>P := E</html:code></html:td><html:td><html:em>update</html:em> contents of <html:code>P</html:code> to value of <html:code>E</html:code></html:td></html:tr>
</html:table><html:p>The above text presents the OCaml primitives, but most languages have analogues of
them, often heavily disguised.  We need a means of creating references (or
allocating storage), getting at the current contents of a reference cell, and
updating that cell.</html:p><html:p>The function <html:code>ref</html:code> creates references (also called
“locations”).  Calling <html:code>ref</html:code> allocates a new location in memory.
Initially, this location holds the value given by
expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p><html:p>The function <html:code>!</html:code>, when applied to a reference, returns its contents.
This operation is called <html:em>dereferencing</html:em>.  Clearly <html:code>!</html:code> is not a
mathematical function; its result depends upon the store.</html:p><html:p>The assignment <html:code>P:=E</html:code> evaluates expression <fr:tex
display="inline"><![CDATA[P]]></fr:tex>, which must return a
reference <fr:tex
display="inline"><![CDATA[p]]></fr:tex>, and <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.  It stores at address <fr:tex
display="inline"><![CDATA[p]]></fr:tex> the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.
Syntactically, <html:code>:=</html:code> is a function and <html:code>P:=E</html:code> is an
expression, even though it updates the store.  Like many functions that change
the state, it returns the value <html:code>()</html:code> of type <html:code>unit</html:code>.</html:p><html:p>If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is some OCaml type, then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>ref</html:code> is the type of references
to cells that can hold values of <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.  Please do not confuse the type
<html:code>ref</html:code> with the function <html:code>ref</html:code>.  This table of the primitive
functions and their types might be useful:</html:p><html:table>
  <html:tr><html:th>Syntax</html:th><html:th>OCaml Type</html:th></html:tr>
  <html:tr><html:td><html:code>ref</html:code></html:td><html:td><html:code>'a -&gt; 'a ref</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>!</html:code></html:td><html:td><html:code>'a ref -&gt; 'a</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>:=</html:code></html:td><html:td><html:code>'a ref -&gt; 'a -&gt; unit</html:code></html:td></html:tr>
</html:table></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-examples/</fr:uri><fr:display-uri>focs-references-examples</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-examples/</fr:route><fr:title
text="Trying Out References">Trying Out References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let p = ref 5 (* create a reference *)
val p : int ref = {contents = 5}
# p := !p + 1   (* p now holds value 6 *)
- : unit = ()
# let ps = [ ref 77; p ]
val ps : int ref list = [{contents = 77}; {contents = 6}]
# List.hd ps := 3
- : unit = ()
# ps
- : int ref list = [{contents = 3}; {contents = 6}]]]></html:pre><html:p>The first line declares <html:code>p</html:code> to hold a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference</fr:link> to an integer,
initially 5.  Its type is <html:code>int ref</html:code>, not just <html:code>int</html:code>, so it
admits assignment.  Assignment never changes <html:code>let</html:code> bindings: they are
<html:em>immutable</html:em>.  The identifier <html:code>p</html:code> will always denote the reference
mentioned in its declaration unless superseded by a new usage of <html:code>p</html:code>.
Only the <html:em>contents</html:em> of the reference is mutable.</html:p><html:p>OCaml displays a reference value as <html:code><![CDATA[{contents=v}]]></html:code>, where value <fr:tex
display="inline"><![CDATA[v]]></fr:tex> is the
contents.  This notation is readable but gives us no way of telling whether
two references holding the same value are actually the same reference.  To
display a reference as a machine address has obvious drawbacks!</html:p><html:p>In the first assignment, the expression <html:code>!p</html:code> yields the reference’s
current contents, namely 5.  The assignment changes the contents of <html:code>p</html:code>
to 6.  Most languages do not have an explicit dereferencing operator
(like <html:code>!</html:code>) because of its inconvenience.  Instead, by convention,
occurrences of the reference on the <html:em>left-hand</html:em> side of the <html:code>:=</html:code>
denote locations and those on the <html:em>right-hand</html:em> side denote the contents.
A special ‘address of’ operator may be available to override the convention
and make a reference on the right-hand side to denote a location.  Logically
this is a mess, but it makes programs shorter.</html:p><html:p>The list <html:code>ps</html:code> is declared to hold a new reference (initially
containing 77) as well as <html:code>p</html:code>.  Then the new reference is
updated to hold 3.  The assignment to <html:code>hd ps</html:code> does <html:em>not</html:em>
update <html:code>ps</html:code>, only the contents of a reference in that list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-commands/</fr:uri><fr:display-uri>focs-commands</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-commands/</fr:route><fr:title
text="Commands: Expressions with Effects">Commands: Expressions with Effects</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Basic commands update <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link>, write to files, etc.</html:li>
  <html:li><fr:tex
display="inline"><![CDATA[C_1 ; \ldots  ; C_n]]></fr:tex> causes a series of expressions to be evaluated and returns the value of <fr:tex
display="inline"><![CDATA[C_n]]></fr:tex>.</html:li>
  <html:li>A typical command returns the empty tuple: <html:code>()</html:code></html:li>
  <html:li><html:code>if</html:code> <fr:tex
display="inline"><![CDATA[B]]></fr:tex> <html:code>then</html:code> <fr:tex
display="inline"><![CDATA[C_1]]></fr:tex> <html:code>else</html:code> <fr:tex
display="inline"><![CDATA[C_2]]></fr:tex> behaves like the traditional control structure if <fr:tex
display="inline"><![CDATA[C_1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[C_2]]></fr:tex> have effects.</html:li>
  <html:li>Other OCaml constructs behave naturally with commands, including <html:code>match</html:code> expressions and recursive functions.</html:li></html:ul><html:p>We use the term <html:em>command</html:em> informally to refer to an expression that has an
effect on the state. All expressions denote some value, but they can return
<html:code>()</html:code>, which conveys no actual information.</html:p><html:p>We need a way to execute one command after another.
The construct <fr:tex
display="inline"><![CDATA[C_1 ; \ldots  ; C_n]]></fr:tex> evaluates the expressions <fr:tex
display="inline"><![CDATA[C_1]]></fr:tex>
to <fr:tex
display="inline"><![CDATA[C_n]]></fr:tex> in the order given and returns the value of <fr:tex
display="inline"><![CDATA[C_n]]></fr:tex>.  The values
of the other expressions are discarded; their only purpose is to change the
state.</html:p><html:p>Commands may be used with <html:code>if</html:code> and <html:code>match</html:code> much as in conventional languages.
OCaml functions play the role of procedures.</html:p><html:p>Other languages that combine the functional and imperative programming
paradigms include Lisp (and its dialect Scheme), F#, Scala, Swift and Kotlin.
Rust is a notable modern example: a systems programming language whose type
system and pattern matching draw heavily on the ML family (its first compiler
was written in OCaml), yet which gives the programmer precise control over
mutable state.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/</fr:uri><fr:display-uri>focs-while</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-while/</fr:route><fr:title
text="Iteration: the while command">Iteration: the while command</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let tlopt = function
  | [] -> None
  | _::xs -> Some xs
val tlopt : 'a list -> 'a list option = <fun>
# let length xs =
    let lp  = ref xs in (* list of uncounted elements *)
    let np  = ref 0  in (* accumulated count *)
    let fin = ref false in
    while not !fin do
      match tlopt !lp with
      | None -> fin := true
      | Some xs ->
          lp := xs;
          np := 1 + !np
    done;
    !np (* the final count is returned *)
val length : 'a list -> int = <fun>]]></html:pre><html:p>Once we can change the state, we need to do so repeatedly.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">Recursion</fr:link> can
serve this purpose, but having to declare a procedure for every loop is
clumsy, and compilers for conventional languages seldom exploit
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
title="Recursion vs Iteration"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
display-uri="focs-recursion-vs-iteration"
type="local">tail-recursion</fr:link>.</html:p><html:p>Early programming languages provided little support for repetition.  The
programmer had to set up loops using goto commands, exiting the loop using
another goto controlled by an <html:code>if</html:code>.  Modern languages provide a
confusing jumble of looping constructs, the most fundamental of which is
<html:code>while B do C</html:code>.  The boolean expression <fr:tex
display="inline"><![CDATA[B]]></fr:tex> is evaluated,
and if true, command <fr:tex
display="inline"><![CDATA[C]]></fr:tex> is executed and the command repeats.  If <fr:tex
display="inline"><![CDATA[B]]></fr:tex>
evaluates to false then the <html:code>while</html:code> command terminates, perhaps without
executing <fr:tex
display="inline"><![CDATA[C]]></fr:tex> even once.</html:p><html:p>OCaml’s main looping construct is <html:code>while</html:code>, which returns the value <html:code>()</html:code>.  The
function <html:code>length</html:code> declares <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> to hold the list under
examination (<html:code>lp</html:code>) and number of elements counted so far (<html:code>np</html:code>) as well
as whether the end of the list has been reached (the boolean reference <html:code>fin</html:code>).
While the list is non-empty, we skip over one more element (by setting it to
its tail) and count that element.</html:p><html:p>The body of the <html:code>while</html:code> loop first checks to see if the end of the list has
been reached, in which case it sets the <html:code>fin</html:code> variable to true.  If there is a
tail value, then two assignments are executed in sequence.  The <html:code>lp</html:code> reference
is set to the tail of the list, and the <html:code>np</html:code> reference integer is incremented
by one.  When the while loop terminates due to the <html:code>fin</html:code> variable being set to
true, the expression <html:code>!np</html:code> returns the computed length as the function’s
result.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/</fr:uri><fr:display-uri>focs-private-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-private-references/</fr:route><fr:title
text="Private, Persistent References">Private, Persistent References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception TooMuch of int
exception TooMuch of int
# let makeAccount initBalance =
    let balance = ref initBalance in
    let withdraw amt =
       if amt > !balance then
         raise (TooMuch (amt - !balance))
       else begin
         balance := !balance - amt;
         !balance
       end
    in
    withdraw
val makeAccount : int -> int -> int = <fun>]]></html:pre><html:p>As you may have noticed, OCaml’s programming style looks clumsy compared with
that of languages like C.  OCaml omits the defaults and abbreviations they
provide to shorten programs.  However, OCaml’s explicitness makes it ideal for
teaching the fine points of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> and arrays.  OCaml’s references are more
flexible than those found in other languages.</html:p><html:p>The function <html:code>makeAccount</html:code> models a bank.  Calling the function with a
specified initial balance creates a new reference (<html:code>balance</html:code>) to
maintain the account balance and returns a function (<html:code>withdraw</html:code>) having
sole access to that reference.  Calling <html:code>withdraw</html:code> reduces the balance
by the specified amount and returns the new balance.  You can pay money in by
withdrawing a negative amount.  The <html:code>if</html:code>-construct prevents the account
from going overdrawn, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">raising an exception</fr:link>.</html:p><html:p>Look at the <fr:tex
display="inline"><![CDATA[E_1; E_2]]></fr:tex> sequence inside <html:code>begin</html:code> … <html:code>end</html:code> in the <html:em>else</html:em> part above.
The first expression updates the account balance and returns the trivial
value ().  The second expression, <html:code>!balance</html:code>, returns the current
balance but does not return the reference itself: that would allow
unauthorised updates.</html:p><html:p>This example is based on one by Dr A C Norman.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bank-accounts/</fr:uri><fr:display-uri>focs-bank-accounts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bank-accounts/</fr:route><fr:title
text="Two Bank Accounts">Two Bank Accounts</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let student = makeAccount 500
val student : int -> int = <fun>
# let director = makeAccount 4000000
val director : int -> int = <fun>
# student 5        (* coach fare *)
- : int = 495
# director 150000  (* Tesla *)
- : int = 3850000
# student 500      (* oh oh *)
Exception: TooMuch 5.]]></html:pre><html:p>Each call to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>makeAccount</html:code></fr:link> returns a copy of <html:code>withdraw</html:code> holding
a <html:em>fresh</html:em> instance of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference</fr:link> <html:code>balance</html:code>.  As with a real bank
pass-book, there is no access to the account balance except via the
corresponding <html:code>withdraw</html:code> function.  If that function is discarded, the
reference cell becomes unreachable; the computer will eventually reclaim it,
just as banks close down dormant accounts.</html:p><html:p>Here we see two people managing their accounts.  For better or worse, neither
can take money from the other.</html:p><html:p>We could generalise <html:code>makeAccount</html:code> to return several functions that
jointly manage information held in shared references.  The functions might be
packaged using OCaml records, which are not discussed in this course.
Most procedural languages do not properly support the concept of private
references, although <html:em>object-oriented</html:em> languages take them as a basic theme.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/</fr:uri><fr:display-uri>focs-array-primitives</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-array-primitives/</fr:route><fr:title
text="OCaml Primitives for Arrays">OCaml Primitives for Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# [|"a"; "b"; "c"|] (* allocate a fresh string array *)
- : string array = [|"a"; "b"; "c"|]
# Array.make 3 'a'   (* array[3] with cell containing 'a' *)
- : char array = [|'a'; 'a'; 'a'|]
# let aa = Array.init 5 (fun i -> i * 10) (* array[5] initialised to (fun i) *)
val aa : int array = [|0; 10; 20; 30; 40|]
# Array.get aa 3  (* retrieve the 4th cell in the array *)
- : int = 30
# Array.set aa 3 42 (* set the 4th cell's value to 42 *)
- : unit = ()]]></html:pre><html:p>There are many other array operations in the <html:code>Array</html:code> module in the OCaml standard
library.</html:p><html:pre><![CDATA[# Array.make
- : int -> 'a -> 'a array = <fun>
# Array.init
- : int -> (int -> 'a) -> 'a array = <fun>
# Array.get
- : 'a array -> int -> 'a = <fun>
# Array.set
- : 'a array -> int -> 'a -> unit = <fun>]]></html:pre><html:p>OCaml arrays are like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> that hold several elements instead of one.  The
elements of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element array are designated by the integers from 0
to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex>.  The <fr:tex
display="inline"><![CDATA[i]]></fr:tex>th array element is usually written <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex>.
If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is a type then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>array</html:code> is the
type of arrays (of any size) with elements from <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.</html:p><html:p>Calling <html:code>Array.init n f</html:code> creates an array of the size specified in <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
by function <fr:tex
display="inline"><![CDATA[f]]></fr:tex>.  Initially, element <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex> holds the value of <fr:tex
display="inline"><![CDATA[f(i)]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex>.
Like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local"><html:code>ref</html:code></fr:link>, it allocates mutable storage to hold the specified values.</html:p><html:p>Calling <html:code>Array.get A i</html:code> returns the contents of <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex>.</html:p><html:p>Calling <html:code>Array.set A i E</html:code> modifies the array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by storing the
value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as the new contents of <fr:tex
display="inline"><![CDATA[A[i]]]></fr:tex>; it returns <html:code>()</html:code> as its value.</html:p><html:p>OCaml’s arrays are much safer than C’s. In C, an array is nothing more than an
address indicating the start of a storage area. Nothing indicates the size of
the area.  Therefore C programs are vulnerable to <html:em>buffer overrun attacks:</html:em> an
attacker sends more data than the receiving program expects, overrunning the
area of storage set aside to hold it. The attack eventually overwrites the
program itself, replacing it with code controlled by the attacker.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-examples/</fr:uri><fr:display-uri>focs-array-examples</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-array-examples/</fr:route><fr:title
text="Array Examples">Array Examples</fr:title></fr:frontmatter><fr:mainmatter><html:p>In the following session, the identifier <html:code>ar</html:code> is bound to an array of 20 elements, which
are initially set to the squares of their subscripts.  The array’s third
element (which actually has subscript 2) is inspected and found to be four. The
second call to <html:code>Array.get</html:code> supplies a subscript that is out of range, so OCaml
rejects it.</html:p><html:pre><![CDATA[# let ar = Array.init 20 (fun i -> i * i)
val ar : int array =
  [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81; 100; 121; 144; 169; 196; 225; 256;
    289; 324; 361|]
# Array.get ar 2
- : int = 4
# Array.get ar 20
Exception: Invalid_argument "index out of bounds".
# Array.set ar 2 33; ar
- : int array =
[|0; 1; 33; 9; 16; 25; 36; 49; 64; 81; 100; 121; 144; 169; 196; 225; 256;
  289; 324; 361|]]]></html:pre><html:p>By calling <html:code>Array.set</html:code>, we then modify the element with subscript 2. Note
however that we cannot modify the array’s length. If we outgrow the array, we
have to create a new one, copy the data into it, and then forget the old array.
Typically the new array would be double the size of the old one, so that the
cost of copying is insignificant.</html:p><html:p>OCaml provides numerous operators for modifying, computing over and searching in
arrays. Many are analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">functions on lists</fr:link>. For example,
<html:code>Array.exists</html:code> takes a boolean-valued function and returns <html:code>true</html:code> if an
array element satisfies it.</html:p><html:pre><![CDATA[# Array.exists (fun i -> i > 200) ar
- : bool = true
# Array.exists (fun i -> i < 0) ar
- : bool = false]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:uri><fr:display-uri>focs-references-comparison</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:route><fr:title
text="References: OCaml vs conventional languages">References: OCaml vs conventional languages</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>We must write <html:code>!p</html:code> to get the <html:em>contents</html:em> of <html:code>p</html:code></html:li>
  <html:li>We write just <html:code>p</html:code> for the <html:em>address</html:em> of <html:code>p</html:code></html:li>
  <html:li>We can store private <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference cells</fr:link> (like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>balance</html:code></fr:link>) in functions—analogous to elements of <html:em>object-oriented programming</html:em></html:li>
  <html:li>OCaml’s assignment syntax is <fr:tex
display="inline"><![CDATA[\tt  V \, := \, E]]></fr:tex> instead of <fr:tex
display="inline"><![CDATA[V]]></fr:tex> = <fr:tex
display="inline"><![CDATA[E]]></fr:tex></html:li>
  <html:li>OCaml has few control structures: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-while/"
title="Iteration: the while command"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/"
display-uri="focs-while"
type="local"><html:code>while</html:code></fr:link>, <html:code>match</html:code>, <html:code>if</html:code> and <html:code>for</html:code> (the latter is not covered in this course)</html:li>
  <html:li>OCaml has syntax for updating an array via the <html:code>a.(i) &lt;- v</html:code> syntax which is the same as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-array-primitives/"
title="OCaml Primitives for Arrays"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/"
display-uri="focs-array-primitives"
type="local"><html:code>Array.set a i v</html:code></fr:link>.</html:li></html:ul><html:p>Conventional syntax for variables and assignments has hardly changed since
Fortran, the first high-level language. In conventional languages,
virtually all variables can be updated.  We declare something like
<html:code>p: int</html:code>, mentioning no reference type even if the language provides
them.  If we do not specify an initial value, we may get whatever bits were
previously at that address.  Illegal values arising from uninitialised
variables can cause errors that are almost impossible to diagnose.</html:p><html:p>Dereferencing operators (like OCaml’s <html:code>!</html:code>) are especially unpopular, because
they clutter the program text. Virtually all programming languages make dereferencing
implicit (that is, automatic).</html:p><html:p>It is generally accepted these days that a two-dimensional array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> is nothing
but an array of arrays.  An assignment to such an array is typically written
something like <fr:tex
display="inline"><![CDATA[A[i,j] {:=} x]]></fr:tex>; in C, the syntax is <html:code>A[i][j] = x</html:code>. Higher
dimensions are treated analogously.  The corresponding OCaml code can either
declare an array of arrays, or use the <html:code>A.(i)</html:code> syntax to calculate the linear
offset into a single array.</html:p><html:p>You can use the constructs we have learnt to easily create linked (mutable) lists as
an alternative to arrays.</html:p><html:pre><![CDATA[# type 'a mlist =
  | Nil
  | Cons of 'a * 'a mlist ref
type 'a mlist = Nil | Cons of 'a * 'a mlist ref]]></html:pre><html:p>It is worth mentioning that OCaml’s references fully suffice for coding the sort of linked data structures
taught in algorithms courses, as the <html:code>mlist</html:code> type above illustrates. The
programming style is a little different from the usual, but the principles are
the same.  OCaml also provides comprehensive input/output primitives for various
types of file and operating system.</html:p><html:p>OCaml’s system of modules include <html:em>structures,</html:em> which can be seen as encapsulated
groups of declarations, and <html:em>signatures,</html:em> which are specifications of
structures listing the name and type of each component.  Finally, there are
<html:em>functors,</html:em> which are analogous to functions that combine a number of argument
structures, and which can be used to plug program components together. These
primitives are useful for managing large programming projects.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
expanded="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/</fr:uri><fr:display-uri>focs-ex-11</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11/</fr:route><fr:title
text="Exercises">Exercises</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:uri><fr:display-uri>focs-ex-11-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:route><fr:title
text="Lists of references">Lists of references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Comment, with examples, on the differences between an <html:code>int ref list</html:code> and an <html:code>int list ref</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:uri><fr:display-uri>focs-ex-11-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:route><fr:title
text="Iterative power with while">Iterative power with while</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of function <html:code>power</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-intro/"
title="Introduction to Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro"
type="local">Lecture <fr:contextual-number
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro" /></fr:link>) using <html:code>while</html:code> instead of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-3/</fr:uri><fr:display-uri>focs-ex-11-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-3/</fr:route><fr:title
text="Effects in a while condition">Effects in a while condition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What is the effect of <fr:tex
display="inline"><![CDATA[\tt  while \, C_1; \; B \, do \, C_2 \, done]]></fr:tex> ?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-4/</fr:uri><fr:display-uri>focs-ex-11-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-4/</fr:route><fr:title
text="Exchanging two references">Exchanging two references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to exchange the values of two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link>, <html:code>xr</html:code> and <html:code>yr</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
toc="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:uri><fr:display-uri>focs-ex-11-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:route><fr:title
text="Matrix operations on arrays">Matrix operations on arrays</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Arrays of multiple dimensions are represented in OCaml by arrays of arrays. Write functions to
(a) create an <fr:tex
display="inline"><![CDATA[n\times  n]]></fr:tex> identity matrix, given <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, and
(b) to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local">transpose</fr:link> an <fr:tex
display="inline"><![CDATA[m\times  n]]></fr:tex> matrix. Identity matrices have the following form:</html:p><fr:tex
display="block"><![CDATA[
\left ( {
\begin {array}{cccc}
   1 & 0 &  \cdots   & 0  \\
   0 & 1 &  \cdots   & 0  \\
    \vdots   &  \vdots   &  \ddots   &  \vdots    \\
   0 & 0 &  \cdots   & 1  \\
 \end {array}
 } \right )
]]></fr:tex></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter><fr:backmatter><fr:tree
show-metadata="false"
hidden-when-empty="true"><fr:frontmatter><fr:authors /><fr:title
text="References">References</fr:title></fr:frontmatter><fr:mainmatter /></fr:tree><fr:tree
show-metadata="false"
hidden-when-empty="true"><fr:frontmatter><fr:authors /><fr:title
text="Context">Context</fr:title></fr:frontmatter><fr:mainmatter /></fr:tree><fr:tree
show-metadata="false"
hidden-when-empty="true"><fr:frontmatter><fr:authors /><fr:title
text="Backlinks">Backlinks</fr:title></fr:frontmatter><fr:mainmatter /></fr:tree><fr:tree
show-metadata="false"
hidden-when-empty="true"><fr:frontmatter><fr:authors /><fr:title
text="Related">Related</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-all-exercises/</fr:uri><fr:display-uri>focs-all-exercises</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-all-exercises/</fr:route><fr:title
text="All exercises">All exercises</fr:title></fr:frontmatter><fr:mainmatter><html:p>Every exercise in the course, collected automatically from the lecture notes.</html:p><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:uri><fr:display-uri>focs-ex-8-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:route><fr:title
text="Exercises › A map for options"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › A map for options</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The type <html:code>'a option</html:code>, declared below, can be viewed as a type of lists having at most one element.
(It is typically used as an alternative to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">exceptions</fr:link>.) Declare an analogue of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>
for type <html:code>'a option</html:code>.</html:p><html:pre><![CDATA[type 'a option = None | Some of 'a]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:uri><fr:display-uri>focs-ex-9-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:route><fr:title
text="Exercises › A map for sequences"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › A map for sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an analogue of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> for sequences.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:uri><fr:display-uri>focs-ex-4-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:route><fr:title
text="Exercises › A non-exhaustive zip"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › A non-exhaustive zip</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>How does this version of <html:code>zip</html:code> differ from <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local">the one above</fr:link>?</html:p><html:pre><![CDATA[let rec zip xs ys =
  match xs, ys with
  | (x::xs, y::ys) -> (x, y) :: zip xs ys
  | ([], [])   -> []]]></html:pre><html:pre><![CDATA[Lines 2-4, characters 5-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(x::xs, [])]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:uri><fr:display-uri>focs-ex-2-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:route><fr:title
text="Exercises › A tighter recurrence bound"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › A tighter recurrence bound</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Find an upper bound for the recurrence given by <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+1]]></fr:tex>.  You should be
able to find a tighter bound than <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:uri><fr:display-uri>focs-ex-6-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:route><fr:title
text="Exercises › A type for arithmetic expressions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › A type for arithmetic expressions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for arithmetic expressions that have the following
possibilities: floating-point numbers, variables (represented by strings), or expressions of the form <fr:tex
display="inline"><![CDATA[-E]]></fr:tex>,
<fr:tex
display="inline"><![CDATA[E+E]]></fr:tex>, <fr:tex
display="inline"><![CDATA[E\times  E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:uri><fr:display-uri>focs-ex-9-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:route><fr:title
text="Exercises › All lists of zeroes and ones"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › All lists of zeroes and ones</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the lazy list whose elements are all ordinary lists of zeroes and ones, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 1]; [1; 0]; [1; 1]; [0; 0; 0]; </html:code>….  (Taken from the exam question
2003 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:uri><fr:display-uri>focs-ex-10-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:route><fr:title
text="Exercises › An implicit infinite tree"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › An implicit infinite tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the following OCaml function.</html:p><html:pre><![CDATA[let next n = [2 * n; 2 * n + 1]]]></html:pre><html:p>If we regard it as representing a tree, where the subtrees are computed from the current label, what
tree does <html:code>next 1</html:code> represent?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:uri><fr:display-uri>focs-ex-10-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:route><fr:title
text="Exercises › Array-based circular queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Array-based circular queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The traditional way to implement queues uses a fixed-length array. Two indices into the array
indicate the start and end of the queue, which wraps around from the end of the array to the start.
How appropriate is such a data structure for implementing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
title="Breadth-First v Depth-First Tree Traversal"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
display-uri="focs-bfs-dfs"
type="local">breadth-first search</fr:link>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:uri><fr:display-uri>focs-ex-4-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:route><fr:title
text="Exercises › Assumptions in making change"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Assumptions in making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What assumptions do the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">‘making change’</fr:link> functions make about the variables <html:code>till</html:code> and <html:code>amt</html:code>?
Describe what could happen if these assumptions were violated.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-2/</fr:uri><fr:display-uri>focs-ex-1-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-2/</fr:route><fr:title
text="Exercises › Comparing and adding years"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Comparing and adding years</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the date representation of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1-1/"
title="Exercises › Two-digit year windowing"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-1/"
display-uri="focs-ex-1-1"
type="local">the previous exercise</fr:link>, code OCaml functions to (a) compare two
years (b) add/subtract some given number of years from another year.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:uri><fr:display-uri>focs-ex-5-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:route><fr:title
text="Exercises › Complexity of bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Complexity of bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (bubble sort) consists of looking at adjacent pairs of elements,
exchanging them if they are out of order and repeating this process until no more exchanges are
possible. State, with justification, the time complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:uri><fr:display-uri>focs-ex-5-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:route><fr:title
text="Exercises › Complexity of selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Complexity of selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (selection sort) consists of looking at the elements to be sorted,
identifying and removing a minimal element, which is placed at the head of the result. The tail is
obtained by recursively sorting the remaining elements. State, with justification, the time
complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:uri><fr:display-uri>focs-ex-9-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:route><fr:title
text="Exercises › Concatenating infinite sequences"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Concatenating infinite sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the list function <html:code>concat</html:code>, which concatenates a list of lists to form a single list. Can
it be generalised to concatenate a sequence of sequences? What can go wrong?</html:p><html:pre><![CDATA[let rec concat = function
| [] -> []
| l::ls -> l @ concat ls]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:uri><fr:display-uri>focs-ex-4-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:route><fr:title
text="Exercises › Counting ways of making change"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Counting ways of making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the number of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">ways of making change</fr:link> for <fr:tex
display="inline"><![CDATA[n]]></fr:tex> (ignoring order) is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> if there are two
legal coin values. What if there are three, four, … coin values?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:uri><fr:display-uri>focs-ex-6-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:route><fr:title
text="Exercises › Days of the week type"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Days of the week type</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for the days of the week. Comment on the practicality of such
a type in a calendar application.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:uri><fr:display-uri>focs-ex-7-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:route><fr:title
text="Exercises › Deleting from a search tree"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Deleting from a search tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Describe an algorithm for deleting an entry from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>. Comment on the suitability of
your approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-3/</fr:uri><fr:display-uri>focs-ex-11-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-3/</fr:route><fr:title
text="Exercises › Effects in a while condition"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Effects in a while condition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What is the effect of <fr:tex
display="inline"><![CDATA[\tt  while \, C_1; \; B \, do \, C_2 \, done]]></fr:tex> ?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:uri><fr:display-uri>focs-ex-9-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:route><fr:title
text="Exercises › Enumerating palindromes"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Enumerating palindromes</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>(Continuing the previous exercise.)
A <html:em>palindrome</html:em> is a list that equals its own reverse. Code the lazy list whose elements are all
palindromes of 0s and 1s, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 0; 0]; [0; 1; 0]; [1; 1]; [1; 0; 1]; [1; 1; 1]; [0; 0; 0; 0]; </html:code>, …. You
may take the reversal function <html:code>List.rev</html:code> as given.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:uri><fr:display-uri>focs-ex-6-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:route><fr:title
text="Exercises › Evaluating expressions with exceptions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Evaluating expressions with exceptions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, write a function that evaluates an expression. If the expression
contains any variables, your function should raise an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> indicating the variable name.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:uri><fr:display-uri>focs-ex-3-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:route><fr:title
text="Exercises › Even-numbered elements"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Even-numbered elements</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the list consisting of the even-numbered elements of the list given as its
argument. For example, given <html:code>[a; b; c; d]</html:code> it should return <html:code>[b; d]</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-4/</fr:uri><fr:display-uri>focs-ex-11-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-4/</fr:route><fr:title
text="Exercises › Exchanging two references"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Exchanging two references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to exchange the values of two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link>, <html:code>xr</html:code> and <html:code>yr</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-2/</fr:uri><fr:display-uri>focs-ex-2-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-2/</fr:route><fr:title
text="Exercises › Extending the complexity table"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › Extending the complexity table</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Add a column to the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sillysum/"
title="Silly Summing the First n Integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sillysum/"
display-uri="focs-sillysum"
type="local">table of complexities</fr:link> from <html:em>The Design and Analysis of Computer Algorithms</html:em> with the heading <html:em>60 hours:</html:em></html:p><html:table>
  <html:tr><html:th>complexity</html:th><html:th>1 second</html:th><html:th>1 minute</html:th><html:th>1 hour</html:th><html:th>60 hours</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n]]></fr:tex></html:td><html:td>1000</html:td><html:td>60 000</html:td><html:td>3 600 000</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n \log  n]]></fr:tex></html:td><html:td>140</html:td><html:td>4 895</html:td><html:td>204 095</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{2}]]></fr:tex></html:td><html:td>31</html:td><html:td>244</html:td><html:td>1 897</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{3}]]></fr:tex></html:td><html:td>10</html:td><html:td>39</html:td><html:td>153</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[2^{n}]]></fr:tex></html:td><html:td>9</html:td><html:td>15</html:td><html:td>21</html:td><html:td /></html:tr>
</html:table></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:uri><fr:display-uri>focs-ex-1-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:route><fr:title
text="Exercises › Floating-point error by repeated addition"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Floating-point error by repeated addition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Because computer arithmetic is based on binary numbers, simple decimals such as 0.1 often cannot be
represented exactly. Write a function <html:code>mul</html:code> that performs the computation</html:p><fr:tex
display="block"><![CDATA[\underbrace {x+x+\cdots +x}_{n}]]></fr:tex><html:p>where <fr:tex
display="inline"><![CDATA[x]]></fr:tex> has type <html:code>float</html:code>. (It is essential to use repeated addition rather than multiplication!)</html:p><html:p>The value computed with <html:code>n = 10000</html:code> and <html:code>x = 0.1</html:code> may print as
<html:code>1000.0</html:code>, which looks exact. If that happens, then evaluate the
expression <html:code>mul 0.1 10000 -. 1000.0</html:code></html:p><html:p>An error of this type has been blamed for the failure of an American Patriot Missile battery to
intercept an incoming Iraqi missile during the <fr:link
href="https://en.wikipedia.org/wiki/MIM-104_PatriotFailure_at_Dhahran"
type="external">first Gulf War</fr:link>.
The missile hit an American Army barracks, killing 28.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:uri><fr:display-uri>focs-ex-1-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:route><fr:title
text="Exercises › Golden ratio instability"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Golden ratio instability</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another example of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-floating-point/"
title="Example 2: Floating Point Numbers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/"
display-uri="focs-floating-point"
type="local">inaccuracy of floating-point arithmetic</fr:link> takes the golden ratio
<fr:tex
display="inline"><![CDATA[\phi \approx 1.618\ldots ]]></fr:tex> as its starting point:</html:p><fr:tex
display="block"><![CDATA[\gamma _0 = \frac {1+\sqrt 5}{2} \quad \text {and}\quad \gamma _{n+1} = \frac {1}{\gamma _n-1}.]]></fr:tex><html:p>In theory, it is easy to prove that <fr:tex
display="inline"><![CDATA[\gamma _n=\cdots  = \gamma _1 = \gamma _0]]></fr:tex> for all <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>. Code this
computation in OCaml and report the value of <fr:tex
display="inline"><![CDATA[\gamma _{50}]]></fr:tex>. <html:em>Hint:</html:em> in OCaml, <fr:tex
display="inline"><![CDATA[\sqrt 5]]></fr:tex> is expressed
as <html:code>sqrt 5.0</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:uri><fr:display-uri>focs-ex-5-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:route><fr:title
text="Exercises › Implementing bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement bubble sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:uri><fr:display-uri>focs-ex-7-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:route><fr:title
text="Exercises › Implementing deletion"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Implementing deletion</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the delete function outlined in the previous exercise.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:uri><fr:display-uri>focs-ex-5-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:route><fr:title
text="Exercises › Implementing selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement selection sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:uri><fr:display-uri>focs-ex-7-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:route><fr:title
text="Exercises › Insertion order in search trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion order in search trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Draw the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link> that arises from successively inserting the following pairs into the
empty tree: <html:code>("Alice", 6)</html:code>, <html:code>("Tobias", 2)</html:code>, <html:code>("Gerald", 8)</html:code>, <html:code>("Lucy", 9)</html:code>. Then repeat this
task using the order <html:code>("Gerald", 8)</html:code>, <html:code>("Alice", 6)</html:code>, <html:code>("Lucy", 9)</html:code>, <html:code>("Tobias", 2)</html:code>. Why are
results different?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:uri><fr:display-uri>focs-ex-7-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:route><fr:title
text="Exercises › Insertion with collision detection"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion with collision detection</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an insertion function for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link>. It should resemble the existing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-update/"
title="Update"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/"
display-uri="focs-bst-update"
type="local"><html:code>update</html:code></fr:link>
function except that it should raise the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Collision</html:code> if the item to be inserted is already
present.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-1/</fr:uri><fr:display-uri>focs-ex-2-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-1/</fr:route><fr:title
text="Exercises › Iterative power"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › Iterative power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:uri><fr:display-uri>focs-ex-11-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:route><fr:title
text="Exercises › Iterative power with while"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Iterative power with while</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of function <html:code>power</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-intro/"
title="Introduction to Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro"
type="local">Lecture <fr:contextual-number
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro" /></fr:link>) using <html:code>while</html:code> instead of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:uri><fr:display-uri>focs-ex-3-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:route><fr:title
text="Exercises › Last element of a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Last element of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the last element of a non-empty list. How efficiently can this be done?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:uri><fr:display-uri>focs-ex-9-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:route><fr:title
text="Exercises › Lazy binary trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Lazy binary trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A <html:em>lazy binary tree</html:em> is either empty or is a branch containing a label and two lazy <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>,
possibly to infinite depth. Present an OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> to represent lazy binary trees, along with a
function that accepts a lazy binary tree and produces a lazy list that contains all of the tree’s
labels. (Taken from the exam question 2008 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:uri><fr:display-uri>focs-ex-8-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:route><fr:title
text="Exercises › Lexicographic orderings"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Lexicographic orderings</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>There are many ways of combining orderings. The <html:code>lexicographic ordering</html:code> uses two keys for
comparisons. It is specified by</html:p><fr:tex
display="block"><![CDATA[(x',y')<(x,y)\iff  x'<x \vee  (x'=x \wedge  y'<y).]]></fr:tex><html:p>Write an OCaml function to lexicographically combine two orderings, supplied as functions. Explain
how it allows function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-partial-application/"
title="Partial Application: A Curried Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/"
display-uri="focs-partial-application"
type="local"><html:code>insort</html:code></fr:link> to sort a list of pairs.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:uri><fr:display-uri>focs-ex-7-7</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:route><fr:title
text="Exercises › Linear traversals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Linear traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>preord</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>inord</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>postord</html:code></fr:link> all take linear time in the size of the
tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:uri><fr:display-uri>focs-ex-11-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:route><fr:title
text="Exercises › Lists of references"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Lists of references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Comment, with examples, on the differences between an <html:code>int ref list</html:code> and an <html:code>int list ref</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:uri><fr:display-uri>focs-ex-9-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:route><fr:title
text="Exercises › Making change lazily"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Making change lazily</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">make change</fr:link> using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, delivering the sequence of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all possible ways of
making change</fr:link>. Using sequences allows us to compute solutions one at a time when there exists an
astronomical number. Represent lists of coins using ordinary lists. (<html:em>Hint</html:em>: to  benefit from
laziness you may need to pass around the sequence of alternative solutions as a function of type
<html:code>unit -&gt; (int list) seq</html:code>.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:uri><fr:display-uri>focs-ex-8-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:route><fr:title
text="Exercises › Making change with map"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Making change with map</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Recall the making change function of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">More on Lists</fr:link>:</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Function <html:code>allc</html:code> applies the function ‘cons a <html:code>c</html:code>’ to every element of a list. Eliminate it by
declaring a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried</fr:link> cons function and applying <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:uri><fr:display-uri>focs-ex-8-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:route><fr:title
text="Exercises › Mapping over lists of lists"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Mapping over lists of lists</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Without using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> write a function <html:code>map2</html:code> such that <html:code>map2 f</html:code> is equivalent to <html:code>map (map f)</html:code>. The
obvious solution requires declaring two recursive functions. Try to get away with only one by
exploiting nested <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:uri><fr:display-uri>focs-ex-11-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:route><fr:title
text="Exercises › Matrix operations on arrays"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Matrix operations on arrays</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Arrays of multiple dimensions are represented in OCaml by arrays of arrays. Write functions to
(a) create an <fr:tex
display="inline"><![CDATA[n\times  n]]></fr:tex> identity matrix, given <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, and
(b) to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local">transpose</fr:link> an <fr:tex
display="inline"><![CDATA[m\times  n]]></fr:tex> matrix. Identity matrices have the following form:</html:p><fr:tex
display="block"><![CDATA[
\left ( {
\begin {array}{cccc}
   1 & 0 &  \cdots   & 0  \\
   0 & 1 &  \cdots   & 0  \\
    \vdots   &  \vdots   &  \ddots   &  \vdots    \\
   0 & 0 &  \cdots   & 1  \\
 \end {array}
 } \right )
]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:uri><fr:display-uri>focs-ex-4-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:route><fr:title
text="Exercises › Partitioning integers by sign"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Partitioning integers by sign</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function that takes a list of integers and returns two lists, the first consisting of all
non-negative numbers found in the input and the second consisting of all the negative numbers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-4/</fr:uri><fr:display-uri>focs-ex-3-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-4/</fr:route><fr:title
text="Exercises › Polymorphic types of id and loop"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Polymorphic types of id and loop</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic types</fr:link> in these two function declarations:</html:p><html:pre><![CDATA[# let id x = x
val id : 'a -> 'a = <fun>
# let rec loop x = loop x
val loop : 'a -> 'b = <fun>]]></html:pre><html:p>Explain why these types make logical sense, preventing run time type errors, even for expressions
like <html:code>id [id [id 0]]</html:code> or <html:code>loop true / loop 3</html:code>. (<html:code>/</html:code> is the integer division operator in OCaml)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:uri><fr:display-uri>focs-ex-7-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:route><fr:title
text="Exercises › Quadratic traversals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Quadratic traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>preorder</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>postorder</html:code></fr:link> all require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time in the worst
case, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the size of the tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:uri><fr:display-uri>focs-ex-4-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:route><fr:title
text="Exercises › Reasoning from polymorphic types"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Reasoning from polymorphic types</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>We know nothing about the functions <html:code>f</html:code> and <html:code>g</html:code> other than their polymorphic types:
<html:code>val f : 'a * 'b -&gt; 'b * 'a</html:code> and <html:code>val g : 'a -&gt; 'a list</html:code>.
Suppose that <html:code>f (1, true)</html:code> and <html:code>g 0</html:code> are evaluated and return their results. State, with reasons,
what you think the resulting values will be.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-3/</fr:uri><fr:display-uri>focs-ex-1-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-3/</fr:route><fr:title
text="Exercises › Redundant conditionals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Redundant conditionals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Why would no experienced programmer write an expression of the form <html:code>if</html:code> … <html:code>then true else false</html:code>?
What about expressions of the form <html:code>if</html:code> … <html:code>then false else true</html:code>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:uri><fr:display-uri>focs-ex-7-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:route><fr:title
text="Exercises › Returning the old value on collision"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Returning the old value on collision</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, it would be natural for exceptional <html:code>Collision</html:code> to return the
value previously stored in the dictionary. Why is that goal difficult to achieve?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:uri><fr:display-uri>focs-ex-10-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:route><fr:title
text="Exercises › Rewriting breadth with let"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Rewriting breadth with let</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
title="Breadth-First Tree Traversal — Using Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
display-uri="focs-bfs-queues"
type="local"><html:code>breadth</html:code></fr:link> using a nested <html:code>let</html:code> construction rather than
<html:code>match</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:uri><fr:display-uri>focs-ex-10-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:route><fr:title
text="Exercises › Search with a branching factor near one"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Search with a branching factor near one</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
title="Iterative deepening: Another Exhaustive Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
display-uri="focs-iterative-deepening"
type="local">Iterative deepening</fr:link> is inappropriate if <fr:tex
display="inline"><![CDATA[b\approx 1]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[b]]></fr:tex> is the branching factor. What search
strategy is appropriate in this case?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:uri><fr:display-uri>focs-ex-4-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:route><fr:title
text="Exercises › Set union without repetitions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Set union without repetitions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Sets can be represented in OCaml using lists containing no duplicated items
(i.e. where no item is equal to another using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link> comparison).</html:p><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link> function defined above, code a function to implement set
union. It should avoid introducing repetitions, for example the union of the
lists <html:code>[4; 7; 1]</html:code> and <html:code>[6; 4; 7]</html:code> should be <html:code>[1; 6; 4; 7]</html:code> (though the order
does not matter).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:uri><fr:display-uri>focs-ex-7-8</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:route><fr:title
text="Exercises › Shifting a functional array"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Shifting a functional array</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to remove the first element from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional array</fr:link>. All the other elements are to
have their subscripts reduced by one. The cost of this operation should be linear in the size of the
array.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-3/</fr:uri><fr:display-uri>focs-ex-2-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-3/</fr:route><fr:title
text="Exercises › Simplifying sums in O notation"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › Simplifying sums in O notation</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Let <fr:tex
display="inline"><![CDATA[g_1]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[g_k]]></fr:tex> be functions such that <fr:tex
display="inline"><![CDATA[g_i(n)\ge 0]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=1]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[k]]></fr:tex> and all sufficiently
large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>Show that if <fr:tex
display="inline"><![CDATA[f(n) = O(a_1 g_1(n)+\cdots +a_k g_k(n))]]></fr:tex> then <fr:tex
display="inline"><![CDATA[f(n) = O(g_1(n)+\cdots +g_k(n))]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:uri><fr:display-uri>focs-ex-3-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:route><fr:title
text="Exercises › Summing a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Summing a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function</fr:link> to compute the sum of a list’s elements. Then code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version
and comment on the improvement in efficiency.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:uri><fr:display-uri>focs-ex-6-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:route><fr:title
text="Exercises › Summing tree labels"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Summing tree labels</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write an OCaml function taking a binary tree labelled with integers and returning their sum.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:uri><fr:display-uri>focs-ex-3-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:route><fr:title
text="Exercises › Tails of a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Tails of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function <html:code>tails</html:code> to return the list of the tails of its argument. For example, given
<html:code>[1; 2; 3]</html:code> it should return <html:code>[[1; 2; 3]; [2; 3]; [3]; []]</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-1/</fr:uri><fr:display-uri>focs-ex-8-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-1/</fr:route><fr:title
text="Exercises › The argument-swapping functional"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › The argument-swapping functional</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What does the following function do, and what are its uses?</html:p><html:pre><![CDATA[let sw f x y = f y x]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:uri><fr:display-uri>focs-ex-10-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:route><fr:title
text="Exercises › Tree-based queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Tree-based queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Suppose that we have an implementation of queues, based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>, such that each operation
takes logarithmic time in the worst case. Outline the advantages and drawbacks of such an
implementation compared with one presented above.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-1/</fr:uri><fr:display-uri>focs-ex-1-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-1/</fr:route><fr:title
text="Exercises › Two-digit year windowing"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Two-digit year windowing</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>One solution to the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dates/"
title="Example 1: Dates"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/"
display-uri="focs-dates"
type="local">year 2000 bug</fr:link> involves storing years as two digits, but interpreting them such
that 50 means 1950 and 49 means 2049. Comment on the merits and demerits of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:uri><fr:display-uri>focs-ex-1-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:route><fr:title
text="Exercises › Type inference in power"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Type inference in power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> both return a <html:code>float</html:code>. The definition of <html:code>npower</html:code> returns the float
value <html:code>1.0</html:code> in its base case. The definition of <html:code>power</html:code> does not, so how does the OCaml type checker
know that <html:code>power</html:code> returns a <html:code>float</html:code>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:uri><fr:display-uri>focs-ex-6-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:route><fr:title
text="Exercises › What ftree builds"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › What ftree builds</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">definition of <html:code>'a tree</html:code></fr:link> from before:</html:p><html:pre><![CDATA[type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:p>Examine the following function declaration. What does <html:code>ftree (1, n)</html:code> accomplish?</html:p><html:pre><![CDATA[let rec ftree k n =
  if n = 0 then Lf
  else Br (k, ftree (2 * k) (n - 1), ftree (2 * k + 1) (n - 1))]]></html:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors /><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/</fr:uri><fr:display-uri>anil-madhavapeddy</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/anil-madhavapeddy/</fr:route><fr:title
text="Anil Madhavapeddy">Anil Madhavapeddy</fr:title></fr:frontmatter><fr:mainmatter><html:p><fr:link
href="https://anil.recoil.org/"
type="external">Anil Madhavapeddy</fr:link> lectures the Foundations of Computer Science course at the University of Cambridge.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/</fr:uri><fr:display-uri>focs-glossary</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-glossary/</fr:route><fr:title
text="Glossary">Glossary</fr:title></fr:frontmatter><fr:mainmatter><html:p>Definitions of the course’s core concepts, collected automatically.</html:p><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstract-data-type/</fr:uri><fr:display-uri>focs-def-abstract-data-type</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-abstract-data-type/</fr:route><fr:title
text="Abstract data type">Abstract data type</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent them. Before choosing the
internal representation for a data structure, you need to specify the full set of
operations. Abstract types can be declared in any modern programming language:
Java’s <html:em>objects</html:em> serve this role, as do OCaml’s modules.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">Dictionaries</fr:link>, and applied to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-queue-adt/"
title="An Abstract Data Type: Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/"
display-uri="focs-queue-adt"
type="local">queues</fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-stacks/"
title="Another Abstract Data Type: Stacks"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-stacks/"
display-uri="focs-stacks"
type="local">stacks</fr:link> later on.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/</fr:uri><fr:display-uri>focs-def-abstraction-barrier</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/</fr:route><fr:title
text="Abstraction barrier">Abstraction barrier</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Large systems can only be understood in levels: the interface to the higher
level should supply the advertised services and, just as important, block access
to the means by which those services are implemented. This abstraction barrier
allows one level to be changed without affecting levels above.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-basic-concepts/"
title="Basic Concepts in Computer Science"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-basic-concepts/"
display-uri="focs-basic-concepts"
type="local">Basic Concepts in Computer Science</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/</fr:uri><fr:display-uri>focs-def-algebraic-datatype</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/</fr:route><fr:title
text="Algebraic datatype">Algebraic datatype</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>OCaml generalises the notion of enumeration type to allow data to be
associated with each constructor: some constructors are values all by themselves,
while others create values from arguments. Constructors with arguments are
<html:em>distinct values</html:em>, and values built from different constructors of one
datatype can belong to a single list.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-constructors-args/"
title="A Datatype whose Constructors have Arguments"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-constructors-args/"
display-uri="focs-constructors-args"
type="local">A Datatype whose Constructors have Arguments</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/</fr:uri><fr:display-uri>focs-def-binary-search-tree</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/</fr:route><fr:title
text="Binary search tree">Binary search tree</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A binary search tree works for keys that have a total ordering, such as
strings. Each branch of the tree carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree
holds smaller keys and its right subtree holds greater keys. If the tree remains
reasonably balanced, then update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of
size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary Search Trees</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/</fr:uri><fr:display-uri>focs-def-currying</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-currying/</fr:route><fr:title
text="Currying">Currying</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Currying is the technique of expressing a function taking multiple arguments
as nested functions, each taking a single argument. A <html:em>curried function</html:em>
returns another function as its result, so the arguments are supplied one after
another.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-currying/"
title="Curried Functions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/"
display-uri="focs-currying"
type="local">Curried Functions</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/</fr:uri><fr:display-uri>focs-def-exception</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-exception/</fr:route><fr:title
text="Exception">Exception</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>An exception signals that something has gone <html:em>wrong</html:em> during a computation,
such as division by zero or pattern matching failure. Raising an exception
abandons the current computation; handling the exception attempts an alternative
computation. The raising and the handling can be far apart in the code, and
errors of <html:em>different sorts</html:em> can be handled separately.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">Error Handling: Exceptions</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/</fr:uri><fr:display-uri>focs-def-higher-order-function</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/</fr:route><fr:title
text="Higher-order function">Higher-order function</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>In mathematics, a <html:em>functional</html:em> or <html:em>higher-order function</html:em> is a function
that operates on other functions. In OCaml, functions can be passed as arguments
to other functions, returned as results, and put into lists, trees and so on—but
<html:em>not</html:em> tested for equality.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functions/"
title="Functions as Values"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/"
display-uri="focs-functions"
type="local">Functions as Values</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/</fr:uri><fr:display-uri>focs-def-lazy-list</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-lazy-list/</fr:route><fr:title
text="Lazy list">Lazy list</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A lazy list is a list of possibly <html:em>infinite</html:em> length whose elements are
<html:em>computed upon demand</html:em>; in OCaml we implement laziness by <html:em>delaying
evaluation</html:em> of the tail of the list. The traditional word “stream” is reserved in
OCaml parlance for input/output channels, so we call lazy lists <html:em>sequences</html:em>
instead.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lazy-lists/"
title="Lazy Lists (or Streams)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-lists/"
display-uri="focs-lazy-lists"
type="local">Lazy Lists</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/</fr:uri><fr:display-uri>focs-def-mutable-reference</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/</fr:route><fr:title
text="Mutable reference">Mutable reference</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A reference is a cell in the store, also called a “location”: <html:code>ref E</html:code>
creates a reference with initial contents the value of <html:code>E</html:code>, <html:code>!P</html:code>
returns the current contents of reference <html:code>P</html:code> (an operation called
<html:em>dereferencing</html:em>), and <html:code>P := E</html:code> updates the contents of <html:code>P</html:code> to the
value of <html:code>E</html:code>. If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is some OCaml type, then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>ref</html:code> is the
type of references to cells that can hold values of <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local">OCaml Primitives for References</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/</fr:uri><fr:display-uri>focs-def-o-notation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-o-notation/</fr:route><fr:title
text="O notation">O notation</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Formally, <fr:tex
display="inline"><![CDATA[f(n) = O(g(n))]]></fr:tex> provided <fr:tex
display="inline"><![CDATA[|f(n)| \leq  c|g(n)|]]></fr:tex> as <fr:tex
display="inline"><![CDATA[n\to \infty ]]></fr:tex>,
that is, for some constant <fr:tex
display="inline"><![CDATA[c]]></fr:tex> and all <html:em>sufficiently large</html:em> <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. The “Big
O” notation is commonly used to describe efficiency—to be precise,
<html:em>asymptotic complexity</html:em>—by looking only at the most significant term and
ignoring constant factors.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-o-notation/"
title="Comparing Algorithms: O Notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/"
display-uri="focs-o-notation"
type="local">Comparing Algorithms: O Notation</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/</fr:uri><fr:display-uri>focs-def-pattern-matching</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/</fr:route><fr:title
text="Pattern matching">Pattern matching</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Pattern matching takes a value apart by matching it against the forms that
value can have, letting <html:em>one</html:em> function declaration handle several cases,
separated by a vertical bar <html:code>|</html:code>. Taking a list apart using combinations of
<html:code>hd</html:code> and <html:code>tl</html:code> is hard to get right; fortunately, it is seldom necessary
because of pattern-matching.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">Getting at the Head and Tail</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/</fr:uri><fr:display-uri>focs-def-polymorphism</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-polymorphism/</fr:route><fr:title
text="Polymorphism">Polymorphism</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A polymorphic function allows flexibility in the types of its arguments and
results: the list primitives <html:code>null</html:code>, <html:code>hd</html:code> and <html:code>tl</html:code> work whatever
the element type is. Symbols <html:code>'a</html:code> and <html:code>'b</html:code> are called <html:em>type
variables</html:em> and stand for any types, and code written using them is still checked
for type correctness at compile time.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">Getting at the Head and Tail</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/</fr:uri><fr:display-uri>focs-def-recursion</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-recursion/</fr:route><fr:title
text="Recursion">Recursion</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A function is recursive if it calls itself. You can spot a recursive function
by the <html:code>rec</html:code> keyword in its definition: this indicates that any invocation
of the function name within the function body should call itself. The recursion
is meaningful because it terminates: we reduce the problem to smaller problems,
and this cannot go on forever.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local">Raising a Number to a Power</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/</fr:uri><fr:display-uri>focs-def-tail-recursion</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/</fr:route><fr:title
text="Tail recursion">Tail recursion</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A recursive function whose computation does not nest is called <html:em>iterative</html:em>
or <html:em>tail-recursive</html:em>: the recursive calls do not nest, so the work is done
immediately rather than on the way back out. Many functions can be made
iterative by introducing an extra argument, which is often called an
<html:em>accumulator</html:em>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-summing-iter/"
title="Iteratively summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/"
display-uri="focs-summing-iter"
type="local">Iteratively summing the first n integers</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topics/</fr:uri><fr:display-uri>focs-topics</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topics/</fr:route><fr:title
text="Topic index">Topic index</fr:title></fr:frontmatter><fr:mainmatter><html:p>Sections and exercises grouped by topic, collected automatically from tags on each tree.</html:p><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-recursion/</fr:uri><fr:display-uri>focs-topic-recursion</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-recursion/</fr:route><fr:title
text="Recursion">Recursion</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/</fr:uri><fr:display-uri>focs-change-all</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-all/</fr:route><fr:title
text="All Ways of Making Change">All Ways of Making Change</fr:title></fr:frontmatter><fr:mainmatter><html:p>Now we generalise the problem to return the list of <html:em>all possible ways</html:em> of making change,
and write a new <html:code>change</html:code> function.</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Look at the type: the result is now a list of lists.
The code will also never raise <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>.  It expresses failure by returning an
empty list of solutions: it returns <html:code>[]</html:code> if the till is empty and the
amount is nonzero.</html:p><html:p>If the amount is zero, then there is only one way of making change;
the result should be <html:code><![CDATA[[[]]]]></html:code>.  This is success in the base case.</html:p><html:p>In nontrivial cases, there are two sources of solutions: to use a coin (if
possible) and decrease the amount accordingly, or to remove the current coin
value from consideration.</html:p><html:p>The function <html:code>allc</html:code> is declared locally in order to make use
of <html:code>c</html:code>, the current coin.  It adds an extra <html:code>c</html:code> to all the
solutions returned by the recursive call to make change for <html:code>amt - c</html:code>.</html:p><html:p>Observe the naming convention: <html:code>cs</html:code> is a list of coins, while
<html:code>css</html:code> is a list of such lists.  The trailing ‘s’ is suggestive of a
plural.</html:p><html:p>This complicated program, and the even trickier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-faster/"
title="All Ways of Making Change — Faster!"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/"
display-uri="focs-change-faster"
type="local">faster version</fr:link>, are
included as challenges.  Are you enthusiastic enough to work them out?  We
shall revisit the “making change” task later to illustrate <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-exceptions/"
title="Making Change with Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/"
display-uri="focs-change-exceptions"
type="local">exception-handling</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:uri><fr:display-uri>focs-change-faster</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:route><fr:title
text="All Ways of Making Change — Faster!">All Ways of Making Change — Faster!</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec change till amt chg chgs =
    match till, amt with
    | _       , 0   -> chg::chgs
    | []      , _   -> chgs
    | c::till , amt -> if amt < 0 then chgs
                       else change (c::till) (amt - c) (c::chg)
                                   (change till amt chg chgs)
val change : int list -> int -> int list -> int list list -> int list list =
  <fun>]]></html:pre><html:p>We’ve added <html:em>another</html:em> accumulating parameter!  Repeatedly improving simple code
is called <html:em>stepwise refinement</html:em>.</html:p><html:p>Two extra arguments eliminate many <html:code>::</html:code> and append operations from the
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all-solutions <html:code>change</html:code></fr:link> function.  The first, <html:code>chg</html:code>, accumulates the coins chosen so
far; one evaluation of <html:code>c::chg</html:code> replaces many evaluations of <html:code>allc</html:code>.  The
second, <html:code>chgs</html:code>, accumulates the list of solutions so far; it avoids the need
for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link>.  This version runs several times faster than the previous one.</html:p><html:p>Making change is still extremely slow for an obvious reason: the number of
solutions grows rapidly in the amount being changed.  Using 50, 20, 10, 5,
2 and 1, there are 4366 ways of expressing 99.</html:p><html:p>Our three change functions illustrate a basic technique: program development
by stepwise refinement.  Begin by writing a very simple program and add
requirements individually.  Add efficiency refinements last of all.
Even if the simpler program cannot be included in the next version and has
to be discarded, one has learned about the task by writing it.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/</fr:uri><fr:display-uri>focs-making-change</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-making-change/</fr:route><fr:title
text="An Application: Making Change">An Application: Making Change</fr:title></fr:frontmatter><fr:mainmatter><html:p>Consider a till that has unlimited supplies of coins.  The largest coins should be tried
first, to avoid giving change all in pennies.  The list of legal coin values,
called <html:code>till</html:code>, is given in descending order, such as 50, 20, 10, 5,
2 and 1.  (Recall that the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">head of a list</fr:link> is the element most easily reached.)
The code for <html:code>change</html:code> is based on simple observations:</html:p><html:ul><html:li>Change for zero consists of no coins at all.  (Note the pattern of <html:code>0</html:code> in the first clause.)</html:li>
  <html:li>For a nonzero amount, try the largest available coin.  If it is small enough, use it and decrease the amount accordingly.</html:li>
  <html:li>Exclude from consideration any coins that are too large.</html:li></html:ul><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise (Failure "no more coins!")
    | c::till, amt -> if amt < c then change till amt
                      else c :: change (c::till) (amt - c)
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>Although nobody considers making change for zero, this is the simplest way to
make the algorithm terminate.  Most iterative procedures become simplest if,
in their base case, they do nothing.  A base case of one instead of zero is
often a sign of a novice programmer.</html:p><html:ul><html:li>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link> <html:em>terminates</html:em> when <html:code>amt = 0</html:code>.</html:li>
  <html:li>Tries the <html:em>largest coin first</html:em> to use large coins.</html:li>
  <html:li>The algorithm is <html:em>greedy</html:em> and can fail!</html:li></html:ul><html:p>The function can terminate either with success or failure.  It fails by
raising exception <html:code>Failure</html:code> namely if <html:code>till</html:code> becomes empty while <html:code>amt</html:code> is still nonzero.
(<fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">Exceptions</fr:link> will be discussed later.)</html:p><html:p>Unfortunately, failure can occur even when change can be made.  The greedy
"largest coin first" approach is to blame.  Suppose we have coins of values 5
and 2, and must make change for 6; the only way is <fr:tex
display="inline"><![CDATA[6=2+2+2]]></fr:tex>, ignoring the 5.
<html:em>Greedy algorithms</html:em> are often effective, but not here.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:uri><fr:display-uri>focs-quicksort-append-free</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:route><fr:title
text="Append-Free Quicksort">Append-Free Quicksort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quik = function
    | ([], sorted) -> sorted
    | ([x], sorted) -> x::sorted
    | a::bs, sorted ->
       let rec part = function
         | l, r, [] -> quik (l, a :: quik (r, sorted))
         | l, r, x::xs ->
             if x <= a then
               part (x::l, r, xs)
             else
               part (l, x::r, xs)
       in
       part ([], [], bs)
val quik : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>The list <html:code>sorted</html:code> accumulates the result in the <html:em>combine</html:em> stage of
the quicksort algorithm.  We have again used the standard technique for
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-rev/"
title="Reversing a List in O(n)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/"
display-uri="focs-rev"
type="local">eliminating append</fr:link>.  Calling <html:code>quik(xs, sorted)</html:code> reverses the elements of
<html:code>xs</html:code> and prepends them to the list <html:code>sorted</html:code>.</html:p><html:p>Looking closely at <html:code>part</html:code>, observe that <html:code>quik(r, sorted)</html:code> is
performed first.  Then <html:code>a</html:code> is consed to this sorted list.  Finally,
<html:code>quik</html:code> is called again to sort the elements of <html:code>l</html:code>.</html:p><html:p>The speedup is significant.  An imperative quicksort coded in Pascal (taken
from <fr:link
href="https://algs4.cs.princeton.edu/20sorting/"
type="external">Sedgewick</fr:link>) is just slightly faster than function
<html:code>quik</html:code>.  The near-agreement is surprising because the computational overheads
of lists exceed those of arrays.  In realistic applications, comparisons are
the dominant cost and the overheads matter even less.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/</fr:uri><fr:display-uri>focs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-append/</fr:route><fr:title
text="Append: List Concatenation">Append: List Concatenation</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec append xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> x :: append xs ys
val append : 'a list -> 'a list -> 'a list = <fun>
# append [1; 2; 3] [4]
- : int list = [1; 2; 3; 4]
# let (@) = append
val ( @ ) : 'a list -> 'a list -> 'a list = <fun>
# [1; 2; 3] @ [4]
- : int list = [1; 2; 3; 4]]]></html:pre><html:p>Patterns can be as complicated as we like.  Here, the two patterns are
<html:code>[], ys</html:code> and <html:code>x::xs, ys</html:code>.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {append }[1; 2; 3] [4] \Rightarrow  &\; 1 :: \text {append }[2; 3]\;[4] \\
  \Rightarrow  &\; 1 :: (2 :: \text {append }[3]\;[4]) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: \text {append }[]\;[4])) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: [4])) \ [1; 2; 3; 4]
\end {aligned}
]]></fr:tex><html:p>Here is how append might be declared, also noting that we have defined <html:code>@</html:code> as
an infix operator that is a more convenient way to call <html:code>append</html:code> on two lists.
However, this function is also not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It scans its first
argument, sets up a string of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code> operations</fr:link> (<html:code>::</html:code>) and finally does them.</html:p><html:p>It uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its first argument.
<html:em>Its costs are independent of its second argument.</html:em></html:p><html:p>An accumulating argument could make it iterative, but with considerable
complication.  The iterative version would still require <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time
because concatenation requires copying all the elements of the first list.
Therefore, we cannot hope for asymptotic gains; at best we can decrease the
constant factor involved in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>, but complicating the code is likely to
increase that factor.  Never add an accumulator merely out of habit.</html:p><html:p>Note append’s <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic type</fr:link>. It tells us that two lists can be joined if
their element types agree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:uri><fr:display-uri>focs-tree-traversal</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:route><fr:title
text="Aside: Traversing Trees (3 Methods)">Aside: Traversing Trees (3 Methods)</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec preorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      [v] @ preorder t1 @ preorder t2
val preorder : 'a tree -> 'a list = <fun>
# let rec inorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      inorder t1 @ [v] @ inorder t2
val inorder : 'a tree -> 'a list = <fun>
# let rec postorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      postorder t1 @ postorder t2 @ [v]
val postorder : 'a tree -> 'a list = <fun>]]></html:pre><html:p><html:em>Tree traversal</html:em> means examining each node of a tree in some order.  <fr:link
href="https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming"
type="external">D. E.
Knuth</fr:link> has
identified three forms of tree traversal: preorder, inorder and
postorder.  We can code these “visiting orders” as functions
that convert trees into lists of labels.  Algorithms based on these notions
typically perform some action at each node; the functions above simply copy
the nodes into lists.  Consider the tree:</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmic3wbal56lpqlso6xcqsl6jfrutwygavrn3xds7c6ieywfjr7qdhm.svg" /></html:figure><html:ul><html:li><html:code>preorder</html:code> visits the label first (“Polish notation”), yielding <html:code>ABDECFG</html:code></html:li>
<html:li><html:code>inorder</html:code> visits the label midway, yielding <html:code>DBEAFCG</html:code></html:li>
<html:li><html:code>postorder</html:code> visits the label last (“Reverse Polish”), yielding <html:code>DEBFGCA</html:code>. You might be familiar with this concept if you own an ancient RPN calculator!</html:li></html:ul><html:p>What is the use of <html:code>inorder</html:code>? Consider applying it to a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>: the
result is a sorted list of pairs. We could use this, for example, to merge two
binary search trees. It is not difficult to transform a sorted list of pairs
into a binary search tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-properties/</fr:uri><fr:display-uri>focs-tree-properties</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-properties/</fr:route><fr:title
text="Basic Properties of Binary Trees">Basic Properties of Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec count = function
  | Lf -> 0  (* number of branch nodes *)
  | Br (v, t1, t2) -> 1 + count t1 + count t2
val count : 'a tree -> int = <fun>
# let rec depth = function
  | Lf -> 0  (* length of longest path *)
  | Br (v, t1, t2) -> 1 + max (depth t1) (depth t2)
val depth : 'a tree -> int = <fun>]]></html:pre><html:p>The invariant <fr:tex
display="inline"><![CDATA[\texttt {count}(t)\le  2^{\texttt {depth}(t)} - 1]]></fr:tex> holds in the functions above.</html:p><html:p>Functions on trees are expressed recursively using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.  Both
functions above are analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-length/"
title="Efficiently Computing the Length of a List"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/"
display-uri="focs-length"
type="local"><fr:tex
display="inline"><![CDATA[\texttt {length}]]></fr:tex> on lists</fr:link>.  Here is a third
measure of a tree’s size:</html:p><html:pre><![CDATA[# let rec leaves = function
  | Lf -> 1
  | Br (v, t1, t2) -> leaves t1 + leaves t2
val leaves : 'a tree -> int = <fun>]]></html:pre><html:p>This function is redundant because of a basic fact about trees, which can be
proved by induction: for every tree <fr:tex
display="inline"><![CDATA[t]]></fr:tex>, we have <fr:tex
display="inline"><![CDATA[\texttt {leaves}(t) =
\texttt {count}(t)+1]]></fr:tex>.  The invariant <fr:tex
display="inline"><![CDATA[\texttt {count}(t)\le  2^{\texttt {depth}(t)} - 1]]></fr:tex> stated above also has an elementary
proof by induction.</html:p><html:p>A tree of depth 20 can store <fr:tex
display="inline"><![CDATA[2^{20}-1]]></fr:tex> or approximately one million elements.
The access paths to these elements are short, particularly when compared with
a million-element list!</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:uri><fr:display-uri>focs-binary-trees</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:route><fr:title
text="Binary Trees, a Recursive Datatype">Binary Trees, a Recursive Datatype</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a tree =
    Lf
  | Br of 'a * 'a tree * 'a tree
type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmihauytafmmc5evdkkihzsaxper2thnogxohktuubaoxtrpw24qazu.svg" /></html:figure><html:pre><![CDATA[# Br(1, Br(2, Br(4, Lf, Lf),
              Br(5, Lf, Lf)),
        Br(3, Lf, Lf))
- : int tree = Br (1, Br (2, Br (4, Lf, Lf), Br (5, Lf, Lf)), Br (3, Lf, Lf))]]></html:pre><html:p>A data structure with multiple branching is called a “tree”.  Trees can
represent mathematical expressions, logical formulae, computer programs, the
phrase structure of English sentences, etc.</html:p><html:p><html:em>Binary trees</html:em> are nearly as fundamental as lists.  They can provide
efficient storage and retrieval of information.  In a binary tree, each node
is empty (<fr:tex
display="inline"><![CDATA[Lf]]></fr:tex>), or is a branch (<fr:tex
display="inline"><![CDATA[Br]]></fr:tex>) with a label and two subtrees.</html:p><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">OCaml lists</fr:link> are a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> and could be declared as follows:</html:p><html:pre><![CDATA[# type 'a mylist =
  | Nil
  | Cons of 'a * 'a mylist
type 'a mylist = Nil | Cons of 'a * 'a mylist]]></html:pre><html:p>We could even declare <html:code>::</html:code> as an infix constructor.  The only
thing we could not define is the <html:code>[...]</html:code> notation, which is
part of the OCaml grammar (although there does exist a mechanism
to use a <html:em>similar</html:em> syntax for custom indexed datatypes).</html:p><html:p>A <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> type does not have to be <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.
For example, here is a simple datatype of tree shapes with no attached data
that is recursive but not polymorphic.</html:p><html:pre><![CDATA[# type shape =
  | Null
  | Join of shape * shape
type shape = Null | Join of shape * shape]]></html:pre><html:p>The datatype <html:code>'a option</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">mentioned above</fr:link>) is the opposite – it is
polymorphic, but not recursive.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/</fr:uri><fr:display-uri>focs-zip</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-zip/</fr:route><fr:title
text="Building a List of Pairs">Building a List of Pairs</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec zip xs ys =
    match xs, ys with
    | (x::xs, y::ys) -> (x, y) :: zip xs ys
    | _ -> []
val zip : 'a list -> 'b list -> ('a * 'b) list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[\left .[x_1,\ldots ,x_n]\atop 
         [y_1,\ldots ,y_n]\right \}\;\longmapsto \;[(x_1,y_1),\ldots ,(x_n,y_n)]]]></fr:tex><html:p>The <html:em>wildcard</html:em> pattern <html:code>_</html:code> matches <html:em>anything</html:em>. We could have written a
variable such as <html:code>p</html:code> instead, but the wildcard reminds us that the
relevant clause ignores this argument.</html:p><html:p>The patterns are also tested in order of their definitions: first
<html:code>(x::xs, y::ys)</html:code>, then <html:code>_</html:code>.</html:p><html:p>A list of pairs of the form <fr:tex
display="inline"><![CDATA[[(x_1,y_1),\ldots ,(x_n,y_n)]]]></fr:tex> associates each
<fr:tex
display="inline"><![CDATA[x_i]]></fr:tex> with <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex>.  Conceptually, a telephone directory could be regarded as
such a list, where <fr:tex
display="inline"><![CDATA[x_i]]></fr:tex> ranges over names and <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex> over the corresponding
telephone number.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link> in such a list can find the <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex> associated
with a given <fr:tex
display="inline"><![CDATA[x_i]]></fr:tex>, or vice versa—very slowly.</html:p><html:p>In other cases, the <fr:tex
display="inline"><![CDATA[(x_i,y_i)]]></fr:tex> pairs might have been generated by applying a
function to the elements of another list <fr:tex
display="inline"><![CDATA[[z_1,\ldots ,z_n]]]></fr:tex>.</html:p><html:pre><![CDATA[# let rec unzip = function
   | [] -> ([], [])
   | (x, y)::pairs ->
       let xs, ys = unzip pairs in
       (x::xs, y::ys)
val unzip : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>Given a list of pairs, <html:code>unzip</html:code> has to build <html:em>two</html:em> lists of
results, which is awkward using recursion.  The version shown above uses the
<html:em>local binding</html:em> <html:code>let p = </html:code><fr:tex
display="inline"><![CDATA[\;E_1\;]]></fr:tex><html:code> in </html:code><fr:tex
display="inline"><![CDATA[\;E_2]]></fr:tex>,
where the value of <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> is bound to the variable <html:code>p</html:code> within <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex>. The
let-construct counts as an expression and can be used (perhaps wrapped
within parentheses) wherever an expression is expected.</html:p><html:p>Note especially the phrase <html:code>let xs, ys = unzip pairs</html:code>
which binds <html:code>xs</html:code> and <html:code>ys</html:code> to the results of the recursive call.
In general, the phrase <html:code>let P = E</html:code> matches the
pattern <fr:tex
display="inline"><![CDATA[P]]></fr:tex> against the value of expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.  It binds all the variables
in <fr:tex
display="inline"><![CDATA[P]]></fr:tex> to the corresponding values.</html:p><html:p>The functions <html:code>zip</html:code> and <html:code>unzip</html:code> build and take apart lists of
pairs: <html:code>zip</html:code> pairs up corresponding list elements and <html:code>unzip</html:code>
inverts this operation.  Their types reflect what they do:</html:p><html:pre><![CDATA[# zip
- : 'a list -> 'b list -> ('a * 'b) list = <fun>
# unzip
- : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>If the lists are of unequal length, <html:code>zip</html:code> discards surplus items at the
end of the longer list.  Its first pattern only matches a pair of non-empty
lists.  The second pattern is just a wildcard and could match anything.  OCaml
tries the clauses in the order given, so the first pattern is tried first.
The second only gets arguments where at least one of the lists is empty.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-unzip/</fr:uri><fr:display-uri>focs-unzip</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-unzip/</fr:route><fr:title
text="Building a Pair of Results">Building a Pair of Results</fr:title></fr:frontmatter><fr:mainmatter><html:p>Here is a version of <html:code>unzip</html:code> that replaces the local declaration by a
function <html:code>conspair</html:code> for taking apart the pair of lists in the
recursive call.  It defines the same
computation as the previous version of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local"><html:code>unzip</html:code></fr:link> and is possibly clearer,
but not every local binding can be eliminated as easily.</html:p><html:pre><![CDATA[# let conspair ((x, y), (xs, ys)) = (x::xs, y::ys)
val conspair : ('a * 'b) * ('a list * 'b list) -> 'a list * 'b list = <fun>
# let rec unzip = function
    | [] -> ([], [])
    | xy :: pairs -> conspair (xy, unzip pairs)
val unzip : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>Making the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> yields <html:code>revUnzip</html:code> below, which is
very simple.  Iteration can construct many results at once in different
argument positions.  Both output lists are built in reverse order, which can
be corrected by reversing the input to <html:code>revUnzip</html:code>.  The total costs
will probably exceed those of <html:code>unzip</html:code> despite the advantages of
iteration.</html:p><html:pre><![CDATA[# let rec revUnzip = function
    | ([], xs, ys) -> (xs, ys)
    | ((x, y)::pairs, xs, ys) ->
        revUnzip (pairs, x::xs, y::ys)
val revUnzip : ('a * 'b) list * 'a list * 'b list -> 'a list * 'b list =
  <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nlength/</fr:uri><fr:display-uri>focs-nlength</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nlength/</fr:route><fr:title
text="Computing the Length of a List">Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nlength = function
  | [] -> 0
  | x :: xs -> 1 + nlength xs
val nlength : 'a list -> int = <fun>
# nlength []
- : int = 0
# nlength [5; 6; 7]
- : int = 3]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nlength }[a; b; c] \Rightarrow  &\; 1 + \text {nlength }[b; c] \\
   \Rightarrow  &\; 1 + (1 + \text {nlength }[c]) \\
   \Rightarrow  &\; 1 + (1 + (1 + \text {nlength }[])) \\
   \Rightarrow  &\; 1 + (1 + (1 + 0)) \\
   \Rightarrow  &\; \ldots  \;\; 3
\end {aligned}
]]></fr:tex><html:p>Most list processing involves <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  This is a simple example; patterns
can be more complex.  Observe the use of a vertical bar <html:code>|</html:code> to separate the function’s
clauses.  We have <html:em>one</html:em> function declaration that handles two cases.
To understand its role, consider the following faulty code:</html:p><html:pre><![CDATA[# let rec nlength [] = 0
Line 1, characters 17-19:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_

val nlength : 'a list -> int = <fun>
# let rec nlength (x::xs) = 1 + nlength xs
Line 1, characters 17-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val nlength : 'a list -> int = <fun>]]></html:pre><html:p>These are two declarations, not one.  First we declare <html:code>nlength</html:code> to be a
function that handles only empty lists.  Then we redeclare it to be a function
that handles only non-empty lists; it can never deliver a result.  We see that
a second <html:code>let</html:code> declaration replaces any previous one rather than extending it
to cover new cases.</html:p><html:p>Now, let us return to our original declaration of <html:code>nlength</html:code>.  The length function
is <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link></html:em> and applies to <html:em>all</html:em> lists regardless of element
type!  Most programming languages lack such flexibility.</html:p><html:p>Unfortunately, this length computation is naive and wasteful.  Like
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link> earlier, it is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">tail-recursive</fr:link>.  It
uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its input.  As usual, the
solution is to add an accumulating argument.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:uri><fr:display-uri>focs-seq-consume</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:route><fr:title
text="Consuming a Sequence">Consuming a Sequence</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec get n s =
    match n, s with
    | 0, _            -> []
    | n, Nil          -> []
    | n, Cons (x, xf) -> x :: get (n-1) (xf ())
val get : int -> 'a seq -> 'a list = <fun>]]></html:pre><html:p>The above code gets the first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements as a list.
<html:code>xf ()</html:code> <html:em>forces</html:em> evaluation.</html:p><html:p>The function <html:code>get</html:code> converts a sequence to a list.  It takes the
first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements; it takes all of them if <fr:tex
display="inline"><![CDATA[n<0]]></fr:tex>, which can terminate only if
the sequence is finite.</html:p><html:p>In the last line of <html:code>get</html:code>, the expression <html:code>xf()</html:code> calls the tail
function, demanding evaluation of the next element.  This operation is called
<html:em>forcing</html:em> the sequence.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/</fr:uri><fr:display-uri>focs-length</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-length/</fr:route><fr:title
text="Efficiently Computing the Length of a List">Efficiently Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec addlen n = function
  | []    -> n
  | x::xs -> addlen (n + 1) xs
val addlen : int -> 'a list -> int = <fun>
# addlen 0 [5; 6; 7]
- : int = 3]]></html:pre><html:p>Recall that the use of <html:code>function</html:code> introduces an extra (unnamed) argument
that is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matched</fr:link> in the subsequent clauses; in this case, to break
open the list.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {addlen }0 [a; b; c] \Rightarrow  &\;  \text {addlen }1\;[b; c] \\
  \Rightarrow   &\; \text {addlen }2\;[c] \\
  \Rightarrow   &\; \text {addlen }3\;[] \\
  \Rightarrow   &\; 3
\end {aligned}
]]></fr:tex><html:p>Function <html:code>addlen</html:code> is again <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.  Its type mentions the integer
accumulator.</html:p><html:p>Now we may declare an efficient length function.  It is simply a wrapper for
<html:code>addlen</html:code>, supplying zero as the initial value of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# let length xs = addlen 0 xs
val length : 'a list -> int = <fun>
# length [5; 6; 7; 8]
- : int = 4]]></html:pre><html:p>The recursive calls do not nest: this version is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It takes <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
space.  Obviously its time requirement is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> because it takes at least <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
steps to find the length of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/</fr:uri><fr:display-uri>focs-power</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-power/</fr:route><fr:title
text="Efficiently Raising a Number to a Power">Efficiently Raising a Number to a Power</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec power x n =
    if n = 1 then x
    else if even n then
      power (x *. x) (n / 2)
    else
      x *. power (x *. x) (n / 2)
val power : float -> int -> float = <fun>]]></html:pre><html:p><html:em>Mathematical Justification</html:em></html:p><fr:tex
display="block"><![CDATA[\begin {aligned}
           x^1 & = x \\
           x^{2n} & = (x^2)^n  \\
           x^{2n+1} & = x\times (x^2)^n.
\end {aligned}]]></fr:tex><html:p>For large <html:code>n</html:code>, computing powers using <fr:tex
display="inline"><![CDATA[x^{n+1} = x\times  x^n]]></fr:tex> is too slow to
be practical.  The equations above are much faster. Example:</html:p><fr:tex
display="block"><![CDATA[ 2^{12} = 4^6 = 16^3 = 16\times  256^1 = 16\times  256 = 4096. ]]></fr:tex><html:p>Instead of <html:code>n</html:code> multiplications, we need at most <fr:tex
display="inline"><![CDATA[2\lg  n]]></fr:tex> multiplications,
where <fr:tex
display="inline"><![CDATA[\lg  n]]></fr:tex> is the logarithm of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to the base <fr:tex
display="inline"><![CDATA[2]]></fr:tex>.</html:p><html:p>We use the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>even</html:code></fr:link>, declared previously, to test whether the
exponent is even.  Integer division (<html:code>/</html:code>) truncates its result to an
integer: dividing <fr:tex
display="inline"><![CDATA[2n+1]]></fr:tex> by 2 yields <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>A recurrence is a useful computation rule only if it is bound to terminate.
If <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex> then <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is smaller than both <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> and <fr:tex
display="inline"><![CDATA[2n+1]]></fr:tex>.  After enough
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive calls</fr:link>, the exponent will be reduced to <fr:tex
display="inline"><![CDATA[1]]></fr:tex>.  The equations also hold
if <fr:tex
display="inline"><![CDATA[n\leq 0]]></fr:tex>, but the corresponding computation runs forever.</html:p><html:p>Our reasoning assumes arithmetic to be <html:em>exact</html:em>. Fortunately, the calculation is
well-behaved using floating-point.</html:p><html:p>Computer numbers have a finite range, which if exceeded results in the
integer wrapping around.  You will understand this behaviour more as you
learn about computer architecture and how modern systems represent
numbers in memory.</html:p><html:p>If integers and floats must be combined in a calculation, OCaml provides functions
to convert between them:</html:p><html:pre><![CDATA[# int_of_float 3.14159
- : int = 3
# float_of_int 3
- : float = 3.]]></html:pre><html:p>OCaml’s libraries are organised using “modules”, so we may use compound
identifiers such as <html:code>Float.of_int</html:code> to refer to library functions. There
are many thousands of library functions available in the OCaml ecosystem,
including text-processing and operating systems functions in addition to the
usual numerical ones.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:uri><fr:display-uri>focs-tree-traversal-efficient</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:route><fr:title
text="Efficiently Traversing Trees">Efficiently Traversing Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>Unfortunately, the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">traversal functions</fr:link> are quadratic in the
worst case: the appends in the recursive calls are inefficient.  To correct
that problem, we (as usual) add an accumulating argument.  Observe how
each function constructs its result list and compare with how appends were
eliminated from <html:code>quicksort</html:code> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">Sorting lecture</fr:link>.</html:p><html:pre><![CDATA[# let rec preord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      v :: preord (t1, preord (t2, vs))
val preord : 'a tree * 'a list -> 'a list = <fun>
# let rec inord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      inord (t1, v::inord (t2, vs))
val inord : 'a tree * 'a list -> 'a list = <fun>
# let rec postord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      postord (t1, postord (t2, v::vs))
val postord : 'a tree * 'a list -> 'a list = <fun>]]></html:pre><html:p>One can prove equations relating each of these functions to its counterpart on
the previous section.  For example:</html:p><fr:tex
display="block"><![CDATA[\texttt {inord}(t, vs) = \texttt {inorder}(t) @ vs]]></fr:tex><html:p>These three types of tree traversal are related in that all are depth-first.
They each traverse the left subtree in full before traversing the right
subtree.  Breadth-first search (from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queues/"
title="Queues and Search Strategies"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queues/"
display-uri="focs-queues"
type="local">Queues lecture</fr:link>) is another
possibility.  That involves going through the levels of a tree one at a time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-expression-evaluation/</fr:uri><fr:display-uri>focs-expression-evaluation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-expression-evaluation/</fr:route><fr:title
text="Expression Evaluation">Expression Evaluation</fr:title></fr:frontmatter><fr:mainmatter><html:p>Expression evaluation concerns expressions and the values they return. This
view of computation may seem to be too narrow. It is certainly far removed from
computer hardware, but that can be seen as an advantage. For the traditional
concept of computing solutions to problems, expression evaluation is entirely
adequate.</html:p><html:p>Starting with <fr:tex
display="inline"><![CDATA[E_0]]></fr:tex>, the expression <fr:tex
display="inline"><![CDATA[E_i]]></fr:tex> is reduced to <fr:tex
display="inline"><![CDATA[E_{i+1}]]></fr:tex> until this
process concludes with a value <fr:tex
display="inline"><![CDATA[v]]></fr:tex>.  A <html:em>value</html:em> is something like a number
that cannot be further reduced.</html:p><html:p>We write <fr:tex
display="inline"><![CDATA[E \rightarrow  E']]></fr:tex> to say that <fr:tex
display="inline"><![CDATA[E]]></fr:tex> is <html:em>reduced</html:em> to <fr:tex
display="inline"><![CDATA[E']]></fr:tex>.
Mathematically, they are equal: <fr:tex
display="inline"><![CDATA[E=E']]></fr:tex>, but the computation goes from <fr:tex
display="inline"><![CDATA[E]]></fr:tex> to
<fr:tex
display="inline"><![CDATA[E']]></fr:tex> and never the other way around.</html:p><html:p>Computers also interact with the outside world.  For a start, they need some
means of accepting problems and delivering solutions.  Many computer systems
monitor and control industrial processes.  This role of computers is familiar
now, but was never envisaged in the early days. Computer pioneers focused on
mathematical calculations.  Modelling interaction and control requires a notion
of <html:em>states</html:em> that can be observed and changed.  Then we can consider
updating the state by assigning to variables or performing input/output,
finally arriving at conventional programs as coded in C, for instance.</html:p><html:p>For now, we remain at the level of expressions, which is usually termed
<html:em>functional programming</html:em>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:uri><fr:display-uri>focs-insertion-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:route><fr:title
text="Insertion Sort">Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:p>An insert operation does <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> comparisons on average.</html:p><html:pre><![CDATA[# let rec ins x = function
    | [] -> [x]
    | y::ys -> if x <= y then x :: y :: ys
               else y :: ins x ys
val ins : 'a -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Insertion sort</html:em> takes <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons on average:</html:p><html:pre><![CDATA[let rec insort = function
    | [] -> []
    | x::xs -> ins x (insort xs)]]></html:pre><html:p>Items from the input are copied one at a time to the output.  Each new item is
inserted into the right place so that the output is always in order.</html:p><html:p>We could easily write <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> versions of these functions, but to no purpose.
Insertion sort is slow because it does <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons (and a lot of list
copying), not because it is recursive.  Its quadratic runtime makes it nearly
useless: it takes 174 seconds for our example while the next-worst figure is
1.4 seconds.</html:p><html:p>Insertion sort is worth considering because it is easy to code and illustrates
the concepts.  Two efficient sorting algorithms, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link> and heapsort, can be
regarded as refinements of insertion sort.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/</fr:uri><fr:display-uri>focs-while</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-while/</fr:route><fr:title
text="Iteration: the while command">Iteration: the while command</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let tlopt = function
  | [] -> None
  | _::xs -> Some xs
val tlopt : 'a list -> 'a list option = <fun>
# let length xs =
    let lp  = ref xs in (* list of uncounted elements *)
    let np  = ref 0  in (* accumulated count *)
    let fin = ref false in
    while not !fin do
      match tlopt !lp with
      | None -> fin := true
      | Some xs ->
          lp := xs;
          np := 1 + !np
    done;
    !np (* the final count is returned *)
val length : 'a list -> int = <fun>]]></html:pre><html:p>Once we can change the state, we need to do so repeatedly.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">Recursion</fr:link> can
serve this purpose, but having to declare a procedure for every loop is
clumsy, and compilers for conventional languages seldom exploit
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
title="Recursion vs Iteration"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
display-uri="focs-recursion-vs-iteration"
type="local">tail-recursion</fr:link>.</html:p><html:p>Early programming languages provided little support for repetition.  The
programmer had to set up loops using goto commands, exiting the loop using
another goto controlled by an <html:code>if</html:code>.  Modern languages provide a
confusing jumble of looping constructs, the most fundamental of which is
<html:code>while B do C</html:code>.  The boolean expression <fr:tex
display="inline"><![CDATA[B]]></fr:tex> is evaluated,
and if true, command <fr:tex
display="inline"><![CDATA[C]]></fr:tex> is executed and the command repeats.  If <fr:tex
display="inline"><![CDATA[B]]></fr:tex>
evaluates to false then the <html:code>while</html:code> command terminates, perhaps without
executing <fr:tex
display="inline"><![CDATA[C]]></fr:tex> even once.</html:p><html:p>OCaml’s main looping construct is <html:code>while</html:code>, which returns the value <html:code>()</html:code>.  The
function <html:code>length</html:code> declares <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> to hold the list under
examination (<html:code>lp</html:code>) and number of elements counted so far (<html:code>np</html:code>) as well
as whether the end of the list has been reached (the boolean reference <html:code>fin</html:code>).
While the list is non-empty, we skip over one more element (by setting it to
its tail) and count that element.</html:p><html:p>The body of the <html:code>while</html:code> loop first checks to see if the end of the list has
been reached, in which case it sets the <html:code>fin</html:code> variable to true.  If there is a
tail value, then two assignments are executed in sequence.  The <html:code>lp</html:code> reference
is set to the tail of the list, and the <html:code>np</html:code> reference integer is incremented
by one.  When the while loop terminates due to the <html:code>fin</html:code> variable being set to
true, the expression <html:code>!np</html:code> returns the computed length as the function’s
result.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/</fr:uri><fr:display-uri>focs-summing-iter</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-summing-iter/</fr:route><fr:title
text="Iteratively summing the first n integers">Iteratively summing the first n integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec summing n total =
    if n = 0 then
      total
    else
      summing (n - 1) (n + total)
val summing : int -> int -> int = <fun>]]></html:pre><html:p>Function <html:code>summing</html:code> takes an additional argument: a running total.  If
<html:code>n</html:code> is zero then it returns the running total; otherwise, <html:code>summing</html:code>
adds to it and continues.  The recursive calls do not nest; the additions are
done immediately.</html:p><html:p>A recursive function whose computation does not nest is called
<html:em>iterative</html:em> or <html:em>tail-recursive</html:em>. Many functions can be made iterative by
introducing an argument analogous to <html:code>total</html:code>, which is often called an
<html:em>accumulator</html:em>.</html:p><html:p>The gain in efficiency is sometimes worthwhile and sometimes not.  The function
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> is not iterative because nesting occurs whenever the exponent is odd.
Adding a third argument makes it iterative, but the change complicates the
function and the gain in efficiency is minute; for 32-bit integers, the maximum
possible nesting is 30 for the exponent <fr:tex
display="inline"><![CDATA[2^{31}-1]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:uri><fr:display-uri>focs-seq-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:route><fr:title
text="Joining Two Sequences">Joining Two Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec appendq xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons(x, fun () -> appendq (xf ()) yq)
val appendq : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>A more fair alternative:</html:p><html:pre><![CDATA[# let rec interleave xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons (x, fun () -> interleave yq (xf ()))
val interleave : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>Most list functions and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> have analogues on sequences, but strange
things can happen.  Can an infinite list be reversed?</html:p><html:p>Function <html:code>appendq</html:code> is precisely the same idea as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>
from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">Lists lecture</fr:link>; it concatenates two sequences.  If the first
argument is infinite, then <html:code>appendq</html:code> never gets to its second argument,
which is lost.  Concatenation of infinite sequences is not terribly
interesting.</html:p><html:p>The function <html:code>interleave</html:code> avoids this problem by exchanging the two
arguments in each recursive call.  It combines the two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, losing no
elements.  Interleaving is the right way to combine two potentially infinite
information sources into one.</html:p><html:p>In both function declarations, observe that each <html:code>xf ()</html:code> is enclosed
within a <fr:tex
display="inline"><![CDATA[{\tt  fun () \rightarrow  \ldots }]]></fr:tex>.  Each <html:em>force</html:em> is enclosed within a
<html:em>delay</html:em>.  This practice makes the functions lazy.  A force not enclosed
in a delay, as in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-seq-consume/"
title="Consuming a Sequence"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/"
display-uri="focs-seq-consume"
type="local"><html:code>get</html:code></fr:link> above, runs the risk of evaluating the sequence
in full.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/</fr:uri><fr:display-uri>focs-take-drop</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-take-drop/</fr:route><fr:title
text="List Utilities: take and drop">List Utilities: take and drop</fr:title></fr:frontmatter><fr:mainmatter><html:p>This lecture examines more list utilities, illustrating more patterns of
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>, and concludes with a small program for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.</html:p><html:p>The functions <html:code>take</html:code> and <html:code>drop</html:code> divide a list
into parts, returning or discarding the first <fr:tex
display="inline"><![CDATA[i]]></fr:tex> elements.</html:p><fr:tex
display="block"><![CDATA[xs = [\underbrace {x_0,\ldots ,x_{i-1}}_{\text {take i xs}},
      \underbrace {x_i,\ldots ,x_{n-1}}_{\text {drop i xs}} ]]]></fr:tex><html:p>They can be implemented in OCaml as follows:</html:p><html:pre><![CDATA[# let rec take i = function
    | [] -> []
    | x::xs ->
        if i > 0 then x :: take (i - 1) xs
        else []
val take : int -> 'a list -> 'a list = <fun>
# let rec drop i = function
    | [] -> []
    | x::xs ->
        if i > 0 then drop (i-1) xs
        else x::xs
val drop : int -> 'a list -> 'a list = <fun>]]></html:pre><html:p>Applications of <html:code>take</html:code> and <html:code>drop</html:code> will appear in future lectures.  Typically,
they divide a collection of items into equal parts for recursive processing.</html:p><html:p>The <html:code>take</html:code> function is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>, but making it so would not improve
its efficiency.  The task requires copying up to <fr:tex
display="inline"><![CDATA[i]]></fr:tex> list elements, which must
take <fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> space and time.</html:p><html:p>Function <html:code>drop</html:code> simply skips over <fr:tex
display="inline"><![CDATA[i]]></fr:tex> list elements.  This requires
<fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> time but only constant space.  It is iterative and much faster than
<html:code>take</html:code>.  Both functions use <fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> time, but skipping elements is faster
than copying them:  <html:code>drop</html:code>’s constant factor is smaller.</html:p><html:p>Both functions take an integer and a list, returning a list of the same type.
So their type is <html:code>int -&gt; 'a list -&gt; 'a list</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:uri><fr:display-uri>focs-change-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:route><fr:title
text="Making Change with Exceptions">Making Change with Exceptions</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Change
  let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise Change
    | c::till, amt -> if amt < 0 then raise Change
                      else try c :: change (c::till) (amt - c)
                           with Change -> change till amt
exception Change
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>In the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">Lists lectures</fr:link>, we considered the problem of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.  The greedy
algorithm presented there could not express “6 using 5 and 2” because it always
took the largest coin.  Returning <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">the list of all possible solutions</fr:link> avoids
that problem rather expensively: we only need one solution.</html:p><html:p>Using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>, we can code a <html:em>backtracking</html:em> algorithm: one that can undo
past decisions if it comes to a dead end.  The exception <html:code>Change</html:code> is raised if
we run out of coins (with a non-zero amount) or if the amount goes negative.
We always try the largest coin, but enclose the recursive call in an exception
handler, which undoes the choice if it goes wrong.</html:p><html:p>Carefully observe how exceptions interact with <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  The exception
handler always undoes the <html:em>most recent</html:em> choice, leaving others possibly to
be undone later.  If making change really is impossible, then eventually
<html:code>exception Change</html:code> will be raised with no handler to catch it, and it
will be reported at top level.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-trace/</fr:uri><fr:display-uri>focs-change-trace</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-trace/</fr:route><fr:title
text="Making Change: A Trace">Making Change: A Trace</fr:title></fr:frontmatter><fr:mainmatter><html:p>Here is the full execution. Observe how the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception handlers</fr:link> nest and how
they drop away once the given expression has returned a value.</html:p><fr:tex
display="block"><![CDATA[\begin{aligned}
\text{change [5; 2] 6}
  \Rightarrow &\; \text{try 5::change [5; 2] 1}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{try 5::(try 5::change [5; 2] (-4)}\\
              &\; \text{with Change -> change [2] 1)}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{5::(change [2] 1)}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{try 5::(try 2::change [2] (-1)}\\
              &\; \text{with Change -> change [] 1)}\\
              &\; \text{with Change -> change [2] 6} \\
  \Rightarrow &\; \text{try 5::(change [] 1)}\\
              &\; \text{with Change -> change [2] 6} \\
  \Rightarrow &\; \text{change [2] 6} \\
  \Rightarrow &\; \text{try 2::change [2] 4}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::change [2] 2}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::(try 2::change [2] 0 }\\
              &\; \text{with Change -> change [] 2)}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::[2]}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::[2; 2]}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{[2; 2; 2]}
\end{aligned}]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge/</fr:uri><fr:display-uri>focs-merge</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge/</fr:route><fr:title
text="Merging Two Lists">Merging Two Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Merge joins two sorted lists.</html:p><html:pre><![CDATA[# let rec merge = function
    | [], ys -> ys
    | xs, [] -> xs
    | x::xs, y::ys ->
        if x <= y then
          x :: merge (xs, y::ys)
        else
          y :: merge (x::xs, ys)
val merge : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>Generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insert</fr:link> to two lists, and does at most <fr:tex
display="inline"><![CDATA[m+n-1]]></fr:tex> comparisons.</html:p><html:p><html:em>Merging</html:em> means combining two sorted lists to form a larger sorted list.
It does at most <fr:tex
display="inline"><![CDATA[m+n]]></fr:tex> comparisons, where <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are the lengths of the
input lists.  If <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are roughly equal then we have a fast way of
constructing sorted lists; if <fr:tex
display="inline"><![CDATA[n=1]]></fr:tex> then merging degenerates to insertion,
doing much work for little gain.</html:p><html:p>Merging is the basis of several sorting algorithms; we look at a
divide-and-conquer one.  Mergesort is seldom found in conventional programming
because it is hard to code for arrays; it works nicely with lists.  It divides
the input (if non-trivial) into two roughly equal parts, sorts them
recursively, then merges them.</html:p><html:p>Function <html:code>merge</html:code> is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>; the recursion is deep.  An iterative
version is of little benefit for the same reasons that apply to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">earlier lecture on Lists</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/</fr:uri><fr:display-uri>focs-quicksort-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-idea/</fr:route><fr:title
text="Quicksort: The Idea">Quicksort: The Idea</fr:title></fr:frontmatter><fr:mainmatter><html:p>The Quicksort algorithm has the following flow:</html:p><html:ul><html:li>Choose a <html:em>pivot</html:em> element, <fr:tex
display="inline"><![CDATA[a]]></fr:tex></html:li>
  <html:li>Divide to partition the input into two sublists:
    <html:ul><html:li>those <html:em>at most</html:em> <fr:tex
display="inline"><![CDATA[a]]></fr:tex> in value</html:li>
      <html:li>those <html:em>exceeding</html:em> <fr:tex
display="inline"><![CDATA[a]]></fr:tex></html:li></html:ul></html:li>
  <html:li>Conquer using recursive calls to sort the sublists</html:li>
  <html:li>Combine the sorted lists by appending one to the other</html:li></html:ul><html:p>Quicksort was invented by Sir Anthony Hoare (1934–2026), who in later life worked at Microsoft
Research, Cambridge.  Quicksort works by <html:em>divide and conquer,</html:em> a basic algorithm design
principle.  Quicksort chooses from the input some value <fr:tex
display="inline"><![CDATA[a]]></fr:tex>, called the
<html:em>pivot</html:em>.  It partitions the remaining items into two parts: those <fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>, and
those <fr:tex
display="inline"><![CDATA[>a]]></fr:tex>.  It sorts each part recursively, then puts the smaller part before
the greater.</html:p><html:p>The cleverest feature of Hoare's algorithm was that the partition could be done
<html:em>in place</html:em> by exchanging array elements.  Quicksort was invented before
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link> was well known, and people found it extremely hard to understand.  As
usual, we shall consider a list version based on functional programming.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/</fr:uri><fr:display-uri>focs-npower</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-npower/</fr:route><fr:title
text="Raising a Number to a Power">Raising a Number to a Power</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec npower x n =
    if n = 0 then 1.0
    else x *. npower x (n - 1)
val npower : float -> int -> float = <fun>]]></html:pre><html:p>Our new <html:code>npower</html:code> definition can now take additional arguments, reflected in the arrows
present in the type of <html:code>npower</html:code>; these represent <html:em>parameters</html:em> that can be passed to the
new value being defined, with the final segment being the resulting type. Thus our <html:code>npower</html:code>
type can be read as "pass in a float and integer to return a float".</html:p><html:p><html:em>Mathematical Justification</html:em> (for <fr:tex
display="inline"><![CDATA[x\not =0]]></fr:tex>):</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
           x^0 & = 1 \\
           x^{n+1} & = x\times  x^n.
\end {aligned}
]]></fr:tex><html:p>The function <html:code>npower</html:code> raises its float argument <html:code>x</html:code> to the power <html:code>n</html:code>, a
non-negative integer. The function is <html:strong>recursive</html:strong>: it calls itself.  You
can spot a recursive function due to the <html:code>rec</html:code> keyword in the definition:
this indicates that any invocation of the function name within the function body should call itself.
This concept should be familiar from mathematics, since exponentiation is defined by the
rules shown above. You may also have seen recursion in the product rule for
differentiation: <fr:tex
display="inline"><![CDATA[(u\cdot  v)' = u\cdot  v' + u'\cdot  v]]></fr:tex>. In finding the derivative of <fr:tex
display="inline"><![CDATA[u\cdot  v]]></fr:tex>,
we recursively find the derivatives of <fr:tex
display="inline"><![CDATA[u]]></fr:tex> and <fr:tex
display="inline"><![CDATA[v]]></fr:tex>, combining them to obtain the desired result.
The recursion is meaningful because it terminates: we reduce the problem to two smaller
problems, and this cannot go on forever. The OCaml programmer uses recursion
heavily.  For <fr:tex
display="inline"><![CDATA[n\geq 0]]></fr:tex>, the equation <fr:tex
display="inline"><![CDATA[x^{n+1} = x\times  x^n]]></fr:tex> yields an obvious
computation:</html:p><fr:tex
display="block"><![CDATA[ x^3 = x\times  x^2 = x\times  x\times  x^1 = x\times  x\times  x\times  x^0 = x\times  x\times  x ]]></fr:tex><html:p>The equation clearly holds even for negative <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. However, the corresponding
computation runs forever:</html:p><fr:tex
display="block"><![CDATA[ x^{-1} = x\times  x^{-2} = x\times  x\times  x^{-3}=\cdots  ]]></fr:tex><html:p>Note that the function <html:code>npower</html:code> contains both an integer constant (<html:code>0</html:code>) and a
floating point constant (<html:code>1.0</html:code>). The decimal point makes all the difference.
OCaml will notice and ascribe different meaning to each type of constant.</html:p><html:pre><![CDATA[# let square x = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>Now for a tiresome but necessary aside. In most languages, the types of
arguments and results must always be specified. OCaml is unusual that it normally
infers the types itself. However, sometimes it is useful to supply a hint to
help you debug and develop your program. OCaml will still infer the types even if you don’t specify them, but in some cases
it will use a more inefficient function than a specialised one. Some languages
have just one type of number, converting automatically between different
formats; this is slow and could lead to unexpected rounding errors.  Type
constraints are allowed almost anywhere. We can put one on any occurrence of x
in the function.</html:p><html:pre><![CDATA[# let square (x : float) = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>Or we can constrain the type of the function’s result:</html:p><html:pre><![CDATA[# let square x : float = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>OCaml treats the equality and comparison test specially. Expressions like <html:code>if x = y then</html:code> …
are allowed provided <html:code>x</html:code> and <html:code>y</html:code> have the same type and equality testing is
possible for that type. (We discuss <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local">equality</fr:link> further in a later lecture.)
Note that <html:code>x &lt;&gt; y</html:code> is OCaml for <fr:tex
display="inline"><![CDATA[x\not =y]]></fr:tex>.</html:p><html:p>A characteristic feature of the computer is its ability to test for conditions
and act accordingly.  In the early days, a program might jump to a given
address depending on the sign of some number.  Later, John McCarthy defined
the <html:em>conditional expression</html:em> to satisfy <html:code>if true then x else y = x</html:code> and
<html:code>if false then x else y = y</html:code>.</html:p><html:p>OCaml evaluates the expression <html:code>if</html:code> <fr:tex
display="inline"><![CDATA[B]]></fr:tex> <html:code>then</html:code> <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> <html:code>else</html:code> <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex> by first evaluating <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.
If the result is <html:code>true</html:code> then OCaml evaluates <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> and otherwise <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex>.  Only one
of the two expressions <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex> is evaluated!  If both were evaluated,
then recursive functions like <html:code>npower</html:code> above would run forever.</html:p><html:p>The <html:code>if</html:code>-expression is governed by an expression of type <html:code>bool</html:code>, whose two
values are <html:code>true</html:code> and <html:code>false</html:code>.  In modern programming languages, tests are not
built into “conditional branch” constructs but can just be part of normal expressions.
Tests, or <html:em>Boolean expressions,</html:em> can be expressed using relational operators
such as <html:code>&lt;</html:code> and <html:code>=</html:code>. They can be combined using the Boolean operators for
negation (<html:code>not</html:code>), conjunction (written as <html:code>&amp;&amp;</html:code>) and disjunction (written as <html:code>||</html:code>).  New
properties can be declared as functions: here, to test whether an integer is
even, for example:</html:p><html:pre><![CDATA[# let even n = n mod 2 = 0
val even : int -> bool = <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/</fr:uri><fr:display-uri>focs-def-recursion</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-recursion/</fr:route><fr:title
text="Recursion">Recursion</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A function is recursive if it calls itself. You can spot a recursive function
by the <html:code>rec</html:code> keyword in its definition: this indicates that any invocation
of the function name within the function body should call itself. The recursion
is meaningful because it terminates: we reduce the problem to smaller problems,
and this cannot go on forever.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local">Raising a Number to a Power</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/</fr:uri><fr:display-uri>focs-recursion-vs-iteration</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/</fr:route><fr:title
text="Recursion vs Iteration">Recursion vs Iteration</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>“Iterative” normally refers to a loop, coded using <html:code>while</html:code> for example (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural/"
title="Elements of Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/"
display-uri="focs-procedural"
type="local">final lecture</fr:link>)</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">Tail-recursion</fr:link> is only efficient if the compiler detects it</html:li>
  <html:li>Mainly it saves space (memory), though iterative code can also run faster</html:li>
  <html:li>Do not make programs iterative unless the gain is worth it</html:li></html:ul><html:p>A <fr:link
href="https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs"
type="external">classic book</fr:link>
by Abelson and Sussman, which describes the Lisp dialect known as Scheme,
used <html:em>iterative</html:em> to mean <html:em>tail-recursive</html:em>. Iterative functions produce computations
resembling those that can be done using while-loops in conventional languages.</html:p><html:p>Many algorithms can be expressed naturally using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>, but only awkwardly
using iteration. There is a story that Dijkstra sneaked recursion into Algol-60
by inserting the words “any other occurrence of the procedure name denotes
execution of the procedure.” By not using the word “recursion”, he managed to
slip this amendment past sceptical colleagues.</html:p><html:p>Obsession with tail recursion leads to a coding style in which functions
have many more arguments than necessary.  Write straightforward code first,
avoiding only gross inefficiency.  If the program turns out to be too slow,
tools are available for pinpointing the cause.  Always remember KISS (Keep
It Simple, Stupid).</html:p><html:p>I hope you have all noticed by now that the summation can be done even more
efficiently using the arithmetic progression formula:</html:p><fr:tex
display="block"><![CDATA[1+\cdots +n = n(n+1)/2]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/</fr:uri><fr:display-uri>focs-rev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-rev/</fr:route><fr:title
text="Reversing a List in O(n)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec rev_app xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> rev_app xs (x::ys)
val rev_app : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {rev\_app }[a; b; c]\;[] \Rightarrow  &\; \text {rev\_app }[b; c]\; [a] \\
  \Rightarrow  &\; \text {rev\_app }[c]\; [b; a] \\
  \Rightarrow  &\; \text {rev\_app }[]\; [c; b; a] \\
  \Rightarrow  &\; [c; b; a]
\end {aligned}
]]></fr:tex><html:p>Calling <html:code>rev_app xs ys</html:code> reverses the elements of <html:code>xs</html:code> and
prepends them to <html:code>ys</html:code>.  Now we may declare</html:p><html:pre><![CDATA[# let rev xs = rev_app xs []
val rev : 'a list -> 'a list = <fun>
# rev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><html:p>It is easy to see that this reverse function performs just <fr:tex
display="inline"><![CDATA[n]]></fr:tex> conses, given
an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.  For both reverse functions, we could count the number of
conses precisely—not just up to a constant factor.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-o-notation/"
title="Comparing Algorithms: O Notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/"
display-uri="focs-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> is still
useful to describe the overall running time: the time taken by a cons
varies from one system to another.</html:p><html:p>The accumulator <fr:tex
display="inline"><![CDATA[y]]></fr:tex> makes the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  But the gain in complexity
arises from the removal of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.  Replacing an expensive operation (append)
by a series of cheap operations (cons) is called <html:em>reduction in strength</html:em>
and is a common technique in computer science.  It originated when many
computers did not have a hardware multiply instruction; the series of products
<fr:tex
display="inline"><![CDATA[i\times  r]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, <fr:tex
display="inline"><![CDATA[\ldots , n]]></fr:tex> could more efficiently be computed by
repeated addition.  Reduction in strength can be done in various ways; we
shall see many instances of removing append.</html:p><html:p>Consing to an accumulator produces the result in reverse.  If
that forces the use of an extra list reversal then the iterative function
may be much slower than the recursive one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nrev/</fr:uri><fr:display-uri>focs-nrev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nrev/</fr:route><fr:title
text="Reversing a List in O(n^2)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:p>Let us consider one way to reverse a list.</html:p><html:pre><![CDATA[# let rec nrev = function
  | [] -> []
  | x::xs -> (nrev xs) @ [x]
val nrev : 'a list -> 'a list = <fun>
# nrev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nrev }[a; b; c] \Rightarrow  &\; \text {nrev }[b; c]\;@\;[a] \\
  \Rightarrow  &\;  (\text {nrev }[c]\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  ((\text {nrev }[]\;@\;[c])\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  (([]\;@\;[c])\;@\;[b])\;@\;[a] \ \ldots  \ [c; b; a]
\end {aligned}
]]></fr:tex><html:p>This reverse function is grossly inefficient due to poor usage of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>, which
copies its first argument.  If <html:code>nrev</html:code> is given a list of length <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>, then
append makes <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> conses to copy the reversed tail.  Constructing the list
<html:code>[x]</html:code> calls <html:code>cons</html:code> again, for a total of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> calls.  Reversing the tail
requires <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> more conses, and so forth.  The total number of conses is:</html:p><fr:tex
display="block"><![CDATA[ 0 + 1 + 2 + \cdots  + n = {n(n+1)/2} ]]></fr:tex><html:p>The time complexity is therefore <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Space complexity is only <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>
because the copies don’t all exist at the same time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-evaluation/</fr:uri><fr:display-uri>focs-seq-evaluation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-evaluation/</fr:route><fr:title
text="Sample Evaluation">Sample Evaluation</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {aligned}
\tt  get(2,\, from \; 6) \\
\tt  get(2,\, Cons(6, fun \; () \rightarrow  from \; (6+1))) \\
\tt  6 :: get(1,\, from \; (6+1)) \\
\tt  6 :: get(1,\, Cons \; (7,\, fun \; () \rightarrow  from \; (7+1))) \\
\tt  6 :: 7 :: get(0,\, Cons \; (8,\, fun \; () \rightarrow  from \; (8+1))) \\
\tt  6 :: 7 :: [] \\
\tt  [6; 7]
\end {aligned}
]]></fr:tex><html:p>Here we ask for two elements of the infinite sequence.  In fact, three
elements are computed: 6, 7 and 8.  Our implementation is slightly too eager.
A more complicated <html:code>type</html:code> declaration could avoid this problem.
Another problem is that if one repeatedly examines some particular list
element using forcing, that element is repeatedly evaluated.  In a lazy
programming language, the result of the first evaluation would be stored for
later reference.  To get the same effect in OCaml requires the use of
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local">references</fr:link>.</html:p><html:p>We should be grateful that the potentially infinite computation is kept
finite.  The tail of the original sequence even contains the unevaluated
expression 6+1.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sample-costs/</fr:uri><fr:display-uri>focs-sample-costs</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sample-costs/</fr:route><fr:title
text="Sample costs in O notation">Sample costs in O notation</fr:title></fr:frontmatter><fr:mainmatter><html:p>Recall that <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> computes <fr:tex
display="inline"><![CDATA[x^n]]></fr:tex>
by repeated multiplication while <fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link> naively computes the sum
<fr:tex
display="inline"><![CDATA[1+\cdots +n]]></fr:tex>.  Each obviously performs <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> arithmetic operations.  Because
they are not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">tail recursive</fr:link>, their use of space is also <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  The function
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-summing-iter/"
title="Iteratively summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/"
display-uri="focs-summing-iter"
type="local"><html:code>summing</html:code></fr:link> is a version of <html:code>nsum</html:code> with an accumulating argument;
its iterative behaviour lets it work in constant space.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> spares
us from having to specify the units used to measure space.</html:p><html:table>
  <html:tr><html:th>Function</html:th><html:th>Time</html:th><html:th>Space</html:th></html:tr>
  <html:tr><html:td>npower, nsum</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>summing</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n(n+1)/2]]></fr:tex></html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>power</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[\log ~n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[\log ~n]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>sillySum</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[2^n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td></html:tr>
</html:table><html:p>Even ignoring constant factors, the units chosen can influence the result.
Multiplication may be regarded as a single unit of cost.  However, the cost of
multiplying two <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-digit numbers for large <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is itself an important
question, especially now that public-key cryptography uses numbers hundreds of
digits long.</html:p><html:p>Few things can <html:em>really</html:em> be done in constant time or stored in constant
space.  Merely to store the number <fr:tex
display="inline"><![CDATA[n]]></fr:tex> requires <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> bits.  If a
program cost is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>, then we have probably assumed that certain operations
it performs are also <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>—typically because we expect never to exceed the
capacity of the standard hardware arithmetic.</html:p><html:p>With <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link>, the precise number of operations depends upon <fr:tex
display="inline"><![CDATA[n]]></fr:tex> in a
complicated way, depending on how many odd numbers arise, so it is convenient
that we can just write <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  An accumulating argument could reduce its
space cost to <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sillysum/</fr:uri><fr:display-uri>focs-sillysum</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sillysum/</fr:route><fr:title
text="Silly Summing the First n Integers">Silly Summing the First n Integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec sillySum n =
    if n = 0 then
      0
    else
      n + (sillySum (n - 1) + sillySum (n - 1)) / 2
val sillySum : int -> int = <fun>]]></html:pre><html:p>The function calls itself <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> times!  Bigger inputs mean higher costs—but
what’s the growth rate?</html:p><html:p>Now let us consider how to estimate various costs associated with a program.
<html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local">Asymptotic complexity</fr:link></html:em> refers to how costs—usually time or space—grow with
increasing inputs. Space complexity can never exceed time complexity, for it
takes time to do anything with the space.  Time complexity often greatly
exceeds space complexity.</html:p><html:p>The function <html:code>sillySum</html:code> calls itself twice in each <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> step.  This
function is contrived, but many mathematical formulas refer to a particular
quantity more than once.  In OCaml, we can create a local binding to a computed
value using the <html:em>local declaration</html:em> syntax. In the following expression, <html:code>y</html:code> is
computed once and used twice:</html:p><html:pre><![CDATA[# let x = 2.0 in
  let y = Float.pow x 20.0 in
  y *. (x /. y)
- : float = 2.]]></html:pre><html:p>You can read <html:code>let x = e1 in e2</html:code> as assigning (or "binding") the name <html:code>x</html:code> with
the value of <html:code>e1</html:code> into <html:code>e2</html:code>. Any use of <html:code>x</html:code> within <html:code>e2</html:code> will have the value of <html:code>e1</html:code>,
and <html:code>x</html:code> will only be visible in subexpressions into which it has been bound.</html:p><html:p>Why do we need let bindings? Fast hardware does not make good algorithms unnecessary.
On the contrary, faster hardware magnifies the superiority of better algorithms.
Typically, we want to handle the largest inputs possible.  If we double our processing power,
what do we gain?  How much can we increase <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, the input to our function?</html:p><html:p>With <html:code>sillySum</html:code>, we can only go from <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>.  We are limited to this
modest increase because the function’s running time is proportional to <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex>.
With the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> defined in the previous section, we can go from <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
to <fr:tex
display="inline"><![CDATA[2n]]></fr:tex>: we can handle problems twice as big.  With <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> we can do much
better still, going from <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p><html:p>The following table (excerpted from <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">a 50-year-old book</fr:link>!)
illustrates the effect of various time complexities.  The left-hand column (dubbed "complexity")
is defined as how many milliseconds are required to process an input of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
The other entries show the maximum size of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> that can be processed in the given time (one
second, minute or hour).</html:p><html:table>
  <html:tr><html:th>complexity</html:th><html:th>1 second</html:th><html:th>1 minute</html:th><html:th>1 hour</html:th><html:th>gain</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n]]></fr:tex></html:td><html:td>1000</html:td><html:td>60 000</html:td><html:td>3 600 000</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  60]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n \log  n]]></fr:tex></html:td><html:td>140</html:td><html:td>4 895</html:td><html:td>204 095</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  41]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{2}]]></fr:tex></html:td><html:td>31</html:td><html:td>244</html:td><html:td>1 897</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  8]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{3}]]></fr:tex></html:td><html:td>10</html:td><html:td>39</html:td><html:td>153</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  4]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[2^{n}]]></fr:tex></html:td><html:td>9</html:td><html:td>15</html:td><html:td>21</html:td><html:td><fr:tex
display="inline"><![CDATA[+6]]></fr:tex></html:td></html:tr>
</html:table><html:p>The table illustrates how large an input can be processed as a function
of time.  As we increase the computer time per input from one second to one
minute and then to one hour, the size of the input increases accordingly.</html:p><html:p>The top two rows (complexities <fr:tex
display="inline"><![CDATA[n]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n \lg  n]]></fr:tex>) increase rapidly: for <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, by
a factor of 60 per column.  The bottom two start out close together, but <fr:tex
display="inline"><![CDATA[n^3]]></fr:tex> (which
grows by a factor of 3.9) pulls well away from <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> (whose growth is only
additive).  If an algorithm’s complexity is exponential then it can never
handle large inputs, even if it is given huge resources.  On the other hand,
suppose the complexity has the form <fr:tex
display="inline"><![CDATA[n^c]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[c]]></fr:tex> is a constant.  (We say
the complexity is <html:em>polynomial</html:em>.)  Doubling the argument then increases the
cost by a constant factor.  That is much better, though if <fr:tex
display="inline"><![CDATA[c>3]]></fr:tex> the algorithm
may not be considered practical.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recurrences/</fr:uri><fr:display-uri>focs-recurrences</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recurrences/</fr:route><fr:title
text="Some Simple Recurrence Relations">Some Simple Recurrence Relations</fr:title></fr:frontmatter><fr:mainmatter><html:p>Consider a function <fr:tex
display="inline"><![CDATA[T(n)]]></fr:tex> that has a cost we want to bound using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link>.
A typical <html:em>base case</html:em> is <fr:tex
display="inline"><![CDATA[T(1)=1]]></fr:tex>.  Some <html:em>recurrences</html:em> are:</html:p><html:table>
  <html:tr><html:th>Equation</html:th><html:th>Complexity</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+1]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n) = T(n/2)+1]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex></html:td></html:tr>
</html:table><html:p>To analyse a function, inspect its OCaml declaration.  Recurrence equations for
the cost function <fr:tex
display="inline"><![CDATA[T(n)]]></fr:tex> can usually be read off.  Since we ignore constant
factors, we can give the base case a cost of one unit.  Constant work done in
the recursive step can also be given unit cost; since we only need an upper
bound, this unit represents the larger of the two actual costs.  We could use
other constants if it simplifies the algebra.</html:p><html:p>For example, recall our function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link>:</html:p><html:pre><![CDATA[# let rec nsum n =
    if n = 0 then
      0
    else
      n + nsum (n - 1)
val nsum : int -> int = <fun>]]></html:pre><html:p>Given <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>, it performs a constant amount of work (an addition and
subtraction) and calls itself recursively with argument <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  We get the
recurrence equations <fr:tex
display="inline"><![CDATA[T(0)=1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+1]]></fr:tex>.  The closed form is
clearly <fr:tex
display="inline"><![CDATA[T(n)=n+1]]></fr:tex>, as we can easily verify by substitution.  The cost is
<html:em>linear</html:em>.</html:p><html:p>This function, given <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>, calls <html:code>nsum</html:code>, performing <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> work.
Again ignoring constant factors, we can say that this call takes exactly <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
units.</html:p><html:pre><![CDATA[# let rec nsumsum n =
    if n = 0 then
      0
    else
      nsum n + nsumsum (n - 1)
val nsumsum : int -> int = <fun>]]></html:pre><html:p>We get the recurrence equations <fr:tex
display="inline"><![CDATA[T(0)=1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>.  It is easy to
see that <fr:tex
display="inline"><![CDATA[T(n)=(n-1)+\cdots +1=n(n-1)/2=O(n^2)]]></fr:tex>.  The cost is
<html:em>quadratic</html:em>.</html:p><html:p>The function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> divides its input <fr:tex
display="inline"><![CDATA[n]]></fr:tex> into two, with
the recurrence equation <fr:tex
display="inline"><![CDATA[T(n) = T(n/2)+1]]></fr:tex>.  Clearly <fr:tex
display="inline"><![CDATA[T(2^n)=n+1]]></fr:tex>, so
<fr:tex
display="inline"><![CDATA[T(n)=O(\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/</fr:uri><fr:display-uri>focs-nsum</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nsum/</fr:route><fr:title
text="Summing the first n integers">Summing the first n integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nsum n =
    if n = 0 then
      0
    else
      n + nsum (n - 1)
val nsum : int -> int = <fun>]]></html:pre><html:p>The function call <html:code>nsum n</html:code> computes the sum <html:code>1 +</html:code> … <html:code>+ n</html:code> rather naively, hence the
initial <html:code>n</html:code> in its name:</html:p><fr:tex
display="block"><![CDATA[\begin {aligned}
\text {nsum}\;3 \Rightarrow  &\; 3 + (\text {nsum}\;2) \\
               \Rightarrow  &\; 3 + (2 + (\text {nsum}\;1)) \\
               \Rightarrow  &\; 3 + (2 + (1 + (\text {nsum}\;0))) \\
               \Rightarrow  &\; 3 + (2 + (1 + 0))
\end {aligned}]]></fr:tex><html:p>The nesting of parentheses is not just an artifact of
our notation; it indicates a real problem.  The function gathers up a
collection of numbers, but none of the additions can be performed until <html:code>nsum
0</html:code> is reached.  Meanwhile, the computer must store the numbers in an internal
data structure, typically the <html:em>stack</html:em>.  For large <html:code>n</html:code>, say <html:code>nsum 10000</html:code>, the
computation might fail due to stack overflow.</html:p><html:p>We all know that the additions can be performed as we go along.  How do we
make the computer do that?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/</fr:uri><fr:display-uri>focs-def-tail-recursion</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/</fr:route><fr:title
text="Tail recursion">Tail recursion</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A recursive function whose computation does not nest is called <html:em>iterative</html:em>
or <html:em>tail-recursive</html:em>: the recursive calls do not nest, so the work is done
immediately rather than on the way back out. Many functions can be made
iterative by introducing an extra argument, which is often called an
<html:em>accumulator</html:em>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-summing-iter/"
title="Iteratively summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/"
display-uri="focs-summing-iter"
type="local">Iteratively summing the first n integers</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-infinite-sequence/</fr:uri><fr:display-uri>focs-infinite-sequence</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-infinite-sequence/</fr:route><fr:title
text="The Infinite Sequence: k, k+1, k+2, …">The Infinite Sequence: <fr:tex
display="inline"><![CDATA[k]]></fr:tex>, <fr:tex
display="inline"><![CDATA[k+1]]></fr:tex>, <fr:tex
display="inline"><![CDATA[k+2]]></fr:tex>, …</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec from k = Cons (k, fun () -> from (k+1))
val from : int -> int seq = <fun>
# let it = from 1
val it : int seq = Cons (1, <fun>)
# let it = tail it
val it : int seq = Cons (2, <fun>)
# let it = tail it
val it : int seq = Cons (3, <fun>)]]></html:pre><html:p>Function <html:code>from</html:code> constructs the infinite sequence of integers starting
from <fr:tex
display="inline"><![CDATA[k]]></fr:tex>.  Execution terminates because of the <html:code>fun</html:code> enclosing the
recursive call.  OCaml displays the tail of a sequence as <html:code>fun</html:code>, which
stands for some function value.  Each call to <html:code>tail</html:code> generates the next
sequence element.  We could do this forever.</html:p><html:p>This example is of little practical value because the cost of computing a
sequence element will be dominated by that of creating the dummy function.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">Lazy lists</fr:link> tend to have high overheads.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:uri><fr:display-uri>focs-bst-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:route><fr:title
text="Update">Update</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update k v = function
  | Lf -> Br ((k, v), Lf, Lf)
  | Br ((a, x), t1, t2) ->
      if k < a then
        Br ((a, x), update k v t1, t2)
      else if a < k then
        Br ((a, x), t1, update k v t2)
      else (* a = k *)
        Br ((a, v), t1, t2)
val update : 'a -> 'b -> ('a * 'b) tree -> ('a * 'b) tree = <fun>]]></html:pre><html:p>This is also <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> as it copies the path only, and <html:em>not whole subtrees!</html:em></html:p><html:p>If you are familiar with the usual update operation for this sort of tree, you
may wonder whether it can be implemented in OCaml, where there is no direct way to
replace part of a data structure by something else.</html:p><html:p>The update operation is a nice piece of functional programming.  It searches
in the same manner as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
title="Lookup: Seeks Left or Right"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
display-uri="focs-bst-lookup"
type="local"><html:code>lookup</html:code></fr:link>, but the recursive calls reconstruct a
new tree around the result of the update.  One subtree is updated and the
other left unchanged.  The internal representation of trees ensures that
unchanged parts of the tree are not copied, but <html:em>shared</html:em>.
Therefore, update copies only the path from the root to the new
node.  Its time and space requirements, for a reasonably balanced tree, are
both <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.</html:p><html:p>The comparison between <fr:tex
display="inline"><![CDATA[b]]></fr:tex> and <fr:tex
display="inline"><![CDATA[a]]></fr:tex> allows three cases:</html:p><html:ul><html:li>smaller: update the left subtree; share the right</html:li>
<html:li>greater: update the right subtree; share the left</html:li>
<html:li>equal: update the label and share both subtrees</html:li></html:ul><html:p>Note: in the function definition, <html:code>(* a = k *)</html:code> is a comment.  Comments
in OCaml are enclosed in the brackets <html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:uri><fr:display-uri>focs-ex-2-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:route><fr:title
text="Exercises › A tighter recurrence bound"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › A tighter recurrence bound</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Find an upper bound for the recurrence given by <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+1]]></fr:tex>.  You should be
able to find a tighter bound than <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:uri><fr:display-uri>focs-ex-4-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:route><fr:title
text="Exercises › Assumptions in making change"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Assumptions in making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What assumptions do the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">‘making change’</fr:link> functions make about the variables <html:code>till</html:code> and <html:code>amt</html:code>?
Describe what could happen if these assumptions were violated.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:uri><fr:display-uri>focs-ex-4-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:route><fr:title
text="Exercises › Counting ways of making change"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Counting ways of making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the number of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">ways of making change</fr:link> for <fr:tex
display="inline"><![CDATA[n]]></fr:tex> (ignoring order) is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> if there are two
legal coin values. What if there are three, four, … coin values?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:uri><fr:display-uri>focs-ex-3-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:route><fr:title
text="Exercises › Even-numbered elements"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Even-numbered elements</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the list consisting of the even-numbered elements of the list given as its
argument. For example, given <html:code>[a; b; c; d]</html:code> it should return <html:code>[b; d]</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:uri><fr:display-uri>focs-ex-1-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:route><fr:title
text="Exercises › Floating-point error by repeated addition"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Floating-point error by repeated addition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Because computer arithmetic is based on binary numbers, simple decimals such as 0.1 often cannot be
represented exactly. Write a function <html:code>mul</html:code> that performs the computation</html:p><fr:tex
display="block"><![CDATA[\underbrace {x+x+\cdots +x}_{n}]]></fr:tex><html:p>where <fr:tex
display="inline"><![CDATA[x]]></fr:tex> has type <html:code>float</html:code>. (It is essential to use repeated addition rather than multiplication!)</html:p><html:p>The value computed with <html:code>n = 10000</html:code> and <html:code>x = 0.1</html:code> may print as
<html:code>1000.0</html:code>, which looks exact. If that happens, then evaluate the
expression <html:code>mul 0.1 10000 -. 1000.0</html:code></html:p><html:p>An error of this type has been blamed for the failure of an American Patriot Missile battery to
intercept an incoming Iraqi missile during the <fr:link
href="https://en.wikipedia.org/wiki/MIM-104_PatriotFailure_at_Dhahran"
type="external">first Gulf War</fr:link>.
The missile hit an American Army barracks, killing 28.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:uri><fr:display-uri>focs-ex-1-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:route><fr:title
text="Exercises › Golden ratio instability"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Golden ratio instability</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another example of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-floating-point/"
title="Example 2: Floating Point Numbers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/"
display-uri="focs-floating-point"
type="local">inaccuracy of floating-point arithmetic</fr:link> takes the golden ratio
<fr:tex
display="inline"><![CDATA[\phi \approx 1.618\ldots ]]></fr:tex> as its starting point:</html:p><fr:tex
display="block"><![CDATA[\gamma _0 = \frac {1+\sqrt 5}{2} \quad \text {and}\quad \gamma _{n+1} = \frac {1}{\gamma _n-1}.]]></fr:tex><html:p>In theory, it is easy to prove that <fr:tex
display="inline"><![CDATA[\gamma _n=\cdots  = \gamma _1 = \gamma _0]]></fr:tex> for all <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>. Code this
computation in OCaml and report the value of <fr:tex
display="inline"><![CDATA[\gamma _{50}]]></fr:tex>. <html:em>Hint:</html:em> in OCaml, <fr:tex
display="inline"><![CDATA[\sqrt 5]]></fr:tex> is expressed
as <html:code>sqrt 5.0</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:uri><fr:display-uri>focs-ex-5-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:route><fr:title
text="Exercises › Implementing bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement bubble sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:uri><fr:display-uri>focs-ex-5-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:route><fr:title
text="Exercises › Implementing selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement selection sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-1/</fr:uri><fr:display-uri>focs-ex-2-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-1/</fr:route><fr:title
text="Exercises › Iterative power"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › Iterative power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:uri><fr:display-uri>focs-ex-11-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:route><fr:title
text="Exercises › Iterative power with while"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Iterative power with while</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of function <html:code>power</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-intro/"
title="Introduction to Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro"
type="local">Lecture <fr:contextual-number
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro" /></fr:link>) using <html:code>while</html:code> instead of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:uri><fr:display-uri>focs-ex-9-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:route><fr:title
text="Exercises › Making change lazily"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Making change lazily</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">make change</fr:link> using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, delivering the sequence of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all possible ways of
making change</fr:link>. Using sequences allows us to compute solutions one at a time when there exists an
astronomical number. Represent lists of coins using ordinary lists. (<html:em>Hint</html:em>: to  benefit from
laziness you may need to pass around the sequence of alternative solutions as a function of type
<html:code>unit -&gt; (int list) seq</html:code>.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:uri><fr:display-uri>focs-ex-8-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:route><fr:title
text="Exercises › Making change with map"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Making change with map</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Recall the making change function of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">More on Lists</fr:link>:</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Function <html:code>allc</html:code> applies the function ‘cons a <html:code>c</html:code>’ to every element of a list. Eliminate it by
declaring a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried</fr:link> cons function and applying <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:uri><fr:display-uri>focs-ex-4-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:route><fr:title
text="Exercises › Partitioning integers by sign"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Partitioning integers by sign</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function that takes a list of integers and returns two lists, the first consisting of all
non-negative numbers found in the input and the second consisting of all the negative numbers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:uri><fr:display-uri>focs-ex-3-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:route><fr:title
text="Exercises › Summing a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Summing a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function</fr:link> to compute the sum of a list’s elements. Then code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version
and comment on the improvement in efficiency.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:uri><fr:display-uri>focs-ex-6-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:route><fr:title
text="Exercises › Summing tree labels"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Summing tree labels</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write an OCaml function taking a binary tree labelled with integers and returning their sum.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:uri><fr:display-uri>focs-ex-3-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:route><fr:title
text="Exercises › Tails of a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Tails of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function <html:code>tails</html:code> to return the list of the tails of its argument. For example, given
<html:code>[1; 2; 3]</html:code> it should return <html:code>[[1; 2; 3]; [2; 3]; [3]; []]</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:uri><fr:display-uri>focs-ex-1-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:route><fr:title
text="Exercises › Type inference in power"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Type inference in power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> both return a <html:code>float</html:code>. The definition of <html:code>npower</html:code> returns the float
value <html:code>1.0</html:code> in its base case. The definition of <html:code>power</html:code> does not, so how does the OCaml type checker
know that <html:code>power</html:code> returns a <html:code>float</html:code>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:uri><fr:display-uri>focs-ex-6-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:route><fr:title
text="Exercises › What ftree builds"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › What ftree builds</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">definition of <html:code>'a tree</html:code></fr:link> from before:</html:p><html:pre><![CDATA[type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:p>Examine the following function declaration. What does <html:code>ftree (1, n)</html:code> accomplish?</html:p><html:pre><![CDATA[let rec ftree k n =
  if n = 0 then Lf
  else Br (k, ftree (2 * k) (n - 1), ftree (2 * k + 1) (n - 1))]]></html:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-complexity/</fr:uri><fr:display-uri>focs-topic-complexity</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-complexity/</fr:route><fr:title
text="Complexity">Complexity</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:uri><fr:display-uri>focs-change-faster</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:route><fr:title
text="All Ways of Making Change — Faster!">All Ways of Making Change — Faster!</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec change till amt chg chgs =
    match till, amt with
    | _       , 0   -> chg::chgs
    | []      , _   -> chgs
    | c::till , amt -> if amt < 0 then chgs
                       else change (c::till) (amt - c) (c::chg)
                                   (change till amt chg chgs)
val change : int list -> int -> int list -> int list list -> int list list =
  <fun>]]></html:pre><html:p>We’ve added <html:em>another</html:em> accumulating parameter!  Repeatedly improving simple code
is called <html:em>stepwise refinement</html:em>.</html:p><html:p>Two extra arguments eliminate many <html:code>::</html:code> and append operations from the
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all-solutions <html:code>change</html:code></fr:link> function.  The first, <html:code>chg</html:code>, accumulates the coins chosen so
far; one evaluation of <html:code>c::chg</html:code> replaces many evaluations of <html:code>allc</html:code>.  The
second, <html:code>chgs</html:code>, accumulates the list of solutions so far; it avoids the need
for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link>.  This version runs several times faster than the previous one.</html:p><html:p>Making change is still extremely slow for an obvious reason: the number of
solutions grows rapidly in the amount being changed.  Using 50, 20, 10, 5,
2 and 1, there are 4366 ways of expressing 99.</html:p><html:p>Our three change functions illustrate a basic technique: program development
by stepwise refinement.  Begin by writing a very simple program and add
requirements individually.  Add efficiency refinements last of all.
Even if the simpler program cannot be included in the next version and has
to be discarded, one has learned about the task by writing it.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/</fr:uri><fr:display-uri>focs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-append/</fr:route><fr:title
text="Append: List Concatenation">Append: List Concatenation</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec append xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> x :: append xs ys
val append : 'a list -> 'a list -> 'a list = <fun>
# append [1; 2; 3] [4]
- : int list = [1; 2; 3; 4]
# let (@) = append
val ( @ ) : 'a list -> 'a list -> 'a list = <fun>
# [1; 2; 3] @ [4]
- : int list = [1; 2; 3; 4]]]></html:pre><html:p>Patterns can be as complicated as we like.  Here, the two patterns are
<html:code>[], ys</html:code> and <html:code>x::xs, ys</html:code>.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {append }[1; 2; 3] [4] \Rightarrow  &\; 1 :: \text {append }[2; 3]\;[4] \\
  \Rightarrow  &\; 1 :: (2 :: \text {append }[3]\;[4]) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: \text {append }[]\;[4])) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: [4])) \ [1; 2; 3; 4]
\end {aligned}
]]></fr:tex><html:p>Here is how append might be declared, also noting that we have defined <html:code>@</html:code> as
an infix operator that is a more convenient way to call <html:code>append</html:code> on two lists.
However, this function is also not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It scans its first
argument, sets up a string of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code> operations</fr:link> (<html:code>::</html:code>) and finally does them.</html:p><html:p>It uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its first argument.
<html:em>Its costs are independent of its second argument.</html:em></html:p><html:p>An accumulating argument could make it iterative, but with considerable
complication.  The iterative version would still require <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time
because concatenation requires copying all the elements of the first list.
Therefore, we cannot hope for asymptotic gains; at best we can decrease the
constant factor involved in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>, but complicating the code is likely to
increase that factor.  Never add an accumulator merely out of habit.</html:p><html:p>Note append’s <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic type</fr:link>. It tells us that two lists can be joined if
their element types agree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-complexity-classes/</fr:uri><fr:display-uri>focs-complexity-classes</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-complexity-classes/</fr:route><fr:title
text="Common Complexity Classes">Common Complexity Classes</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> is <html:em>constant</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> is <html:em>logarithmic</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> is <html:em>linear</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> is <html:em>quasi-linear</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> is <html:em>quadratic</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(n^3)]]></fr:tex> is <html:em>cubic</html:em></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(a^n)]]></fr:tex> is <html:em>exponential</html:em> (for fixed <fr:tex
display="inline"><![CDATA[a]]></fr:tex>)</html:li></html:ul><html:p>Logarithms grow very slowly, so <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> complexity is excellent.  Because
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> ignores constant factors, the base of the logarithm is
irrelevant!</html:p><html:p>Under linear we might mention <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>, which occasionally is called
<html:em>quasilinear</html:em> and which scales up well for large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>An example of quadratic complexity is matrix addition: forming the sum of two
<fr:tex
display="inline"><![CDATA[n\times  n]]></fr:tex> matrices obviously takes <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex> additions.  Matrix
multiplication is of cubic complexity, which limits the size of matrices that
we can multiply in reasonable time.  An <fr:tex
display="inline"><![CDATA[O(n^{2.81})]]></fr:tex> algorithm exists, but it
is too complicated to be of much use, even though it is theoretically better.</html:p><html:p>An exponential growth rate such as <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> restricts us to small values of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
Already with <fr:tex
display="inline"><![CDATA[n=20]]></fr:tex> the cost exceeds one million.  However, the worst case
might not arise in normal practice.  OCaml type-checking is exponential in the
worst case, but not for ordinary programs.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/</fr:uri><fr:display-uri>focs-o-notation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-o-notation/</fr:route><fr:title
text="Comparing Algorithms: O Notation">Comparing Algorithms: O Notation</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Formally, define <fr:tex
display="inline"><![CDATA[f(n) = O(g(n))]]></fr:tex> provided <fr:tex
display="inline"><![CDATA[|f(n)| \leq  c|g(n)|]]></fr:tex> as <fr:tex
display="inline"><![CDATA[n\to \infty ]]></fr:tex></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[|f(n)|]]></fr:tex> is bounded for some constant <fr:tex
display="inline"><![CDATA[c]]></fr:tex> and all <html:em>sufficiently large</html:em> <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:li>
  <html:li>Intuitively, look at the <html:em>most significant</html:em> term.</html:li>
  <html:li>Ignore <html:em>constant factors</html:em> as they seldom dominate and are often transitory</html:li></html:ul><html:p>For example: consider <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex> instead of <fr:tex
display="inline"><![CDATA[3n^2+34n+433]]></fr:tex>.</html:p><html:p>The cost of a program is usually a complicated formula.  Often we should
consider only the most significant term.  If the cost is <fr:tex
display="inline"><![CDATA[n^2 + 99n + 900]]></fr:tex>
for an input of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, then the <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex> term will eventually dominate,
even though <fr:tex
display="inline"><![CDATA[99n]]></fr:tex> is bigger for <fr:tex
display="inline"><![CDATA[n<99]]></fr:tex>.
The constant term <fr:tex
display="inline"><![CDATA[900]]></fr:tex> may look big, but it is soon dominated by <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p><html:p>Constant factors in costs can be ignored unless they are large.  For one thing,
they seldom make a difference: <fr:tex
display="inline"><![CDATA[100n^2]]></fr:tex> will be better than <fr:tex
display="inline"><![CDATA[n^3]]></fr:tex> in the long
run: or <html:em>asymptotically</html:em> to use the jargon.  Moreover, constant factors are
seldom stable.  They depend upon details such as which hardware, operating
system or programming language is being used.  By ignoring constant factors, we
can make comparisons between algorithms that remain valid in a broad range of
circumstances.</html:p><html:p>The “Big O” notation is commonly used to describe efficiency—to be precise,
<html:em>asymptotic complexity</html:em>.  It concerns the limit of a function as its
argument tends to infinity.  It is an abstraction that meets the informal
criteria that we have just discussed.
In the definition, <html:em>sufficiently large</html:em> means there is some constant <fr:tex
display="inline"><![CDATA[n_0]]></fr:tex>
such that <fr:tex
display="inline"><![CDATA[|f(n)|\leq  c|g(n)|]]></fr:tex> for all <fr:tex
display="inline"><![CDATA[n]]></fr:tex> greater than <fr:tex
display="inline"><![CDATA[n_0]]></fr:tex>.  The
role of <fr:tex
display="inline"><![CDATA[n_0]]></fr:tex> is to ignore finitely many exceptions to the bound, such as the
cases when <fr:tex
display="inline"><![CDATA[99n]]></fr:tex> exceeds <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:uri><fr:display-uri>focs-functional-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:route><fr:title
text="Efficient Functional Queues: Code">Efficient Functional Queues: Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a queue =
  | Q of 'a list * 'a list
type 'a queue = Q of 'a list * 'a list
# let norm = function
  | Q ([], tls) -> Q (List.rev tls, [])
  | q -> q
val norm : 'a queue -> 'a queue = <fun>
# let qnull = function
  | Q ([], []) -> true
  | _ -> false
val qnull : 'a queue -> bool = <fun>
# let enq (Q (hds, tls)) x = norm (Q (hds, x::tls))
val enq : 'a queue -> 'a -> 'a queue = <fun>
# exception Empty
exception Empty
# let deq = function
  | Q (x::hds, tls) -> norm (Q (hds, tls))
  | _ -> raise Empty
val deq : 'a queue -> 'a queue = <fun>
# let qempty = Q ([], [])
val qempty : 'a queue = Q ([], [])
# let qhd = function
  | Q (x::_, _) -> x
  | _ -> raise Empty
val qhd : 'a queue -> 'a = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> of queues prevents confusion with other pairs of lists.  The empty
queue has both parts empty.</html:p><html:p>The function <html:code>norm</html:code> puts a queue into normal form, ensuring that the front part
is never empty unless the entire queue is empty.  Functions <html:code>deq</html:code> and <html:code>enq</html:code>
call <html:code>norm</html:code> to normalise their result.</html:p><html:p>Because queues are in normal form, their head is certain to be in their
front part, so <html:code>qhd</html:code> looks there.</html:p><html:p>Let us analyse the cost of an execution comprising (in any possible order) <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
<html:code>enq</html:code> operations and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> <html:code>deq</html:code> operations, starting with an
empty queue.  Each <html:code>enq</html:code> operation will perform one cons, adding an
element to the rear part.  Since the final queue must be empty, each element
of the rear part gets transferred to the front part.  The corresponding
reversals perform one cons per element.  Thus, the total cost of the series of
queue operations is <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> cons operations, an average of 2 per operation.  The
amortized time is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p><html:p>There is a catch.  The conses need not be distributed evenly; reversing a long
list could take up to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> of them.  Unpredictable delays make the approach
unsuitable for <html:em>real-time programming</html:em> where deadlines must be met.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:uri><fr:display-uri>focs-functional-queues-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:route><fr:title
text="Efficient Functional Queues: Idea">Efficient Functional Queues: Idea</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Represent the queue <fr:tex
display="inline"><![CDATA[x_1\; x_2\; \ldots \; x_m\; y_n\; \ldots \; y_1]]></fr:tex> by any <html:em>pair of lists</html:em>
    <fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \; [y_1,y_2,\ldots ,y_n])]]></fr:tex></html:li>
  <html:li>Add new items to the <html:em>rear list</html:em></html:li>
  <html:li>Remove items from <html:em>front list</html:em> and if empty move <html:em>rear</html:em> to <html:em>front</html:em></html:li>
  <html:li><html:em>Amortized</html:em> time per operation is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p>Queues require efficient access at both ends: at the front, for removal, and
at the back, for insertion.  Ideally, access should take constant time,
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.  It may appear that lists cannot provide such access.  If
<html:code>enq(q, x)</html:code> performs <html:code>q@[x]</html:code>, then this operation will be <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  We
could represent queues by reversed lists, implementing <html:code>enq(q, x)</html:code> by
<html:code>x::q</html:code>, but then the <html:code>deq</html:code> and <html:code>qhd</html:code> operations would be
<fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Linear time is intolerable: a series of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> queue operations
could then require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time.</html:p><html:p>The solution is to represent a queue by a pair of lists, where</html:p><fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \, [y_1,y_2,\ldots ,y_n])]]></fr:tex><html:p>represents the queue <fr:tex
display="inline"><![CDATA[x_1 x_2 \ldots  x_m y_n \ldots  y_1]]></fr:tex>.</html:p><html:p>The front part of the queue is stored in order, and the rear part is stored in
reverse order.  The <html:code>enq</html:code> operation adds elements to the rear part
using cons, since this list is reversed; thus, <html:code>enq</html:code> takes constant
time.  The <html:code>deq</html:code> and <html:code>qhd</html:code> operations look at the front part,
which normally takes constant time, since this list is stored in order.  But
sometimes <html:code>deq</html:code> removes the last element from the front part; when this
happens, it reverses the rear part, which becomes the new front part.</html:p><html:p><html:em>Amortized</html:em> time refers to the cost per operation averaged over the
lifetime of any complete execution.  Even for the worst possible execution,
the average cost per operation turns out to be constant; see the analysis
below.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/</fr:uri><fr:display-uri>focs-length</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-length/</fr:route><fr:title
text="Efficiently Computing the Length of a List">Efficiently Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec addlen n = function
  | []    -> n
  | x::xs -> addlen (n + 1) xs
val addlen : int -> 'a list -> int = <fun>
# addlen 0 [5; 6; 7]
- : int = 3]]></html:pre><html:p>Recall that the use of <html:code>function</html:code> introduces an extra (unnamed) argument
that is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matched</fr:link> in the subsequent clauses; in this case, to break
open the list.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {addlen }0 [a; b; c] \Rightarrow  &\;  \text {addlen }1\;[b; c] \\
  \Rightarrow   &\; \text {addlen }2\;[c] \\
  \Rightarrow   &\; \text {addlen }3\;[] \\
  \Rightarrow   &\; 3
\end {aligned}
]]></fr:tex><html:p>Function <html:code>addlen</html:code> is again <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.  Its type mentions the integer
accumulator.</html:p><html:p>Now we may declare an efficient length function.  It is simply a wrapper for
<html:code>addlen</html:code>, supplying zero as the initial value of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# let length xs = addlen 0 xs
val length : 'a list -> int = <fun>
# length [5; 6; 7; 8]
- : int = 4]]></html:pre><html:p>The recursive calls do not nest: this version is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It takes <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
space.  Obviously its time requirement is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> because it takes at least <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
steps to find the length of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/</fr:uri><fr:display-uri>focs-power</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-power/</fr:route><fr:title
text="Efficiently Raising a Number to a Power">Efficiently Raising a Number to a Power</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec power x n =
    if n = 1 then x
    else if even n then
      power (x *. x) (n / 2)
    else
      x *. power (x *. x) (n / 2)
val power : float -> int -> float = <fun>]]></html:pre><html:p><html:em>Mathematical Justification</html:em></html:p><fr:tex
display="block"><![CDATA[\begin {aligned}
           x^1 & = x \\
           x^{2n} & = (x^2)^n  \\
           x^{2n+1} & = x\times (x^2)^n.
\end {aligned}]]></fr:tex><html:p>For large <html:code>n</html:code>, computing powers using <fr:tex
display="inline"><![CDATA[x^{n+1} = x\times  x^n]]></fr:tex> is too slow to
be practical.  The equations above are much faster. Example:</html:p><fr:tex
display="block"><![CDATA[ 2^{12} = 4^6 = 16^3 = 16\times  256^1 = 16\times  256 = 4096. ]]></fr:tex><html:p>Instead of <html:code>n</html:code> multiplications, we need at most <fr:tex
display="inline"><![CDATA[2\lg  n]]></fr:tex> multiplications,
where <fr:tex
display="inline"><![CDATA[\lg  n]]></fr:tex> is the logarithm of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to the base <fr:tex
display="inline"><![CDATA[2]]></fr:tex>.</html:p><html:p>We use the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>even</html:code></fr:link>, declared previously, to test whether the
exponent is even.  Integer division (<html:code>/</html:code>) truncates its result to an
integer: dividing <fr:tex
display="inline"><![CDATA[2n+1]]></fr:tex> by 2 yields <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>A recurrence is a useful computation rule only if it is bound to terminate.
If <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex> then <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is smaller than both <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> and <fr:tex
display="inline"><![CDATA[2n+1]]></fr:tex>.  After enough
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive calls</fr:link>, the exponent will be reduced to <fr:tex
display="inline"><![CDATA[1]]></fr:tex>.  The equations also hold
if <fr:tex
display="inline"><![CDATA[n\leq 0]]></fr:tex>, but the corresponding computation runs forever.</html:p><html:p>Our reasoning assumes arithmetic to be <html:em>exact</html:em>. Fortunately, the calculation is
well-behaved using floating-point.</html:p><html:p>Computer numbers have a finite range, which if exceeded results in the
integer wrapping around.  You will understand this behaviour more as you
learn about computer architecture and how modern systems represent
numbers in memory.</html:p><html:p>If integers and floats must be combined in a calculation, OCaml provides functions
to convert between them:</html:p><html:pre><![CDATA[# int_of_float 3.14159
- : int = 3
# float_of_int 3
- : float = 3.]]></html:pre><html:p>OCaml’s libraries are organised using “modules”, so we may use compound
identifiers such as <html:code>Float.of_int</html:code> to refer to library functions. There
are many thousands of library functions available in the OCaml ecosystem,
including text-processing and operating systems functions in addition to the
usual numerical ones.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:uri><fr:display-uri>focs-tree-traversal-efficient</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:route><fr:title
text="Efficiently Traversing Trees">Efficiently Traversing Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>Unfortunately, the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">traversal functions</fr:link> are quadratic in the
worst case: the appends in the recursive calls are inefficient.  To correct
that problem, we (as usual) add an accumulating argument.  Observe how
each function constructs its result list and compare with how appends were
eliminated from <html:code>quicksort</html:code> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">Sorting lecture</fr:link>.</html:p><html:pre><![CDATA[# let rec preord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      v :: preord (t1, preord (t2, vs))
val preord : 'a tree * 'a list -> 'a list = <fun>
# let rec inord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      inord (t1, v::inord (t2, vs))
val inord : 'a tree * 'a list -> 'a list = <fun>
# let rec postord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      postord (t1, postord (t2, v::vs))
val postord : 'a tree * 'a list -> 'a list = <fun>]]></html:pre><html:p>One can prove equations relating each of these functions to its counterpart on
the previous section.  For example:</html:p><fr:tex
display="block"><![CDATA[\texttt {inord}(t, vs) = \texttt {inorder}(t) @ vs]]></fr:tex><html:p>These three types of tree traversal are related in that all are depth-first.
They each traverse the left subtree in full before traversing the right
subtree.  Breadth-first search (from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queues/"
title="Queues and Search Strategies"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queues/"
display-uri="focs-queues"
type="local">Queues lecture</fr:link>) is another
possibility.  That involves going through the levels of a tree one at a time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:uri><fr:display-uri>focs-functional-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:route><fr:title
text="Functional Arrays as Binary Trees">Functional Arrays as Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>The path to element <fr:tex
display="inline"><![CDATA[i]]></fr:tex> follows the <html:em>binary code</html:em> for <fr:tex
display="inline"><![CDATA[i]]></fr:tex> (its “subscript”).</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifetc2v73r7qxnzo6bthiblab2tezbaqvmovq7e4q6vgdl5ewr3wi.svg" /></html:figure><html:p>This simple representation (credited to W. Braun) ensures that the tree is
balanced.  Complexity of access is always <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>, which is optimal.  For
actual running time, access to conventional arrays is much faster: it requires
only a few hardware instructions.  Array access is often taken to be <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>,
which (as always) presumes that hardware limits are never exceeded.</html:p><html:p>The lower bound for array subscripts (or “indices”) is one.  The upper bound starts at zero
(which signifies the empty array) and can grow without limit.  Inspection of
the diagram above should make it clear that these trees are always balanced:
the left subtree can have at most one node more than the right subtree,
recursively all the way down.  (This assumes that the array is defined for
subscripts <fr:tex
display="inline"><![CDATA[1\ldots  n]]></fr:tex> with no gaps; an array defined only for odd numbers, for
example, would obviously be unbalanced.)</html:p><html:p>The numbers in the diagram above are not the labels of branch nodes, but
indicate the positions of array elements. For example, the label corresponding
to <fr:tex
display="inline"><![CDATA[A[2]]]></fr:tex> is at the position shown. The nodes of a functional array are
labelled with the data we want to store, not with these integers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting-bounds/</fr:uri><fr:display-uri>focs-sorting-bounds</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting-bounds/</fr:route><fr:title
text="How Fast Can We Sort?">How Fast Can We Sort?</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>typically count <html:em>comparisons</html:em> <fr:tex
display="inline"><![CDATA[C(n)]]></fr:tex></html:li>
  <html:li>there are <fr:tex
display="inline"><![CDATA[n!]]></fr:tex> permutations of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements</html:li>
  <html:li>each comparison eliminates <html:em>half</html:em> of the permutations <fr:tex
display="inline"><![CDATA[2^{C(n)}\geq  n!]]></fr:tex></html:li>
  <html:li>therefore <fr:tex
display="inline"><![CDATA[C(n)\geq  \log (n!)\approx  n\log  n-1.44n]]></fr:tex></html:li></html:ul><html:p>The usual measure of efficiency for sorting algorithms is the number of
comparison operations required.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">Mergesort</fr:link> requires only <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>
comparisons to sort an input of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> items.  It is straightforward to prove
that this complexity is the best possible.  There
are <fr:tex
display="inline"><![CDATA[n!]]></fr:tex> permutations of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements and each comparison distinguishes two
permutations.  The lower bound on the number of comparisons, <fr:tex
display="inline"><![CDATA[C(n)]]></fr:tex>, is
obtained by solving <fr:tex
display="inline"><![CDATA[2^{C(n)}\geq  n!]]></fr:tex>; therefore
<fr:tex
display="inline"><![CDATA[C(n)\geq  \log (n!)\approx  n\log  n-1.44n]]></fr:tex>.</html:p><html:p>In order to compare the sorting algorithms, we use the <fr:link
href="http://www.firstpr.com.au/dsp/rand31/p1192-park.pdf"
type="external">following source</fr:link> of
pseudo-random numbers. Never mind how this works: generating
statistically good random numbers is hard.  Much effort has gone into those few
lines of code.</html:p><html:pre><![CDATA[# let nextrandom seed =
    let a = 16807.0 in
    let m = 2147483647.0 in
    let t = a *. seed in
    t -. m *. (floor (t /. m))
val nextrandom : float -> float = <fun>
# let rec randlist (seed, seeds) = function
    | 0 -> (seed, seeds)
    | n -> randlist (nextrandom seed, seed::seeds) (n-1)
val randlist : float * float list -> int -> float * float list = <fun>]]></html:pre><html:p>We can now bind the identifier <html:code>rs</html:code> to a list of 10,000 random numbers.</html:p><html:pre><![CDATA[# let seed, rs = randlist (1.0, []) 10000
val seed : float = 1043618065.
val rs : float list =
  [1484786315.; 925166085.; 1614852353.; 721631166.; 173942219.; 1229443779.;
   789328014.; 570809709.; 1760109362.; 270600523.; 2108528931.; 16480421.;
   519782231.; 162430624.; 372212905.; 1954184989.; 898872741.; 1651521688.;
   1114791388.; 1325968501.; 1469981427.; 465437343.; 1732504088.;
   280054095.; 1924919450.; 1244369648.; 1524535715.; 706293012.;
   1372325856.; 1302473561.; 941382430.; 2137445578.; 1937168414.;
   1852570660.; 495231255.; 1092873378.; 140232191.; 328129841.; 632752255.;
   227857208.; 1616471915.; 719842438.; 1402481130.; 745001020.; 791471334.;
   2131048000.; 312659966.; 1389551813.; 443838892.; 854190041.; 741774068.;
   267473377.; 1372555293.; 1539748349.; 697860888.; 1261546017.; 734770781.;
   1512111397.; 813238415.; 1034499961.; 602256496.; 462191385.; 250718457.;
   246489360.; 295426232.; 468306241.; 877829533.; 1130589227.; 1914364883.;
   1479854970.; 878528585.; 1268712064.; 115837978.; 1803525169.; 689954646.;
   1174020926.; 651968560.; 391152461.; 1776325865.; 2015344107.; 246977673.;
   1381242649.; 1115030853.; 190703911.; 316761032.; 464218769.; 1537522160.;
   1958981931.; 390463588.; 224009597.; 235243732.; 620352731.; 1374109567.;
   832140633.; 675075162.; 1296171190.; 2009054653.; 1534419747.; 145880482.;
   1649432515.; 403989126.; 1112417244.; 1290575192.; 896661113.; 218545469.;
   1002393512.; 2131316096.; 551979127.; 932010335.; 665881436.; 1975412808.;
   639877791.; 1781707137.; 894518191.; 568004958.; 1331430214.; 629489848.;
   183264178.; 162027282.; 464592882.; 93302056.; 1178713033.; 1401486247.;
   1846150129.; 1646978216.; 1104441491.; 111995009.; 66193165.; 2038880392.;
   79340676.; 871801051.; 967550305.; 2067810758.; 1600354198.; 1746626663.;
   1516388116.; 1308870791.; 173082747.; 189881227.; 478010722.; 739707315.;
   255334803.; 164203714.; 1893097038.; 1587694259.; 292950569.; 918323194.;
   41453146.; 1217297445.; 256768724.; 586494122.; 586258194.; 660494391.;
   507554325.; 699716071.; 672895139.; 76065072.; 1594869218.; 1439459639.;
   641123634.; 1650611940.; 177447368.; 301427463.; 525804524.; 553672425.;
   926899509.; 794676486.; 690277940.; 2115070333.; 1062048650.; 1653192448.;
   1808855340.; 126475289.; 1028198214.; 1739565096.; 1515748830.;
   427491435.; 319330584.; 666483848.; 854842154.; 1853528448.; 1975611245.;
   1905343266.; 1229802342.; 1416055428.; 2091603253.; 1068308139.;
   198239748.; 982076370.; 1094563396.; 44402415.; 889814989.; 290736902.;
   417580014.; 1935788352.; 595665917.; 367638848.; 894945148.; 1868608068.;
   317883051.; 941451621.; 1595942893.; 789094274.; 1150772108.; 422742112.;
   1444245279.; 1273601104.; 256005435.; 1742330161.; 1514599036.;
   956344512.; 2113041793.; 293237373.; 1386995194.; 1509339194.; 891946522.;
   1020832915.; 592544922.; 1746311153.; 1471539715.; 143832370.;
   2041568248.; 1039556199.; 1608726047.; 1205124472.; 2123533995.;
   1560620058.; 1837598795.; 1028172251.; 98318742.; 1405510706.;
   1047695837.; 59221314.; 1822176683.; 1096018886.; 1528104537.;
   1270922857.; 812074106.; 291115596.; 795788616.; 638657646.; 2034314619.;
   1527649272.; 156357479.; 1010056202.; 1139413443.; 1110927723.;
   1216083346.; 846825145.; 2100385733.; 315213605.; 1629637749.;
   1139833627.; 895118866.; 296359237.; 1361440746.; 1188627020.;
   1964199872.; 166733080.; 54185744.; 575493576.; 1810324496.; 1765549585.;
   53514233.; 747348448.; 61758907.; 1710119765.; 188311628.; 8827553.;
   67975851.; 1808633248.; 1290488843.; 1264775607.; 1711469075.;
   1537468597.; 706677101.; 518290019.; 190285086.; 157683412.; 985907152.;
   1571668636.; 632570698.; 791081325.; 1773794197.; 1787141077.;
   1727982894.; 794213057.; 633163306.; 682601940.; 1573439414.; 1041956036.;
   1169697582.; 758914445.; 2096291761.; 1502226099.; 1665995955.;
   948048264.; 1596326605.; 1816773893.; ...]]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:uri><fr:display-uri>focs-iterative-deepening</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:route><fr:title
text="Iterative deepening: Another Exhaustive Search">Iterative deepening: Another Exhaustive Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Breadth-first search examines <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> nodes:
    <fr:tex
display="block"><![CDATA[1 + b + \cdots  + b^d = {b^{d+1}-1 \over  b-1}
  \qquad  \begin {array}{rl}
            b & {} = \hbox {branching factor}\\
            d & {} = \hbox {depth}
          \end {array}]]></fr:tex></html:li>
  <html:li>Recompute nodes at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> instead of storing them</html:li>
  <html:li>Time factor is <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>; complexity is still <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex></html:li>
  <html:li>Space required at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> drops from <fr:tex
display="inline"><![CDATA[b^d]]></fr:tex> to <fr:tex
display="inline"><![CDATA[d]]></fr:tex></html:li></html:ul><html:p>Breadth-first search is not practical for infinite trees: it uses too much
space. Large parts of the tree have to be stored.
Consider the slightly more general problem of searching trees whose
branching factor is <fr:tex
display="inline"><![CDATA[b]]></fr:tex> (for binary trees, <fr:tex
display="inline"><![CDATA[b=2]]></fr:tex>).  Then breadth-first search
to depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> examines <fr:tex
display="inline"><![CDATA[(b^{d+1}-1)/(b-1)]]></fr:tex> nodes, which is <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>, ignoring
the constant factor of <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex>.  Since all nodes that are examined are also
stored, the space and time requirements are both <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.</html:p><html:p><html:em>Depth-first iterative deepening</html:em> combines the space efficiency of
depth-first with the “nearest-first” property of breadth-first search.  It
performs repeated depth-first searches with increasing depth bounds, each time
discarding the result of the previous search.  Thus it searches to depth 1,
then to depth 2, and so on until it finds a solution.  We can afford to
discard previous results because the number of nodes is growing exponentially.
There are <fr:tex
display="inline"><![CDATA[b^{d+1}]]></fr:tex> nodes at level <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>; if <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex>, this number actually
exceeds the total number of nodes of all previous levels put together, namely
<fr:tex
display="inline"><![CDATA[(b^{d+1}-1) / (b-1)]]></fr:tex>.</html:p><html:p><fr:link
href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.91.288"
type="external">Korf shows</fr:link> that the time needed for iterative deepening to reach
depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> is only <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> times that for breadth-first search, if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>.
This is a constant factor; both algorithms have the same time complexity,
<fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.  In typical applications where <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex> the extra factor of
<fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> is quite tolerable.  The reduction in the space requirement is
exponential, from <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> for breadth-first to <fr:tex
display="inline"><![CDATA[O(d)]]></fr:tex> for iterative
deepening. Of course, this assumes that the tree itself is not stored in memory.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:uri><fr:display-uri>focs-linear-search</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:route><fr:title
text="Linear Search">Linear Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>find <fr:tex
display="inline"><![CDATA[x]]></fr:tex> in list <fr:tex
display="inline"><![CDATA[[x_1,\ldots ,x_n]]]></fr:tex> by comparing with each element</html:li>
  <html:li>obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time</html:li>
  <html:li>simple &amp; general</html:li>
  <html:li>ordered searching needs only <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:li>
  <html:li>indexed lookup needs only <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p><html:em>Linear search</html:em> is the obvious way to find a desired item in a
collection: simply look through all the items, one at a time.  If <fr:tex
display="inline"><![CDATA[x]]></fr:tex> is in
the list, then it will be found in <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> steps on average, and even the worst
case is obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p><html:p>Large collections of data are usually ordered or indexed so that items can be
found in <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> time, which is exponentially better than <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Even
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> is achievable (using a hash table), though subject to the usual
proviso that machine limits are not exceeded.</html:p><html:p>Efficient indexing methods are of prime importance: consider Web
search engines.  Nevertheless, linear search is often used to search small
collections because it is so simple and general, and it is the starting point
for better algorithms.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/</fr:uri><fr:display-uri>focs-def-o-notation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-o-notation/</fr:route><fr:title
text="O notation">O notation</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Formally, <fr:tex
display="inline"><![CDATA[f(n) = O(g(n))]]></fr:tex> provided <fr:tex
display="inline"><![CDATA[|f(n)| \leq  c|g(n)|]]></fr:tex> as <fr:tex
display="inline"><![CDATA[n\to \infty ]]></fr:tex>,
that is, for some constant <fr:tex
display="inline"><![CDATA[c]]></fr:tex> and all <html:em>sufficiently large</html:em> <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. The “Big
O” notation is commonly used to describe efficiency—to be precise,
<html:em>asymptotic complexity</html:em>—by looking only at the most significant term and
ignoring constant factors.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-o-notation/"
title="Comparing Algorithms: O Notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/"
display-uri="focs-o-notation"
type="local">Comparing Algorithms: O Notation</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:uri><fr:display-uri>focs-quicksort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:route><fr:title
text="Quicksort: The Code">Quicksort: The Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quick = function
    | [] -> []
    | [x] -> [x]
    | a::bs ->
        let rec part l r = function
          | [] -> (quick l) @ (a :: quick r)
          | x::xs ->
              if (x <= a) then
                part (x::l) r xs
              else
                part l (x::r) xs
        in
        part [] [] bs
val quick : 'a list -> 'a list = <fun>]]></html:pre><html:p>Our OCaml quicksort copies the items.  It is still pretty fast, and it is much
easier to understand.  It takes roughly 0.74 seconds to sort our list of random
numbers.</html:p><html:p>The function declaration consists of three clauses.  The first handles the
empty list; the second handles singleton lists (those of the form <html:code>[x]</html:code>); the
third handles lists of two or more elements.  Often, lists of length up to five
or so are treated as special cases to boost speed.</html:p><html:p>The locally declared function <html:code>part</html:code> partitions the input using <html:code>a</html:code> as the
pivot.  The arguments <html:code>l</html:code> and <html:code>r</html:code> accumulate items for the left (<fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>) and
right (<fr:tex
display="inline"><![CDATA[>a]]></fr:tex>) parts of the input, respectively.</html:p><html:p>It is not hard to prove that quicksort does <fr:tex
display="inline"><![CDATA[n\log  n]]></fr:tex> comparisons, <html:em>in the average case</html:em>
(see <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">page 94 of Aho</fr:link>).  With random data, the pivot
usually has an average value that divides the input in two approximately equal
parts.  We have the recurrence <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>, which is
<fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.  In our example, it is about 235 times faster than <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insertion
sort</fr:link>.</html:p><html:p>In the worst case, quicksort's running time is quadratic!  An example is when
its input is almost sorted or reverse sorted.  Nearly all of the items end up
in one partition; work is not divided evenly.  We have the recurrence
<fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>, which is <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Randomising the input
makes the worst case highly unlikely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/</fr:uri><fr:display-uri>focs-rev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-rev/</fr:route><fr:title
text="Reversing a List in O(n)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec rev_app xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> rev_app xs (x::ys)
val rev_app : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {rev\_app }[a; b; c]\;[] \Rightarrow  &\; \text {rev\_app }[b; c]\; [a] \\
  \Rightarrow  &\; \text {rev\_app }[c]\; [b; a] \\
  \Rightarrow  &\; \text {rev\_app }[]\; [c; b; a] \\
  \Rightarrow  &\; [c; b; a]
\end {aligned}
]]></fr:tex><html:p>Calling <html:code>rev_app xs ys</html:code> reverses the elements of <html:code>xs</html:code> and
prepends them to <html:code>ys</html:code>.  Now we may declare</html:p><html:pre><![CDATA[# let rev xs = rev_app xs []
val rev : 'a list -> 'a list = <fun>
# rev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><html:p>It is easy to see that this reverse function performs just <fr:tex
display="inline"><![CDATA[n]]></fr:tex> conses, given
an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.  For both reverse functions, we could count the number of
conses precisely—not just up to a constant factor.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-o-notation/"
title="Comparing Algorithms: O Notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/"
display-uri="focs-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> is still
useful to describe the overall running time: the time taken by a cons
varies from one system to another.</html:p><html:p>The accumulator <fr:tex
display="inline"><![CDATA[y]]></fr:tex> makes the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  But the gain in complexity
arises from the removal of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.  Replacing an expensive operation (append)
by a series of cheap operations (cons) is called <html:em>reduction in strength</html:em>
and is a common technique in computer science.  It originated when many
computers did not have a hardware multiply instruction; the series of products
<fr:tex
display="inline"><![CDATA[i\times  r]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, <fr:tex
display="inline"><![CDATA[\ldots , n]]></fr:tex> could more efficiently be computed by
repeated addition.  Reduction in strength can be done in various ways; we
shall see many instances of removing append.</html:p><html:p>Consing to an accumulator produces the result in reverse.  If
that forces the use of an extra list reversal then the iterative function
may be much slower than the recursive one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nrev/</fr:uri><fr:display-uri>focs-nrev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nrev/</fr:route><fr:title
text="Reversing a List in O(n^2)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:p>Let us consider one way to reverse a list.</html:p><html:pre><![CDATA[# let rec nrev = function
  | [] -> []
  | x::xs -> (nrev xs) @ [x]
val nrev : 'a list -> 'a list = <fun>
# nrev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nrev }[a; b; c] \Rightarrow  &\; \text {nrev }[b; c]\;@\;[a] \\
  \Rightarrow  &\;  (\text {nrev }[c]\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  ((\text {nrev }[]\;@\;[c])\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  (([]\;@\;[c])\;@\;[b])\;@\;[a] \ \ldots  \ [c; b; a]
\end {aligned}
]]></fr:tex><html:p>This reverse function is grossly inefficient due to poor usage of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>, which
copies its first argument.  If <html:code>nrev</html:code> is given a list of length <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>, then
append makes <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> conses to copy the reversed tail.  Constructing the list
<html:code>[x]</html:code> calls <html:code>cons</html:code> again, for a total of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> calls.  Reversing the tail
requires <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> more conses, and so forth.  The total number of conses is:</html:p><fr:tex
display="block"><![CDATA[ 0 + 1 + 2 + \cdots  + n = {n(n+1)/2} ]]></fr:tex><html:p>The time complexity is therefore <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Space complexity is only <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>
because the copies don’t all exist at the same time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sample-costs/</fr:uri><fr:display-uri>focs-sample-costs</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sample-costs/</fr:route><fr:title
text="Sample costs in O notation">Sample costs in O notation</fr:title></fr:frontmatter><fr:mainmatter><html:p>Recall that <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> computes <fr:tex
display="inline"><![CDATA[x^n]]></fr:tex>
by repeated multiplication while <fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link> naively computes the sum
<fr:tex
display="inline"><![CDATA[1+\cdots +n]]></fr:tex>.  Each obviously performs <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> arithmetic operations.  Because
they are not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">tail recursive</fr:link>, their use of space is also <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  The function
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-summing-iter/"
title="Iteratively summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-summing-iter/"
display-uri="focs-summing-iter"
type="local"><html:code>summing</html:code></fr:link> is a version of <html:code>nsum</html:code> with an accumulating argument;
its iterative behaviour lets it work in constant space.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> spares
us from having to specify the units used to measure space.</html:p><html:table>
  <html:tr><html:th>Function</html:th><html:th>Time</html:th><html:th>Space</html:th></html:tr>
  <html:tr><html:td>npower, nsum</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>summing</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n(n+1)/2]]></fr:tex></html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[1]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>power</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[\log ~n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[\log ~n]]></fr:tex>)</html:td></html:tr>
  <html:tr><html:td>sillySum</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[2^n]]></fr:tex>)</html:td><html:td>O(<fr:tex
display="inline"><![CDATA[n]]></fr:tex>)</html:td></html:tr>
</html:table><html:p>Even ignoring constant factors, the units chosen can influence the result.
Multiplication may be regarded as a single unit of cost.  However, the cost of
multiplying two <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-digit numbers for large <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is itself an important
question, especially now that public-key cryptography uses numbers hundreds of
digits long.</html:p><html:p>Few things can <html:em>really</html:em> be done in constant time or stored in constant
space.  Merely to store the number <fr:tex
display="inline"><![CDATA[n]]></fr:tex> requires <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> bits.  If a
program cost is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>, then we have probably assumed that certain operations
it performs are also <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>—typically because we expect never to exceed the
capacity of the standard hardware arithmetic.</html:p><html:p>With <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link>, the precise number of operations depends upon <fr:tex
display="inline"><![CDATA[n]]></fr:tex> in a
complicated way, depending on how many odd numbers arise, so it is convenient
that we can just write <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  An accumulating argument could reduce its
space cost to <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sillysum/</fr:uri><fr:display-uri>focs-sillysum</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sillysum/</fr:route><fr:title
text="Silly Summing the First n Integers">Silly Summing the First n Integers</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec sillySum n =
    if n = 0 then
      0
    else
      n + (sillySum (n - 1) + sillySum (n - 1)) / 2
val sillySum : int -> int = <fun>]]></html:pre><html:p>The function calls itself <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> times!  Bigger inputs mean higher costs—but
what’s the growth rate?</html:p><html:p>Now let us consider how to estimate various costs associated with a program.
<html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local">Asymptotic complexity</fr:link></html:em> refers to how costs—usually time or space—grow with
increasing inputs. Space complexity can never exceed time complexity, for it
takes time to do anything with the space.  Time complexity often greatly
exceeds space complexity.</html:p><html:p>The function <html:code>sillySum</html:code> calls itself twice in each <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> step.  This
function is contrived, but many mathematical formulas refer to a particular
quantity more than once.  In OCaml, we can create a local binding to a computed
value using the <html:em>local declaration</html:em> syntax. In the following expression, <html:code>y</html:code> is
computed once and used twice:</html:p><html:pre><![CDATA[# let x = 2.0 in
  let y = Float.pow x 20.0 in
  y *. (x /. y)
- : float = 2.]]></html:pre><html:p>You can read <html:code>let x = e1 in e2</html:code> as assigning (or "binding") the name <html:code>x</html:code> with
the value of <html:code>e1</html:code> into <html:code>e2</html:code>. Any use of <html:code>x</html:code> within <html:code>e2</html:code> will have the value of <html:code>e1</html:code>,
and <html:code>x</html:code> will only be visible in subexpressions into which it has been bound.</html:p><html:p>Why do we need let bindings? Fast hardware does not make good algorithms unnecessary.
On the contrary, faster hardware magnifies the superiority of better algorithms.
Typically, we want to handle the largest inputs possible.  If we double our processing power,
what do we gain?  How much can we increase <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, the input to our function?</html:p><html:p>With <html:code>sillySum</html:code>, we can only go from <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>.  We are limited to this
modest increase because the function’s running time is proportional to <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex>.
With the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> defined in the previous section, we can go from <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
to <fr:tex
display="inline"><![CDATA[2n]]></fr:tex>: we can handle problems twice as big.  With <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> we can do much
better still, going from <fr:tex
display="inline"><![CDATA[n]]></fr:tex> to <fr:tex
display="inline"><![CDATA[n^2]]></fr:tex>.</html:p><html:p>The following table (excerpted from <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">a 50-year-old book</fr:link>!)
illustrates the effect of various time complexities.  The left-hand column (dubbed "complexity")
is defined as how many milliseconds are required to process an input of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
The other entries show the maximum size of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> that can be processed in the given time (one
second, minute or hour).</html:p><html:table>
  <html:tr><html:th>complexity</html:th><html:th>1 second</html:th><html:th>1 minute</html:th><html:th>1 hour</html:th><html:th>gain</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n]]></fr:tex></html:td><html:td>1000</html:td><html:td>60 000</html:td><html:td>3 600 000</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  60]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n \log  n]]></fr:tex></html:td><html:td>140</html:td><html:td>4 895</html:td><html:td>204 095</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  41]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{2}]]></fr:tex></html:td><html:td>31</html:td><html:td>244</html:td><html:td>1 897</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  8]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{3}]]></fr:tex></html:td><html:td>10</html:td><html:td>39</html:td><html:td>153</html:td><html:td><fr:tex
display="inline"><![CDATA[\times  4]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[2^{n}]]></fr:tex></html:td><html:td>9</html:td><html:td>15</html:td><html:td>21</html:td><html:td><fr:tex
display="inline"><![CDATA[+6]]></fr:tex></html:td></html:tr>
</html:table><html:p>The table illustrates how large an input can be processed as a function
of time.  As we increase the computer time per input from one second to one
minute and then to one hour, the size of the input increases accordingly.</html:p><html:p>The top two rows (complexities <fr:tex
display="inline"><![CDATA[n]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n \lg  n]]></fr:tex>) increase rapidly: for <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, by
a factor of 60 per column.  The bottom two start out close together, but <fr:tex
display="inline"><![CDATA[n^3]]></fr:tex> (which
grows by a factor of 3.9) pulls well away from <fr:tex
display="inline"><![CDATA[2^n]]></fr:tex> (whose growth is only
additive).  If an algorithm’s complexity is exponential then it can never
handle large inputs, even if it is given huge resources.  On the other hand,
suppose the complexity has the form <fr:tex
display="inline"><![CDATA[n^c]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[c]]></fr:tex> is a constant.  (We say
the complexity is <html:em>polynomial</html:em>.)  Doubling the argument then increases the
cost by a constant factor.  That is much better, though if <fr:tex
display="inline"><![CDATA[c>3]]></fr:tex> the algorithm
may not be considered practical.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation-facts/</fr:uri><fr:display-uri>focs-o-notation-facts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-o-notation-facts/</fr:route><fr:title
text="Simple Facts About O Notation">Simple Facts About O Notation</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {aligned}
 O(2g(n)) & \text { is the same as } O(g(n)) \\
 O(\log _{10}n) & \text { is the same as } O(\ln  n)  \\
 O(n^2+50n+36) & \text { is the same as } O(n^2) \\[1.5ex]
 O(n^2) & \text { is contained in }  O(n^3) \\
 O(2^n) & \text { is contained in }  O(3^n)  \\
 O(\log  n) & \text { is contained in } O(\sqrt  n)
\end {aligned}
]]></fr:tex><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> lets us reason about the costs of algorithms easily.</html:p><html:ul><html:li>Constant factors such as the <fr:tex
display="inline"><![CDATA[2]]></fr:tex> in <fr:tex
display="inline"><![CDATA[O(2g(n))]]></fr:tex> drop out: we can use <fr:tex
display="inline"><![CDATA[O(g(n))]]></fr:tex> with twice the value of <fr:tex
display="inline"><![CDATA[c]]></fr:tex> in the definition.</html:li>
  <html:li>Because constant factors drop out, the base of logarithms is irrelevant.</html:li>
  <html:li>Insignificant terms drop out.  To see that <fr:tex
display="inline"><![CDATA[O(n^2+50n+36)]]></fr:tex> is the same as <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>, consider that <fr:tex
display="inline"><![CDATA[n^2+50n+36/n^2]]></fr:tex> converges to 1 for increasing <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. In fact, <fr:tex
display="inline"><![CDATA[n^2+50n+36 \le  2n^2]]></fr:tex> for <fr:tex
display="inline"><![CDATA[n\ge  51]]></fr:tex>, so can double the constant factor</html:li></html:ul><html:p>If <fr:tex
display="inline"><![CDATA[c]]></fr:tex> and <fr:tex
display="inline"><![CDATA[d]]></fr:tex> are constants (that is, they are independent of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>) with <fr:tex
display="inline"><![CDATA[0 < c < d]]></fr:tex> then</html:p><html:ul><html:li><fr:tex
display="inline"><![CDATA[O(n^c)]]></fr:tex> is contained in <fr:tex
display="inline"><![CDATA[O(n^d)]]></fr:tex></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(c^n)]]></fr:tex> is contained in <fr:tex
display="inline"><![CDATA[O(d^n)]]></fr:tex></html:li>
  <html:li><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> is contained in <fr:tex
display="inline"><![CDATA[O(n^c)]]></fr:tex></html:li></html:ul><html:p>To say that <fr:tex
display="inline"><![CDATA[O(c^n)]]></fr:tex> <html:em>is contained in</html:em> <fr:tex
display="inline"><![CDATA[O(d^n)]]></fr:tex> means that the former gives
a tighter bound than the latter.  For example, if <fr:tex
display="inline"><![CDATA[f(n)=O(2^n)]]></fr:tex> then
<fr:tex
display="inline"><![CDATA[f(n)=O(3^n)]]></fr:tex> trivially, but the converse does not hold.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recurrences/</fr:uri><fr:display-uri>focs-recurrences</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recurrences/</fr:route><fr:title
text="Some Simple Recurrence Relations">Some Simple Recurrence Relations</fr:title></fr:frontmatter><fr:mainmatter><html:p>Consider a function <fr:tex
display="inline"><![CDATA[T(n)]]></fr:tex> that has a cost we want to bound using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
title="O notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-o-notation/"
display-uri="focs-def-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link>.
A typical <html:em>base case</html:em> is <fr:tex
display="inline"><![CDATA[T(1)=1]]></fr:tex>.  Some <html:em>recurrences</html:em> are:</html:p><html:table>
  <html:tr><html:th>Equation</html:th><html:th>Complexity</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+1]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n) = T(n/2)+1]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:td></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex></html:td><html:td><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex></html:td></html:tr>
</html:table><html:p>To analyse a function, inspect its OCaml declaration.  Recurrence equations for
the cost function <fr:tex
display="inline"><![CDATA[T(n)]]></fr:tex> can usually be read off.  Since we ignore constant
factors, we can give the base case a cost of one unit.  Constant work done in
the recursive step can also be given unit cost; since we only need an upper
bound, this unit represents the larger of the two actual costs.  We could use
other constants if it simplifies the algebra.</html:p><html:p>For example, recall our function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link>:</html:p><html:pre><![CDATA[# let rec nsum n =
    if n = 0 then
      0
    else
      n + nsum (n - 1)
val nsum : int -> int = <fun>]]></html:pre><html:p>Given <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>, it performs a constant amount of work (an addition and
subtraction) and calls itself recursively with argument <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  We get the
recurrence equations <fr:tex
display="inline"><![CDATA[T(0)=1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+1]]></fr:tex>.  The closed form is
clearly <fr:tex
display="inline"><![CDATA[T(n)=n+1]]></fr:tex>, as we can easily verify by substitution.  The cost is
<html:em>linear</html:em>.</html:p><html:p>This function, given <fr:tex
display="inline"><![CDATA[n+1]]></fr:tex>, calls <html:code>nsum</html:code>, performing <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> work.
Again ignoring constant factors, we can say that this call takes exactly <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
units.</html:p><html:pre><![CDATA[# let rec nsumsum n =
    if n = 0 then
      0
    else
      nsum n + nsumsum (n - 1)
val nsumsum : int -> int = <fun>]]></html:pre><html:p>We get the recurrence equations <fr:tex
display="inline"><![CDATA[T(0)=1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>.  It is easy to
see that <fr:tex
display="inline"><![CDATA[T(n)=(n-1)+\cdots +1=n(n-1)/2=O(n^2)]]></fr:tex>.  The cost is
<html:em>quadratic</html:em>.</html:p><html:p>The function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> divides its input <fr:tex
display="inline"><![CDATA[n]]></fr:tex> into two, with
the recurrence equation <fr:tex
display="inline"><![CDATA[T(n) = T(n/2)+1]]></fr:tex>.  Clearly <fr:tex
display="inline"><![CDATA[T(2^n)=n+1]]></fr:tex>, so
<fr:tex
display="inline"><![CDATA[T(n)=O(\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting-summary/</fr:uri><fr:display-uri>focs-sorting-summary</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting-summary/</fr:route><fr:title
text="Summary of Sorting Algorithms">Summary of Sorting Algorithms</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Optimal is <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">Insertion sort</fr:link>: simple to code; too slow (quadratic) [174 secs]</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort/"
title="Quicksort: The Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/"
display-uri="focs-quicksort"
type="local">Quicksort</fr:link>: fast on average; quadratic in worst case [0.53 secs]</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">Mergesort</fr:link>: optimal in theory; often slower than quicksort [1.4 secs]</html:li>
  <html:li><html:em>Match the algorithm to the application</html:em></html:li></html:ul><html:p>Quicksort’s worst case cannot be ignored.  For large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, a complexity of
<fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> is catastrophic.  Mergesort has an <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> worst case running
time, which is optimal, but it is typically slower than quicksort for random
data.</html:p><html:p>Non-comparison sorting deserves mentioning.  We can sort a large number of
small integers using their radix representation in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time.  This result
does not contradict the comparison-counting argument because comparisons are
not used at all.  Linear time is achievable only if the greatest integer is
fixed in advance; as <fr:tex
display="inline"><![CDATA[n]]></fr:tex> goes to infinity, increasingly many of the items
are the same.  It is a simple special case.</html:p><html:p>Many other sorting algorithms exist. A few are outlined in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">the exercises</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:uri><fr:display-uri>focs-merge-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:route><fr:title
text="Top-down Merge sort">Top-down Merge sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec tmergesort = function
    | [] -> []
    | [x] -> [x]
    | xs ->
        let k = List.length xs / 2 in
        let l = tmergesort (take k xs) in
        let r = tmergesort (drop k xs) in
        merge (l, r)
val tmergesort : 'a list -> 'a list = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons in worst case</html:p><html:p>Mergesort’s <html:em>divide</html:em> stage divides the input not by choosing a pivot (as
in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>) but by simply counting out half of the elements.  The
<html:em>conquer</html:em> stage again involves recursive calls, and the <html:em>combine</html:em>
stage involves merging.  Function <html:code>tmergesort</html:code> takes roughly 1.4
seconds to sort the list <html:code>rs</html:code>.</html:p><html:p>In the worst case, mergesort does <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons, with the same
recurrence equation as in quicksort’s average case.  Because <fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>take</html:code></fr:link> and
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>drop</html:code></fr:link> divide the input in two equal parts (they differ at most by
one element), we always have <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>.</html:p><html:p>Quicksort is nearly 3 times as fast in the example.  But it risks a
quadratic worst case!  Merge sort is safe but slow.  So which algorithm is
best?</html:p><html:p>We have seen a <html:em>top-down</html:em> mergesort.  <html:em>Bottom-up</html:em> algorithms also
exist.  They start with a list of one-element lists and repeatedly merge
adjacent lists until only one is left.  A refinement, which exploits any
initial order among the input, is to start with a list of increasing or
decreasing runs of input items.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:uri><fr:display-uri>focs-ex-2-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-4/</fr:route><fr:title
text="Exercises › A tighter recurrence bound"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › A tighter recurrence bound</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Find an upper bound for the recurrence given by <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+1]]></fr:tex>.  You should be
able to find a tighter bound than <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:uri><fr:display-uri>focs-ex-5-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:route><fr:title
text="Exercises › Complexity of bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Complexity of bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (bubble sort) consists of looking at adjacent pairs of elements,
exchanging them if they are out of order and repeating this process until no more exchanges are
possible. State, with justification, the time complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:uri><fr:display-uri>focs-ex-5-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:route><fr:title
text="Exercises › Complexity of selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Complexity of selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (selection sort) consists of looking at the elements to be sorted,
identifying and removing a minimal element, which is placed at the head of the result. The tail is
obtained by recursively sorting the remaining elements. State, with justification, the time
complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:uri><fr:display-uri>focs-ex-4-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-5/</fr:route><fr:title
text="Exercises › Counting ways of making change"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Counting ways of making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the number of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">ways of making change</fr:link> for <fr:tex
display="inline"><![CDATA[n]]></fr:tex> (ignoring order) is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> if there are two
legal coin values. What if there are three, four, … coin values?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-2/</fr:uri><fr:display-uri>focs-ex-2-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-2/</fr:route><fr:title
text="Exercises › Extending the complexity table"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › Extending the complexity table</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Add a column to the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sillysum/"
title="Silly Summing the First n Integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sillysum/"
display-uri="focs-sillysum"
type="local">table of complexities</fr:link> from <html:em>The Design and Analysis of Computer Algorithms</html:em> with the heading <html:em>60 hours:</html:em></html:p><html:table>
  <html:tr><html:th>complexity</html:th><html:th>1 second</html:th><html:th>1 minute</html:th><html:th>1 hour</html:th><html:th>60 hours</html:th></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n]]></fr:tex></html:td><html:td>1000</html:td><html:td>60 000</html:td><html:td>3 600 000</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n \log  n]]></fr:tex></html:td><html:td>140</html:td><html:td>4 895</html:td><html:td>204 095</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{2}]]></fr:tex></html:td><html:td>31</html:td><html:td>244</html:td><html:td>1 897</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[n^{3}]]></fr:tex></html:td><html:td>10</html:td><html:td>39</html:td><html:td>153</html:td><html:td /></html:tr>
  <html:tr><html:td><fr:tex
display="inline"><![CDATA[2^{n}]]></fr:tex></html:td><html:td>9</html:td><html:td>15</html:td><html:td>21</html:td><html:td /></html:tr>
</html:table></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:uri><fr:display-uri>focs-ex-3-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:route><fr:title
text="Exercises › Last element of a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Last element of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the last element of a non-empty list. How efficiently can this be done?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:uri><fr:display-uri>focs-ex-7-7</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:route><fr:title
text="Exercises › Linear traversals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Linear traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>preord</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>inord</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>postord</html:code></fr:link> all take linear time in the size of the
tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:uri><fr:display-uri>focs-ex-7-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:route><fr:title
text="Exercises › Quadratic traversals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Quadratic traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>preorder</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>postorder</html:code></fr:link> all require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time in the worst
case, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the size of the tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:uri><fr:display-uri>focs-ex-10-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:route><fr:title
text="Exercises › Search with a branching factor near one"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Search with a branching factor near one</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
title="Iterative deepening: Another Exhaustive Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
display-uri="focs-iterative-deepening"
type="local">Iterative deepening</fr:link> is inappropriate if <fr:tex
display="inline"><![CDATA[b\approx 1]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[b]]></fr:tex> is the branching factor. What search
strategy is appropriate in this case?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2-3/</fr:uri><fr:display-uri>focs-ex-2-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-2-3/</fr:route><fr:title
text="Exercises › Simplifying sums in O notation"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-2/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-2/"
display-uri="focs-ex-2"
type="local">Exercises</fr:link> › Simplifying sums in O notation</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Let <fr:tex
display="inline"><![CDATA[g_1]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[g_k]]></fr:tex> be functions such that <fr:tex
display="inline"><![CDATA[g_i(n)\ge 0]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=1]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[k]]></fr:tex> and all sufficiently
large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>Show that if <fr:tex
display="inline"><![CDATA[f(n) = O(a_1 g_1(n)+\cdots +a_k g_k(n))]]></fr:tex> then <fr:tex
display="inline"><![CDATA[f(n) = O(g_1(n)+\cdots +g_k(n))]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:uri><fr:display-uri>focs-ex-10-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:route><fr:title
text="Exercises › Tree-based queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Tree-based queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Suppose that we have an implementation of queues, based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>, such that each operation
takes logarithmic time in the worst case. Outline the advantages and drawbacks of such an
implementation compared with one presented above.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-lists/</fr:uri><fr:display-uri>focs-topic-lists</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-lists/</fr:route><fr:title
text="Lists">Lists</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/</fr:uri><fr:display-uri>focs-change-all</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-all/</fr:route><fr:title
text="All Ways of Making Change">All Ways of Making Change</fr:title></fr:frontmatter><fr:mainmatter><html:p>Now we generalise the problem to return the list of <html:em>all possible ways</html:em> of making change,
and write a new <html:code>change</html:code> function.</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Look at the type: the result is now a list of lists.
The code will also never raise <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>.  It expresses failure by returning an
empty list of solutions: it returns <html:code>[]</html:code> if the till is empty and the
amount is nonzero.</html:p><html:p>If the amount is zero, then there is only one way of making change;
the result should be <html:code><![CDATA[[[]]]]></html:code>.  This is success in the base case.</html:p><html:p>In nontrivial cases, there are two sources of solutions: to use a coin (if
possible) and decrease the amount accordingly, or to remove the current coin
value from consideration.</html:p><html:p>The function <html:code>allc</html:code> is declared locally in order to make use
of <html:code>c</html:code>, the current coin.  It adds an extra <html:code>c</html:code> to all the
solutions returned by the recursive call to make change for <html:code>amt - c</html:code>.</html:p><html:p>Observe the naming convention: <html:code>cs</html:code> is a list of coins, while
<html:code>css</html:code> is a list of such lists.  The trailing ‘s’ is suggestive of a
plural.</html:p><html:p>This complicated program, and the even trickier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-faster/"
title="All Ways of Making Change — Faster!"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/"
display-uri="focs-change-faster"
type="local">faster version</fr:link>, are
included as challenges.  Are you enthusiastic enough to work them out?  We
shall revisit the “making change” task later to illustrate <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-exceptions/"
title="Making Change with Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/"
display-uri="focs-change-exceptions"
type="local">exception-handling</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:uri><fr:display-uri>focs-change-faster</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-faster/</fr:route><fr:title
text="All Ways of Making Change — Faster!">All Ways of Making Change — Faster!</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec change till amt chg chgs =
    match till, amt with
    | _       , 0   -> chg::chgs
    | []      , _   -> chgs
    | c::till , amt -> if amt < 0 then chgs
                       else change (c::till) (amt - c) (c::chg)
                                   (change till amt chg chgs)
val change : int list -> int -> int list -> int list list -> int list list =
  <fun>]]></html:pre><html:p>We’ve added <html:em>another</html:em> accumulating parameter!  Repeatedly improving simple code
is called <html:em>stepwise refinement</html:em>.</html:p><html:p>Two extra arguments eliminate many <html:code>::</html:code> and append operations from the
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all-solutions <html:code>change</html:code></fr:link> function.  The first, <html:code>chg</html:code>, accumulates the coins chosen so
far; one evaluation of <html:code>c::chg</html:code> replaces many evaluations of <html:code>allc</html:code>.  The
second, <html:code>chgs</html:code>, accumulates the list of solutions so far; it avoids the need
for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link>.  This version runs several times faster than the previous one.</html:p><html:p>Making change is still extremely slow for an obvious reason: the number of
solutions grows rapidly in the amount being changed.  Using 50, 20, 10, 5,
2 and 1, there are 4366 ways of expressing 99.</html:p><html:p>Our three change functions illustrate a basic technique: program development
by stepwise refinement.  Begin by writing a very simple program and add
requirements individually.  Add efficiency refinements last of all.
Even if the simpler program cannot be included in the next version and has
to be discarded, one has learned about the task by writing it.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/</fr:uri><fr:display-uri>focs-making-change</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-making-change/</fr:route><fr:title
text="An Application: Making Change">An Application: Making Change</fr:title></fr:frontmatter><fr:mainmatter><html:p>Consider a till that has unlimited supplies of coins.  The largest coins should be tried
first, to avoid giving change all in pennies.  The list of legal coin values,
called <html:code>till</html:code>, is given in descending order, such as 50, 20, 10, 5,
2 and 1.  (Recall that the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">head of a list</fr:link> is the element most easily reached.)
The code for <html:code>change</html:code> is based on simple observations:</html:p><html:ul><html:li>Change for zero consists of no coins at all.  (Note the pattern of <html:code>0</html:code> in the first clause.)</html:li>
  <html:li>For a nonzero amount, try the largest available coin.  If it is small enough, use it and decrease the amount accordingly.</html:li>
  <html:li>Exclude from consideration any coins that are too large.</html:li></html:ul><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise (Failure "no more coins!")
    | c::till, amt -> if amt < c then change till amt
                      else c :: change (c::till) (amt - c)
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>Although nobody considers making change for zero, this is the simplest way to
make the algorithm terminate.  Most iterative procedures become simplest if,
in their base case, they do nothing.  A base case of one instead of zero is
often a sign of a novice programmer.</html:p><html:ul><html:li>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link> <html:em>terminates</html:em> when <html:code>amt = 0</html:code>.</html:li>
  <html:li>Tries the <html:em>largest coin first</html:em> to use large coins.</html:li>
  <html:li>The algorithm is <html:em>greedy</html:em> and can fail!</html:li></html:ul><html:p>The function can terminate either with success or failure.  It fails by
raising exception <html:code>Failure</html:code> namely if <html:code>till</html:code> becomes empty while <html:code>amt</html:code> is still nonzero.
(<fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">Exceptions</fr:link> will be discussed later.)</html:p><html:p>Unfortunately, failure can occur even when change can be made.  The greedy
"largest coin first" approach is to blame.  Suppose we have coins of values 5
and 2, and must make change for 6; the only way is <fr:tex
display="inline"><![CDATA[6=2+2+2]]></fr:tex>, ignoring the 5.
<html:em>Greedy algorithms</html:em> are often effective, but not here.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:uri><fr:display-uri>focs-quicksort-append-free</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:route><fr:title
text="Append-Free Quicksort">Append-Free Quicksort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quik = function
    | ([], sorted) -> sorted
    | ([x], sorted) -> x::sorted
    | a::bs, sorted ->
       let rec part = function
         | l, r, [] -> quik (l, a :: quik (r, sorted))
         | l, r, x::xs ->
             if x <= a then
               part (x::l, r, xs)
             else
               part (l, x::r, xs)
       in
       part ([], [], bs)
val quik : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>The list <html:code>sorted</html:code> accumulates the result in the <html:em>combine</html:em> stage of
the quicksort algorithm.  We have again used the standard technique for
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-rev/"
title="Reversing a List in O(n)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/"
display-uri="focs-rev"
type="local">eliminating append</fr:link>.  Calling <html:code>quik(xs, sorted)</html:code> reverses the elements of
<html:code>xs</html:code> and prepends them to the list <html:code>sorted</html:code>.</html:p><html:p>Looking closely at <html:code>part</html:code>, observe that <html:code>quik(r, sorted)</html:code> is
performed first.  Then <html:code>a</html:code> is consed to this sorted list.  Finally,
<html:code>quik</html:code> is called again to sort the elements of <html:code>l</html:code>.</html:p><html:p>The speedup is significant.  An imperative quicksort coded in Pascal (taken
from <fr:link
href="https://algs4.cs.princeton.edu/20sorting/"
type="external">Sedgewick</fr:link>) is just slightly faster than function
<html:code>quik</html:code>.  The near-agreement is surprising because the computational overheads
of lists exceed those of arrays.  In realistic applications, comparisons are
the dominant cost and the overheads matter even less.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/</fr:uri><fr:display-uri>focs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-append/</fr:route><fr:title
text="Append: List Concatenation">Append: List Concatenation</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec append xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> x :: append xs ys
val append : 'a list -> 'a list -> 'a list = <fun>
# append [1; 2; 3] [4]
- : int list = [1; 2; 3; 4]
# let (@) = append
val ( @ ) : 'a list -> 'a list -> 'a list = <fun>
# [1; 2; 3] @ [4]
- : int list = [1; 2; 3; 4]]]></html:pre><html:p>Patterns can be as complicated as we like.  Here, the two patterns are
<html:code>[], ys</html:code> and <html:code>x::xs, ys</html:code>.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {append }[1; 2; 3] [4] \Rightarrow  &\; 1 :: \text {append }[2; 3]\;[4] \\
  \Rightarrow  &\; 1 :: (2 :: \text {append }[3]\;[4]) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: \text {append }[]\;[4])) \\
  \Rightarrow  &\; 1 :: (2 :: (3 :: [4])) \ [1; 2; 3; 4]
\end {aligned}
]]></fr:tex><html:p>Here is how append might be declared, also noting that we have defined <html:code>@</html:code> as
an infix operator that is a more convenient way to call <html:code>append</html:code> on two lists.
However, this function is also not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It scans its first
argument, sets up a string of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code> operations</fr:link> (<html:code>::</html:code>) and finally does them.</html:p><html:p>It uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its first argument.
<html:em>Its costs are independent of its second argument.</html:em></html:p><html:p>An accumulating argument could make it iterative, but with considerable
complication.  The iterative version would still require <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space and time
because concatenation requires copying all the elements of the first list.
Therefore, we cannot hope for asymptotic gains; at best we can decrease the
constant factor involved in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>, but complicating the code is likely to
increase that factor.  Never add an accumulator merely out of habit.</html:p><html:p>Note append’s <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic type</fr:link>. It tells us that two lists can be joined if
their element types agree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:uri><fr:display-uri>focs-predicate-applications</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:route><fr:title
text="Applications of the Predicate Functionals">Applications of the Predicate Functionals</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let member y xs =
    exists (fun x -> x=y) xs
val member : 'a -> 'a list -> bool = <fun>
# let inter xs ys =
    filter (fun x -> member x ys) xs
val inter : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Testing whether two lists have no common elements</html:em></html:p><html:pre><![CDATA[# let disjoint xs ys =
    all (fun x -> all (fun y -> x<>y) ys) xs
val disjoint : 'a list -> 'a list -> bool = <fun>]]></html:pre><html:p>The Lists lecture presented the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link>, which tests whether a
specified value can be found as a list element, and <html:code>inter</html:code>, which returns the
“intersection” of two lists: the list of elements they have in common.</html:p><html:p>But remember: the purpose of list <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> is not to replace the
declarations of popular functions, which probably are available already.  It is
to eliminate the need for separate declarations of ad-hoc functions.  When they
are nested, like the calls to <html:code>all</html:code> in <html:code>disjoint</html:code> above, the
inner functions are almost certainly one-offs, not worth declaring separately.</html:p><html:p>Our primitives themselves can be seen as a programming language.  Part of the
task of programming is to extend our programming language with notation for
solving the problem at hand.  The levels of notation that we define should
correspond to natural <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">levels of abstraction</fr:link> in the problem domain.</html:p><html:p>Historical Note:
Alonzo Church’s <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus gave a simple syntax, <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-notation,
for expressing functions.  It is the direct precursor of OCaml’s
<html:code>fun</html:code>-notation.  It was soon shown that his system was equivalent in
computational power to Turing machines, and <html:em>Church’s thesis</html:em> states that
this defines precisely the set of functions that can be computed effectively.</html:p><html:p>The <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus had a tremendous influence on the design of functional
programming languages.  McCarthy’s Lisp was something of a false start; it
interpreted variable binding incorrectly, an error that stood for some 20
years.  But in 1966, Peter Landin (of Queen Mary College, University of London)
sketched out the main features of functional languages.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:uri><fr:display-uri>focs-tree-traversal</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:route><fr:title
text="Aside: Traversing Trees (3 Methods)">Aside: Traversing Trees (3 Methods)</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec preorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      [v] @ preorder t1 @ preorder t2
val preorder : 'a tree -> 'a list = <fun>
# let rec inorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      inorder t1 @ [v] @ inorder t2
val inorder : 'a tree -> 'a list = <fun>
# let rec postorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      postorder t1 @ postorder t2 @ [v]
val postorder : 'a tree -> 'a list = <fun>]]></html:pre><html:p><html:em>Tree traversal</html:em> means examining each node of a tree in some order.  <fr:link
href="https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming"
type="external">D. E.
Knuth</fr:link> has
identified three forms of tree traversal: preorder, inorder and
postorder.  We can code these “visiting orders” as functions
that convert trees into lists of labels.  Algorithms based on these notions
typically perform some action at each node; the functions above simply copy
the nodes into lists.  Consider the tree:</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmic3wbal56lpqlso6xcqsl6jfrutwygavrn3xds7c6ieywfjr7qdhm.svg" /></html:figure><html:ul><html:li><html:code>preorder</html:code> visits the label first (“Polish notation”), yielding <html:code>ABDECFG</html:code></html:li>
<html:li><html:code>inorder</html:code> visits the label midway, yielding <html:code>DBEAFCG</html:code></html:li>
<html:li><html:code>postorder</html:code> visits the label last (“Reverse Polish”), yielding <html:code>DEBFGCA</html:code>. You might be familiar with this concept if you own an ancient RPN calculator!</html:li></html:ul><html:p>What is the use of <html:code>inorder</html:code>? Consider applying it to a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>: the
result is a sorted list of pairs. We could use this, for example, to merge two
binary search trees. It is not difficult to transform a sorted list of pairs
into a binary search tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:uri><fr:display-uri>focs-bfs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Append">Breadth-First Tree Traversal — Using Append</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nbreadth = function
  | [] -> []
  | Lf :: ts -> nbreadth ts
  | Br (v, t, u) :: ts ->
      v :: nbreadth (ts @ [t; u])
val nbreadth : 'a tree list -> 'a list = <fun>]]></html:pre><html:p>Keeps an <html:em>enormous queue</html:em> of nodes of search, and is a wasteful use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.</html:p><html:p>Breadth-first search can be inefficient, this naive implementation especially
so.  When the search is at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> of the tree, the list contains all the
remaining trees at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex>, followed by the subtrees (all at depth <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>) of
the trees that have already been visited.  At depth 10, the list could already
contain 1024 elements.  It requires a lot of space, and aggravates this with a
gross misuse of append.  Evaluating <html:code>ts@[t, u]</html:code> copies the long list
<html:code>ts</html:code> just to insert two elements.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/</fr:uri><fr:display-uri>focs-zip</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-zip/</fr:route><fr:title
text="Building a List of Pairs">Building a List of Pairs</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec zip xs ys =
    match xs, ys with
    | (x::xs, y::ys) -> (x, y) :: zip xs ys
    | _ -> []
val zip : 'a list -> 'b list -> ('a * 'b) list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[\left .[x_1,\ldots ,x_n]\atop 
         [y_1,\ldots ,y_n]\right \}\;\longmapsto \;[(x_1,y_1),\ldots ,(x_n,y_n)]]]></fr:tex><html:p>The <html:em>wildcard</html:em> pattern <html:code>_</html:code> matches <html:em>anything</html:em>. We could have written a
variable such as <html:code>p</html:code> instead, but the wildcard reminds us that the
relevant clause ignores this argument.</html:p><html:p>The patterns are also tested in order of their definitions: first
<html:code>(x::xs, y::ys)</html:code>, then <html:code>_</html:code>.</html:p><html:p>A list of pairs of the form <fr:tex
display="inline"><![CDATA[[(x_1,y_1),\ldots ,(x_n,y_n)]]]></fr:tex> associates each
<fr:tex
display="inline"><![CDATA[x_i]]></fr:tex> with <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex>.  Conceptually, a telephone directory could be regarded as
such a list, where <fr:tex
display="inline"><![CDATA[x_i]]></fr:tex> ranges over names and <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex> over the corresponding
telephone number.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link> in such a list can find the <fr:tex
display="inline"><![CDATA[y_i]]></fr:tex> associated
with a given <fr:tex
display="inline"><![CDATA[x_i]]></fr:tex>, or vice versa—very slowly.</html:p><html:p>In other cases, the <fr:tex
display="inline"><![CDATA[(x_i,y_i)]]></fr:tex> pairs might have been generated by applying a
function to the elements of another list <fr:tex
display="inline"><![CDATA[[z_1,\ldots ,z_n]]]></fr:tex>.</html:p><html:pre><![CDATA[# let rec unzip = function
   | [] -> ([], [])
   | (x, y)::pairs ->
       let xs, ys = unzip pairs in
       (x::xs, y::ys)
val unzip : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>Given a list of pairs, <html:code>unzip</html:code> has to build <html:em>two</html:em> lists of
results, which is awkward using recursion.  The version shown above uses the
<html:em>local binding</html:em> <html:code>let p = </html:code><fr:tex
display="inline"><![CDATA[\;E_1\;]]></fr:tex><html:code> in </html:code><fr:tex
display="inline"><![CDATA[\;E_2]]></fr:tex>,
where the value of <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> is bound to the variable <html:code>p</html:code> within <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex>. The
let-construct counts as an expression and can be used (perhaps wrapped
within parentheses) wherever an expression is expected.</html:p><html:p>Note especially the phrase <html:code>let xs, ys = unzip pairs</html:code>
which binds <html:code>xs</html:code> and <html:code>ys</html:code> to the results of the recursive call.
In general, the phrase <html:code>let P = E</html:code> matches the
pattern <fr:tex
display="inline"><![CDATA[P]]></fr:tex> against the value of expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.  It binds all the variables
in <fr:tex
display="inline"><![CDATA[P]]></fr:tex> to the corresponding values.</html:p><html:p>The functions <html:code>zip</html:code> and <html:code>unzip</html:code> build and take apart lists of
pairs: <html:code>zip</html:code> pairs up corresponding list elements and <html:code>unzip</html:code>
inverts this operation.  Their types reflect what they do:</html:p><html:pre><![CDATA[# zip
- : 'a list -> 'b list -> ('a * 'b) list = <fun>
# unzip
- : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>If the lists are of unequal length, <html:code>zip</html:code> discards surplus items at the
end of the longer list.  Its first pattern only matches a pair of non-empty
lists.  The second pattern is just a wildcard and could match anything.  OCaml
tries the clauses in the order given, so the first pattern is tried first.
The second only gets arguments where at least one of the lists is empty.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-unzip/</fr:uri><fr:display-uri>focs-unzip</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-unzip/</fr:route><fr:title
text="Building a Pair of Results">Building a Pair of Results</fr:title></fr:frontmatter><fr:mainmatter><html:p>Here is a version of <html:code>unzip</html:code> that replaces the local declaration by a
function <html:code>conspair</html:code> for taking apart the pair of lists in the
recursive call.  It defines the same
computation as the previous version of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local"><html:code>unzip</html:code></fr:link> and is possibly clearer,
but not every local binding can be eliminated as easily.</html:p><html:pre><![CDATA[# let conspair ((x, y), (xs, ys)) = (x::xs, y::ys)
val conspair : ('a * 'b) * ('a list * 'b list) -> 'a list * 'b list = <fun>
# let rec unzip = function
    | [] -> ([], [])
    | xy :: pairs -> conspair (xy, unzip pairs)
val unzip : ('a * 'b) list -> 'a list * 'b list = <fun>]]></html:pre><html:p>Making the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> yields <html:code>revUnzip</html:code> below, which is
very simple.  Iteration can construct many results at once in different
argument positions.  Both output lists are built in reverse order, which can
be corrected by reversing the input to <html:code>revUnzip</html:code>.  The total costs
will probably exceed those of <html:code>unzip</html:code> despite the advantages of
iteration.</html:p><html:pre><![CDATA[# let rec revUnzip = function
    | ([], xs, ys) -> (xs, ys)
    | ((x, y)::pairs, xs, ys) ->
        revUnzip (pairs, x::xs, y::ys)
val revUnzip : ('a * 'b) list * 'a list * 'b list -> 'a list * 'b list =
  <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nlength/</fr:uri><fr:display-uri>focs-nlength</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nlength/</fr:route><fr:title
text="Computing the Length of a List">Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nlength = function
  | [] -> 0
  | x :: xs -> 1 + nlength xs
val nlength : 'a list -> int = <fun>
# nlength []
- : int = 0
# nlength [5; 6; 7]
- : int = 3]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nlength }[a; b; c] \Rightarrow  &\; 1 + \text {nlength }[b; c] \\
   \Rightarrow  &\; 1 + (1 + \text {nlength }[c]) \\
   \Rightarrow  &\; 1 + (1 + (1 + \text {nlength }[])) \\
   \Rightarrow  &\; 1 + (1 + (1 + 0)) \\
   \Rightarrow  &\; \ldots  \;\; 3
\end {aligned}
]]></fr:tex><html:p>Most list processing involves <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  This is a simple example; patterns
can be more complex.  Observe the use of a vertical bar <html:code>|</html:code> to separate the function’s
clauses.  We have <html:em>one</html:em> function declaration that handles two cases.
To understand its role, consider the following faulty code:</html:p><html:pre><![CDATA[# let rec nlength [] = 0
Line 1, characters 17-19:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_

val nlength : 'a list -> int = <fun>
# let rec nlength (x::xs) = 1 + nlength xs
Line 1, characters 17-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val nlength : 'a list -> int = <fun>]]></html:pre><html:p>These are two declarations, not one.  First we declare <html:code>nlength</html:code> to be a
function that handles only empty lists.  Then we redeclare it to be a function
that handles only non-empty lists; it can never deliver a result.  We see that
a second <html:code>let</html:code> declaration replaces any previous one rather than extending it
to cover new cases.</html:p><html:p>Now, let us return to our original declaration of <html:code>nlength</html:code>.  The length function
is <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link></html:em> and applies to <html:em>all</html:em> lists regardless of element
type!  Most programming languages lack such flexibility.</html:p><html:p>Unfortunately, this length computation is naive and wasteful.  Like
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-nsum/"
title="Summing the first n integers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nsum/"
display-uri="focs-nsum"
type="local"><html:code>nsum</html:code></fr:link> earlier, it is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">tail-recursive</fr:link>.  It
uses <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> space, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the length of its input.  As usual, the
solution is to add an accumulating argument.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:uri><fr:display-uri>focs-seq-consume</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:route><fr:title
text="Consuming a Sequence">Consuming a Sequence</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec get n s =
    match n, s with
    | 0, _            -> []
    | n, Nil          -> []
    | n, Cons (x, xf) -> x :: get (n-1) (xf ())
val get : int -> 'a seq -> 'a list = <fun>]]></html:pre><html:p>The above code gets the first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements as a list.
<html:code>xf ()</html:code> <html:em>forces</html:em> evaluation.</html:p><html:p>The function <html:code>get</html:code> converts a sequence to a list.  It takes the
first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements; it takes all of them if <fr:tex
display="inline"><![CDATA[n<0]]></fr:tex>, which can terminate only if
the sequence is finite.</html:p><html:p>In the last line of <html:code>get</html:code>, the expression <html:code>xf()</html:code> calls the tail
function, demanding evaluation of the next element.  This operation is called
<html:em>forcing</html:em> the sequence.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:uri><fr:display-uri>focs-dictionary-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:route><fr:title
text="Dictionaries">Dictionaries</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>lookup: find an item in the dictionary</html:li>
<html:li>update (insert): replace (store) an item in the dictionary</html:li>
<html:li>delete: remove an item from the dictionary</html:li>
<html:li>empty: the null dictionary</html:li>
<html:li>Missing: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> for errors in <html:code>lookup</html:code> and <html:code>delete</html:code></html:li></html:ul><html:p>Ideally, an <html:em>abstract type</html:em> should provide these operations and hide the internal data structures.</html:p><html:p>A dictionary attaches values to identifiers, called “keys”.  Before choosing
the internal representation for a data structure, you need to specify the full
set of operations. In fact, here we only consider <html:code>update</html:code> (associating a
value with an identifier) and <html:code>lookup</html:code> (retrieving such a value). Deletion
is more difficult and would limit our choices. Some applications may need
additional operations, such as <html:code>merge</html:code> (combining two dictionaries). We
shall see that update can be done efficiently in a functional style, without
excessive copying.</html:p><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent dictionaries. Abstract
types can be declared in any modern programming language. Java’s <html:em>objects</html:em>
serve this role, as do OCaml’s modules. This course does not cover modules, and we
simply declare the dictionary operations individually.</html:p><html:p>An <html:em>association list</html:em> (a list of pairs) is the simplest dictionary representation.
Lookup is by <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link>, and therefore slow: <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>. Association lists are
only usable if there are few keys in use. However, they are general in that the
keys do not need a concept of ordering, only equality.</html:p><html:pre><![CDATA[# exception Missing
exception Missing
# let rec lookup a = function
  | [] -> raise Missing
  | (x, y) :: pairs ->
      if a = x then y
      else lookup a pairs
val lookup : 'a -> ('a * 'b) list -> 'b = <fun>
# let update (l, b, y) = (b, y) :: l
val update : ('a * 'b) list * 'a * 'b -> ('a * 'b) list = <fun>]]></html:pre><html:p>To enter a new <html:code>(key, value)</html:code> pair, simply “cons” it to the list with <html:code>update</html:code>.
This takes constant time, which is the best we could hope for.  But the space
requirement is huge: linear in the number of updates, not in the number of
distinct keys. Obsolete entries are never deleted: that would require first
finding them, increasing the update time from <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:uri><fr:display-uri>focs-functional-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:route><fr:title
text="Efficient Functional Queues: Code">Efficient Functional Queues: Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a queue =
  | Q of 'a list * 'a list
type 'a queue = Q of 'a list * 'a list
# let norm = function
  | Q ([], tls) -> Q (List.rev tls, [])
  | q -> q
val norm : 'a queue -> 'a queue = <fun>
# let qnull = function
  | Q ([], []) -> true
  | _ -> false
val qnull : 'a queue -> bool = <fun>
# let enq (Q (hds, tls)) x = norm (Q (hds, x::tls))
val enq : 'a queue -> 'a -> 'a queue = <fun>
# exception Empty
exception Empty
# let deq = function
  | Q (x::hds, tls) -> norm (Q (hds, tls))
  | _ -> raise Empty
val deq : 'a queue -> 'a queue = <fun>
# let qempty = Q ([], [])
val qempty : 'a queue = Q ([], [])
# let qhd = function
  | Q (x::_, _) -> x
  | _ -> raise Empty
val qhd : 'a queue -> 'a = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> of queues prevents confusion with other pairs of lists.  The empty
queue has both parts empty.</html:p><html:p>The function <html:code>norm</html:code> puts a queue into normal form, ensuring that the front part
is never empty unless the entire queue is empty.  Functions <html:code>deq</html:code> and <html:code>enq</html:code>
call <html:code>norm</html:code> to normalise their result.</html:p><html:p>Because queues are in normal form, their head is certain to be in their
front part, so <html:code>qhd</html:code> looks there.</html:p><html:p>Let us analyse the cost of an execution comprising (in any possible order) <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
<html:code>enq</html:code> operations and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> <html:code>deq</html:code> operations, starting with an
empty queue.  Each <html:code>enq</html:code> operation will perform one cons, adding an
element to the rear part.  Since the final queue must be empty, each element
of the rear part gets transferred to the front part.  The corresponding
reversals perform one cons per element.  Thus, the total cost of the series of
queue operations is <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> cons operations, an average of 2 per operation.  The
amortized time is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p><html:p>There is a catch.  The conses need not be distributed evenly; reversing a long
list could take up to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> of them.  Unpredictable delays make the approach
unsuitable for <html:em>real-time programming</html:em> where deadlines must be met.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:uri><fr:display-uri>focs-functional-queues-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:route><fr:title
text="Efficient Functional Queues: Idea">Efficient Functional Queues: Idea</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Represent the queue <fr:tex
display="inline"><![CDATA[x_1\; x_2\; \ldots \; x_m\; y_n\; \ldots \; y_1]]></fr:tex> by any <html:em>pair of lists</html:em>
    <fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \; [y_1,y_2,\ldots ,y_n])]]></fr:tex></html:li>
  <html:li>Add new items to the <html:em>rear list</html:em></html:li>
  <html:li>Remove items from <html:em>front list</html:em> and if empty move <html:em>rear</html:em> to <html:em>front</html:em></html:li>
  <html:li><html:em>Amortized</html:em> time per operation is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p>Queues require efficient access at both ends: at the front, for removal, and
at the back, for insertion.  Ideally, access should take constant time,
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.  It may appear that lists cannot provide such access.  If
<html:code>enq(q, x)</html:code> performs <html:code>q@[x]</html:code>, then this operation will be <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  We
could represent queues by reversed lists, implementing <html:code>enq(q, x)</html:code> by
<html:code>x::q</html:code>, but then the <html:code>deq</html:code> and <html:code>qhd</html:code> operations would be
<fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Linear time is intolerable: a series of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> queue operations
could then require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time.</html:p><html:p>The solution is to represent a queue by a pair of lists, where</html:p><fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \, [y_1,y_2,\ldots ,y_n])]]></fr:tex><html:p>represents the queue <fr:tex
display="inline"><![CDATA[x_1 x_2 \ldots  x_m y_n \ldots  y_1]]></fr:tex>.</html:p><html:p>The front part of the queue is stored in order, and the rear part is stored in
reverse order.  The <html:code>enq</html:code> operation adds elements to the rear part
using cons, since this list is reversed; thus, <html:code>enq</html:code> takes constant
time.  The <html:code>deq</html:code> and <html:code>qhd</html:code> operations look at the front part,
which normally takes constant time, since this list is stored in order.  But
sometimes <html:code>deq</html:code> removes the last element from the front part; when this
happens, it reverses the rear part, which becomes the new front part.</html:p><html:p><html:em>Amortized</html:em> time refers to the cost per operation averaged over the
lifetime of any complete execution.  Even for the worst possible execution,
the average cost per operation turns out to be constant; see the analysis
below.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/</fr:uri><fr:display-uri>focs-length</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-length/</fr:route><fr:title
text="Efficiently Computing the Length of a List">Efficiently Computing the Length of a List</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec addlen n = function
  | []    -> n
  | x::xs -> addlen (n + 1) xs
val addlen : int -> 'a list -> int = <fun>
# addlen 0 [5; 6; 7]
- : int = 3]]></html:pre><html:p>Recall that the use of <html:code>function</html:code> introduces an extra (unnamed) argument
that is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matched</fr:link> in the subsequent clauses; in this case, to break
open the list.</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {addlen }0 [a; b; c] \Rightarrow  &\;  \text {addlen }1\;[b; c] \\
  \Rightarrow   &\; \text {addlen }2\;[c] \\
  \Rightarrow   &\; \text {addlen }3\;[] \\
  \Rightarrow   &\; 3
\end {aligned}
]]></fr:tex><html:p>Function <html:code>addlen</html:code> is again <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.  Its type mentions the integer
accumulator.</html:p><html:p>Now we may declare an efficient length function.  It is simply a wrapper for
<html:code>addlen</html:code>, supplying zero as the initial value of <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# let length xs = addlen 0 xs
val length : 'a list -> int = <fun>
# length [5; 6; 7; 8]
- : int = 4]]></html:pre><html:p>The recursive calls do not nest: this version is <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  It takes <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
space.  Obviously its time requirement is <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> because it takes at least <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
steps to find the length of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/</fr:uri><fr:display-uri>focs-equality</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-equality/</fr:route><fr:title
text="Equality Tests">Equality Tests</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec member x = function
   | [] -> false
   | y::l ->
      if x = y then true
      else member x l
val member : 'a -> 'a list -> bool = <fun>]]></html:pre><html:p>All the list functions we have encountered up to now have been “<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>”,
working for lists of any type.  Function <html:code>member</html:code> uses <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link> to report
whether or not <html:code>x</html:code> occurs in <html:code>l</html:code>.</html:p><html:p>To do this generically, it uses a special feature of OCaml known as
“polymorphic equality”, which manifests itself via the <html:code>=</html:code>, <html:code>&gt;=</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code> and
<html:code>&lt;</html:code> operators.  These operators inspect the <html:em>structure</html:em> of the values using a
consistent order.  Types you can legitimately compare this way include integers,
strings, booleans, and tuples or lists of primitive types.</html:p><html:p>More complex types can be compared this way within careful limits: recursive
structures or function values will not work (we will cover function values in
the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-currying/"
title="Curried Functions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/"
display-uri="focs-currying"
type="local">Currying lecture</fr:link> later).  For now, it is sufficient to use these magic
polymorphic equality operators.  As you get more familiar with OCaml and the
use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functions/"
title="Functions as Values"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/"
display-uri="focs-functions"
type="local">higher order functions</fr:link> (also covered in a later lecture), you will
encounter the use of explicit <html:code>compare</html:code> functions that are used to provide more
complex equality tests.</html:p><html:p>The presence of polymorphic equality is a contentious feature in OCaml.  While
it provides a great ease of use in smaller codebases, it starts to become more
dangerous when building larger OCaml-based systems.  Most large-scale users of
OCaml tend towards not using it in important code, but it is just fine for our
purposes while learning the beginning steps of computer science.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/</fr:uri><fr:display-uri>focs-transpose</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-transpose/</fr:route><fr:title
text="Example: Matrix Transpose">Example: Matrix Transpose</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {pmatrix}
           a   & b & c \\
           d   & e & f
   \end {pmatrix}^T =
   \begin {pmatrix}
        a & d     \\
        b & e     \\
        c & f
\end {pmatrix}
]]></fr:tex><html:pre><![CDATA[# let rec transp = function
    | []::_ -> []
    | rows -> (map List.hd rows) ::
              (transp (map List.tl rows))
val transp : 'a list list -> 'a list list = <fun>]]></html:pre><html:p>A matrix can be viewed as a list of rows, each row a list of matrix elements.
This representation is not especially efficient compared with the conventional
one (using arrays).  Lists of lists turn up often, though, and we can see how
to deal with them by taking familiar matrix operations as examples.
<html:em>ML for the Working Programmer</html:em> goes as far as Gaussian elimination,
which presents surprisingly few difficulties.</html:p><html:p>The transpose of the matrix
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix} a & b & c \\
                           d & e & f\end {smallmatrix}\right )]]></fr:tex>
is
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix}
        a & d     \\
        b & e     \\
        c & f
   \end {smallmatrix}\right )]]></fr:tex>,
which in OCaml corresponds to the following transformation on lists of lists:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {[[a; b; c]; [d; e; f]]} \Rightarrow & \text { [[a; d]; [b; e]; [c; f]]}
\end {aligned}
]]></fr:tex><html:p>The workings of function <html:code>transp</html:code> are simple.  If <html:code>rows</html:code> is the
matrix to be transposed, then <html:code>map hd</html:code> extracts its first column and
<html:code>map tl</html:code> extracts its second column:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {map hd rows} \Rightarrow  & \text { [a; d]}\\
\text {map tl rows} \Rightarrow  & \text { [[b; c]; [e; f]]}
\end {aligned}
]]></fr:tex><html:p>A recursive call transposes the latter matrix, which is then given the column
<html:code>[a; d]</html:code> as its first row.
The two functions expressed using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> would otherwise have to be declared
separately.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/</fr:uri><fr:display-uri>focs-head-tail</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-head-tail/</fr:route><fr:title
text="Getting at the Head and Tail">Getting at the Head and Tail</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let null = function
    | [] -> true
    | x :: l -> false
val null : 'a list -> bool = <fun>
# null []
- : bool = true
# null [1; 2; 3]
- : bool = false
# let hd (x::l) = x
Line 1, characters 8-14:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val hd : 'a list -> 'a = <fun>
# hd [1; 2; 3]
- : int = 1
# let tl (x::l) = l
Line 1, characters 8-14:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val tl : 'a list -> 'a list = <fun>
# tl [7; 6; 5]
- : int list = [6; 5]]]></html:pre><html:p>The empty list has neither head nor tail.  Applying <html:code>hd</html:code> or <html:code>tl</html:code> to <html:code>[]</html:code>
is an error—strictly speaking, an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">“exception”</fr:link>.  The function <html:code>null</html:code> can
be used to check for the empty list beforehand.  Taking a list apart using
combinations of <html:code>hd</html:code> and <html:code>tl</html:code> is hard to get right.  Fortunately, it is seldom
necessary because of <html:em>pattern-matching</html:em>.</html:p><html:p>The declaration of <html:code>null</html:code> introduces a new concept known as "pattern matching",
which we will explore more in subsequent lectures. For now, it is sufficient
to observe that <html:code>let null = function</html:code> allows for matching on the two possible values
that might be passed in as argument to <html:code>null</html:code> here: one for the empty list (for which it returns <html:code>true</html:code>)
and one for non-empty lists (for which it returns <html:code>false</html:code>).</html:p><html:p>The declaration of <html:code>hd</html:code> above has only one clause, for non-empty lists.  They
have the form <html:code>x::l</html:code> and the function returns <html:code>x</html:code>, which is the head.  If you
compile this program, OCaml also prints a warning to tell us that calling
the function could raise an exception because not all possible inputs are handled,
including a counter-example (in this case, the empty list <html:code>[]</html:code>). The declaration of <html:code>tl</html:code> is similar to <html:code>hd</html:code>.</html:p><html:p>These three primitive functions are <html:em>polymorphic</html:em> and allow flexibility in the
types of their arguments and results. Note their types!</html:p><html:pre><![CDATA[# null
- : 'a list -> bool = <fun>
# hd
- : 'a list -> 'a = <fun>
# tl
- : 'a list -> 'a list = <fun>]]></html:pre><html:p>Symbols <html:code>'a</html:code> and <html:code>'b</html:code> are called <html:em>type variables</html:em> and stand for any types. Code
written using these functions is checked for type correctness at compile time.
And this guarantees strong properties at run time, for example that the
elements of any list all have the same type.  They are usually read as their
corresponding greek characters; <html:code>'a</html:code> is "alpha", <html:code>'b</html:code> is "beta", and so on.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:uri><fr:display-uri>focs-insertion-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:route><fr:title
text="Insertion Sort">Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:p>An insert operation does <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> comparisons on average.</html:p><html:pre><![CDATA[# let rec ins x = function
    | [] -> [x]
    | y::ys -> if x <= y then x :: y :: ys
               else y :: ins x ys
val ins : 'a -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Insertion sort</html:em> takes <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons on average:</html:p><html:pre><![CDATA[let rec insort = function
    | [] -> []
    | x::xs -> ins x (insort xs)]]></html:pre><html:p>Items from the input are copied one at a time to the output.  Each new item is
inserted into the right place so that the output is always in order.</html:p><html:p>We could easily write <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> versions of these functions, but to no purpose.
Insertion sort is slow because it does <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons (and a lot of list
copying), not because it is recursive.  Its quadratic runtime makes it nearly
useless: it takes 174 seconds for our example while the next-worst figure is
1.4 seconds.</html:p><html:p>Insertion sort is worth considering because it is easy to code and illustrates
the concepts.  Two efficient sorting algorithms, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link> and heapsort, can be
regarded as refinements of insertion sort.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/</fr:uri><fr:display-uri>focs-while</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-while/</fr:route><fr:title
text="Iteration: the while command">Iteration: the while command</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let tlopt = function
  | [] -> None
  | _::xs -> Some xs
val tlopt : 'a list -> 'a list option = <fun>
# let length xs =
    let lp  = ref xs in (* list of uncounted elements *)
    let np  = ref 0  in (* accumulated count *)
    let fin = ref false in
    while not !fin do
      match tlopt !lp with
      | None -> fin := true
      | Some xs ->
          lp := xs;
          np := 1 + !np
    done;
    !np (* the final count is returned *)
val length : 'a list -> int = <fun>]]></html:pre><html:p>Once we can change the state, we need to do so repeatedly.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">Recursion</fr:link> can
serve this purpose, but having to declare a procedure for every loop is
clumsy, and compilers for conventional languages seldom exploit
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
title="Recursion vs Iteration"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
display-uri="focs-recursion-vs-iteration"
type="local">tail-recursion</fr:link>.</html:p><html:p>Early programming languages provided little support for repetition.  The
programmer had to set up loops using goto commands, exiting the loop using
another goto controlled by an <html:code>if</html:code>.  Modern languages provide a
confusing jumble of looping constructs, the most fundamental of which is
<html:code>while B do C</html:code>.  The boolean expression <fr:tex
display="inline"><![CDATA[B]]></fr:tex> is evaluated,
and if true, command <fr:tex
display="inline"><![CDATA[C]]></fr:tex> is executed and the command repeats.  If <fr:tex
display="inline"><![CDATA[B]]></fr:tex>
evaluates to false then the <html:code>while</html:code> command terminates, perhaps without
executing <fr:tex
display="inline"><![CDATA[C]]></fr:tex> even once.</html:p><html:p>OCaml’s main looping construct is <html:code>while</html:code>, which returns the value <html:code>()</html:code>.  The
function <html:code>length</html:code> declares <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> to hold the list under
examination (<html:code>lp</html:code>) and number of elements counted so far (<html:code>np</html:code>) as well
as whether the end of the list has been reached (the boolean reference <html:code>fin</html:code>).
While the list is non-empty, we skip over one more element (by setting it to
its tail) and count that element.</html:p><html:p>The body of the <html:code>while</html:code> loop first checks to see if the end of the list has
been reached, in which case it sets the <html:code>fin</html:code> variable to true.  If there is a
tail value, then two assignments are executed in sequence.  The <html:code>lp</html:code> reference
is set to the tail of the list, and the <html:code>np</html:code> reference integer is incremented
by one.  When the while loop terminates due to the <html:code>fin</html:code> variable being set to
true, the expression <html:code>!np</html:code> returns the computed length as the function’s
result.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:uri><fr:display-uri>focs-seq-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:route><fr:title
text="Joining Two Sequences">Joining Two Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec appendq xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons(x, fun () -> appendq (xf ()) yq)
val appendq : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>A more fair alternative:</html:p><html:pre><![CDATA[# let rec interleave xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons (x, fun () -> interleave yq (xf ()))
val interleave : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>Most list functions and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> have analogues on sequences, but strange
things can happen.  Can an infinite list be reversed?</html:p><html:p>Function <html:code>appendq</html:code> is precisely the same idea as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>
from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">Lists lecture</fr:link>; it concatenates two sequences.  If the first
argument is infinite, then <html:code>appendq</html:code> never gets to its second argument,
which is lost.  Concatenation of infinite sequences is not terribly
interesting.</html:p><html:p>The function <html:code>interleave</html:code> avoids this problem by exchanging the two
arguments in each recursive call.  It combines the two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, losing no
elements.  Interleaving is the right way to combine two potentially infinite
information sources into one.</html:p><html:p>In both function declarations, observe that each <html:code>xf ()</html:code> is enclosed
within a <fr:tex
display="inline"><![CDATA[{\tt  fun () \rightarrow  \ldots }]]></fr:tex>.  Each <html:em>force</html:em> is enclosed within a
<html:em>delay</html:em>.  This practice makes the functions lazy.  A force not enclosed
in a delay, as in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-seq-consume/"
title="Consuming a Sequence"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/"
display-uri="focs-seq-consume"
type="local"><html:code>get</html:code></fr:link> above, runs the risk of evaluating the sequence
in full.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-lists/</fr:uri><fr:display-uri>focs-lazy-lists</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-lists/</fr:route><fr:title
text="Lazy Lists (or Streams)">Lazy Lists (or Streams)</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Lists of possibly <html:em>infinite</html:em> length</html:li>
  <html:li>Elements <html:em>computed upon demand</html:em></html:li>
  <html:li><html:em>Avoids waste</html:em> if there are many solutions</html:li>
  <html:li><html:em>Infinite</html:em> values are a useful abstraction</html:li></html:ul><html:p>In OCaml, we can implement laziness by <html:em>delaying evaluation</html:em> of the tail of
the list.</html:p><html:p>Lazy lists have practical uses.  Some algorithms, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>, can
yield many solutions when only a few are required.  Sometimes the original
problem concerns infinite series: with lazy lists, we can pretend they really
exist!</html:p><html:p>We are now dealing with <html:em>infinite</html:em> (or at least unbounded) computations.
A potentially infinite source of data is processed one element at a time, upon
demand.  Such programs are harder to understand than terminating ones and have
more ways of going wrong.</html:p><html:p>Some purely functional languages, such as Haskell, use lazy evaluation
everywhere.  Even the if-then-else construct can be a function, and all lists
are lazy.  In OCaml, we can declare a type of lists such that evaluation of the
tail does not occur until demanded.  <html:em>Delayed</html:em> evaluation is weaker than
<html:em>lazy</html:em> evaluation, but it is good enough for our purposes and often the
best compromise for performance and memory usage.</html:p><html:p>The traditional word “stream” is reserved in OCaml parlance for
input/output channels.  Let us call lazy lists <html:em>sequences</html:em> instead.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/</fr:uri><fr:display-uri>focs-def-lazy-list</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-lazy-list/</fr:route><fr:title
text="Lazy list">Lazy list</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A lazy list is a list of possibly <html:em>infinite</html:em> length whose elements are
<html:em>computed upon demand</html:em>; in OCaml we implement laziness by <html:em>delaying
evaluation</html:em> of the tail of the list. The traditional word “stream” is reserved in
OCaml parlance for input/output channels, so we call lazy lists <html:em>sequences</html:em>
instead.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lazy-lists/"
title="Lazy Lists (or Streams)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-lists/"
display-uri="focs-lazy-lists"
type="local">Lazy Lists</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:uri><fr:display-uri>focs-linear-search</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:route><fr:title
text="Linear Search">Linear Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>find <fr:tex
display="inline"><![CDATA[x]]></fr:tex> in list <fr:tex
display="inline"><![CDATA[[x_1,\ldots ,x_n]]]></fr:tex> by comparing with each element</html:li>
  <html:li>obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time</html:li>
  <html:li>simple &amp; general</html:li>
  <html:li>ordered searching needs only <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:li>
  <html:li>indexed lookup needs only <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p><html:em>Linear search</html:em> is the obvious way to find a desired item in a
collection: simply look through all the items, one at a time.  If <fr:tex
display="inline"><![CDATA[x]]></fr:tex> is in
the list, then it will be found in <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> steps on average, and even the worst
case is obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p><html:p>Large collections of data are usually ordered or indexed so that items can be
found in <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> time, which is exponentially better than <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Even
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> is achievable (using a hash table), though subject to the usual
proviso that machine limits are not exceeded.</html:p><html:p>Efficient indexing methods are of prime importance: consider Web
search engines.  Nevertheless, linear search is often used to search small
collections because it is so simple and general, and it is the starting point
for better algorithms.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:uri><fr:display-uri>focs-predicate-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:route><fr:title
text="List Functionals for Predicates">List Functionals for Predicates</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec exists p = function
  | [] -> false
  | x::xs -> (p x) || (exists p xs)
val exists : ('a -> bool) -> 'a list -> bool = <fun>
# let rec filter p = function
  | [] -> []
  | x::xs ->
      if p x then
        x :: filter p xs
      else
        filter p xs
val filter : ('a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>A <html:em>predicate</html:em> is a <html:em>boolean-valued</html:em> function.</html:p><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>exists</html:code> transforms a predicate into a predicate over
lists.  Given a list, <html:code>exists p</html:code> tests whether or not some list element
satisfies <html:code>p</html:code> (making it return <html:code>true</html:code>).  If it finds one, it stops
searching immediately, thanks to the behaviour of the lazy <html:code>||</html:code> operator.</html:p><html:p>Dually, we have a functional to test whether all list elements satisfy the
predicate.  If it finds a counterexample then it, too, stops searching.</html:p><html:pre><![CDATA[# let rec all p = function
  | [] -> true
  | x::xs -> (p x) && all p xs
val all : ('a -> bool) -> 'a list -> bool = <fun>]]></html:pre><html:p>The <html:code>filter</html:code> functional, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>, transforms lists.  It applies a
predicate to all the list elements, but instead of returning the
resulting values (which could only be <html:code>true</html:code> or <html:code>false</html:code>), it returns
the list of elements satisfying the predicate.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/</fr:uri><fr:display-uri>focs-take-drop</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-take-drop/</fr:route><fr:title
text="List Utilities: take and drop">List Utilities: take and drop</fr:title></fr:frontmatter><fr:mainmatter><html:p>This lecture examines more list utilities, illustrating more patterns of
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>, and concludes with a small program for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.</html:p><html:p>The functions <html:code>take</html:code> and <html:code>drop</html:code> divide a list
into parts, returning or discarding the first <fr:tex
display="inline"><![CDATA[i]]></fr:tex> elements.</html:p><fr:tex
display="block"><![CDATA[xs = [\underbrace {x_0,\ldots ,x_{i-1}}_{\text {take i xs}},
      \underbrace {x_i,\ldots ,x_{n-1}}_{\text {drop i xs}} ]]]></fr:tex><html:p>They can be implemented in OCaml as follows:</html:p><html:pre><![CDATA[# let rec take i = function
    | [] -> []
    | x::xs ->
        if i > 0 then x :: take (i - 1) xs
        else []
val take : int -> 'a list -> 'a list = <fun>
# let rec drop i = function
    | [] -> []
    | x::xs ->
        if i > 0 then drop (i-1) xs
        else x::xs
val drop : int -> 'a list -> 'a list = <fun>]]></html:pre><html:p>Applications of <html:code>take</html:code> and <html:code>drop</html:code> will appear in future lectures.  Typically,
they divide a collection of items into equal parts for recursive processing.</html:p><html:p>The <html:code>take</html:code> function is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>, but making it so would not improve
its efficiency.  The task requires copying up to <fr:tex
display="inline"><![CDATA[i]]></fr:tex> list elements, which must
take <fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> space and time.</html:p><html:p>Function <html:code>drop</html:code> simply skips over <fr:tex
display="inline"><![CDATA[i]]></fr:tex> list elements.  This requires
<fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> time but only constant space.  It is iterative and much faster than
<html:code>take</html:code>.  Both functions use <fr:tex
display="inline"><![CDATA[O(i)]]></fr:tex> time, but skipping elements is faster
than copying them:  <html:code>drop</html:code>’s constant factor is smaller.</html:p><html:p>Both functions take an integer and a list, returning a list of the same type.
So their type is <html:code>int -&gt; 'a list -&gt; 'a list</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-strings-chars/</fr:uri><fr:display-uri>focs-strings-chars</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-strings-chars/</fr:route><fr:title
text="Lists, Strings and Characters">Lists, Strings and Characters</fr:title></fr:frontmatter><fr:mainmatter><html:p>Strings are provided in most programming languages to allow text processing.
Strings are essential for communication with users. Even a purely numerical
program formats its results ultimately as strings.</html:p><html:pre><![CDATA[# 'a'   (* a character constant *)
- : char = 'a'
# "a"   (* a string constant of length 1 *)
- : string = "a"
# "abc" (* a string constant of length 3 *)
- : string = "abc"
# String.length "abc"
- : int = 3
# "abc" ^ "def"  (* concatenate two strings *)
- : string = "abcdef"]]></html:pre><html:p>In a few programming languages, strings simply are lists of characters. In
OCaml they are a separate type, unrelated to lists, reflecting the fact that
strings are an abstract concept in themselves.</html:p><html:p>Similarly, characters are not strings of size one, but are a primitive concept.
Character constants in OCaml have the form <html:code>'c'</html:code>, where <fr:tex
display="inline"><![CDATA[c]]></fr:tex> is any character.
For example, the comma character is <html:code>','</html:code>.</html:p><html:p>Special characters are coded in strings using <html:em>escape sequences</html:em> involving the
backslash character; among many others, a double quote is written <html:code><![CDATA["\\"]]></html:code> and
the newline character is written <html:code><![CDATA["\n"]]></html:code>. For example, the string
<html:code><![CDATA["I\nLIKE\nCHEESE\n"]]></html:code> represents three text lines.</html:p><html:p>In addition to the operators described above, the relations <html:code>&lt;</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code>, and
<html:code>&gt;=</html:code> work for strings and yield alphabetic order (more precisely, lexicographic
order with respect to ASCII character codes).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:uri><fr:display-uri>focs-matmul-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:route><fr:title
text="Matrix Multiplication in OCaml">Matrix Multiplication in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:p><html:em>Dot product</html:em> of two vectors—a <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link></html:em></html:p><html:pre><![CDATA[# let rec dotprod xs ys =
    match xs, ys with
    | [], [] -> 0.0
    | x::xs, y::ys ->  (x *. y) +. (dotprod xs ys)
Lines 2-4, characters 5-51:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
([], _::_)

val dotprod : float list -> float list -> float = <fun>]]></html:pre><html:p><html:em>Matrix product</html:em></html:p><html:pre><![CDATA[# let rec matprod arows brows =
    let cols = transp brows in
    map (fun row -> map (dotprod row) cols) arows
val matprod : float list list -> float list list -> float list list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local"><html:code>transp brows</html:code></fr:link> converts <fr:tex
display="inline"><![CDATA[B]]></fr:tex> into a list of columns, yielding a
list whose elements are the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Each row of <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is
obtained by multiplying a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><html:p>Because <html:code>dotprod</html:code> is curried, it can be applied to a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The
resulting function is applied to all the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  We have another
example of currying and partial application.</html:p><html:p>The outer <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> applies <html:code>dotprod</html:code> to each row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The inner
<html:code>map</html:code>, using <html:code>fun</html:code>-notation, applies <html:code>dotprod row</html:code> to each
column of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Compare with the version in <html:em>ML for the Working
  Programmer</html:em> (page 89) which does not use <html:code>map</html:code> and requires two
additional function declarations.</html:p><html:p>In the dot product function, the two vectors must have the same length.
Otherwise, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Match_failure</html:code> is raised.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge/</fr:uri><fr:display-uri>focs-merge</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge/</fr:route><fr:title
text="Merging Two Lists">Merging Two Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Merge joins two sorted lists.</html:p><html:pre><![CDATA[# let rec merge = function
    | [], ys -> ys
    | xs, [] -> xs
    | x::xs, y::ys ->
        if x <= y then
          x :: merge (xs, y::ys)
        else
          y :: merge (x::xs, ys)
val merge : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>Generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insert</fr:link> to two lists, and does at most <fr:tex
display="inline"><![CDATA[m+n-1]]></fr:tex> comparisons.</html:p><html:p><html:em>Merging</html:em> means combining two sorted lists to form a larger sorted list.
It does at most <fr:tex
display="inline"><![CDATA[m+n]]></fr:tex> comparisons, where <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are the lengths of the
input lists.  If <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are roughly equal then we have a fast way of
constructing sorted lists; if <fr:tex
display="inline"><![CDATA[n=1]]></fr:tex> then merging degenerates to insertion,
doing much work for little gain.</html:p><html:p>Merging is the basis of several sorting algorithms; we look at a
divide-and-conquer one.  Mergesort is seldom found in conventional programming
because it is hard to code for arrays; it works nicely with lists.  It divides
the input (if non-trivial) into two roughly equal parts, sorts them
recursively, then merges them.</html:p><html:p>Function <html:code>merge</html:code> is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>; the recursion is deep.  An iterative
version is of little benefit for the same reasons that apply to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">earlier lecture on Lists</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/</fr:uri><fr:display-uri>focs-def-polymorphism</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-polymorphism/</fr:route><fr:title
text="Polymorphism">Polymorphism</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A polymorphic function allows flexibility in the types of its arguments and
results: the list primitives <html:code>null</html:code>, <html:code>hd</html:code> and <html:code>tl</html:code> work whatever
the element type is. Symbols <html:code>'a</html:code> and <html:code>'b</html:code> are called <html:em>type
variables</html:em> and stand for any types, and code written using them is still checked
for type correctness at compile time.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">Getting at the Head and Tail</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:uri><fr:display-uri>focs-quicksort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:route><fr:title
text="Quicksort: The Code">Quicksort: The Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quick = function
    | [] -> []
    | [x] -> [x]
    | a::bs ->
        let rec part l r = function
          | [] -> (quick l) @ (a :: quick r)
          | x::xs ->
              if (x <= a) then
                part (x::l) r xs
              else
                part l (x::r) xs
        in
        part [] [] bs
val quick : 'a list -> 'a list = <fun>]]></html:pre><html:p>Our OCaml quicksort copies the items.  It is still pretty fast, and it is much
easier to understand.  It takes roughly 0.74 seconds to sort our list of random
numbers.</html:p><html:p>The function declaration consists of three clauses.  The first handles the
empty list; the second handles singleton lists (those of the form <html:code>[x]</html:code>); the
third handles lists of two or more elements.  Often, lists of length up to five
or so are treated as special cases to boost speed.</html:p><html:p>The locally declared function <html:code>part</html:code> partitions the input using <html:code>a</html:code> as the
pivot.  The arguments <html:code>l</html:code> and <html:code>r</html:code> accumulate items for the left (<fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>) and
right (<fr:tex
display="inline"><![CDATA[>a]]></fr:tex>) parts of the input, respectively.</html:p><html:p>It is not hard to prove that quicksort does <fr:tex
display="inline"><![CDATA[n\log  n]]></fr:tex> comparisons, <html:em>in the average case</html:em>
(see <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">page 94 of Aho</fr:link>).  With random data, the pivot
usually has an average value that divides the input in two approximately equal
parts.  We have the recurrence <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>, which is
<fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.  In our example, it is about 235 times faster than <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insertion
sort</fr:link>.</html:p><html:p>In the worst case, quicksort's running time is quadratic!  An example is when
its input is almost sorted or reverse sorted.  Nearly all of the items end up
in one partition; work is not divided evenly.  We have the recurrence
<fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>, which is <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Randomising the input
makes the worst case highly unlikely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/</fr:uri><fr:display-uri>focs-rev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-rev/</fr:route><fr:title
text="Reversing a List in O(n)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec rev_app xs ys =
    match xs, ys with
    | [], ys    -> ys
    | x::xs, ys -> rev_app xs (x::ys)
val rev_app : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {rev\_app }[a; b; c]\;[] \Rightarrow  &\; \text {rev\_app }[b; c]\; [a] \\
  \Rightarrow  &\; \text {rev\_app }[c]\; [b; a] \\
  \Rightarrow  &\; \text {rev\_app }[]\; [c; b; a] \\
  \Rightarrow  &\; [c; b; a]
\end {aligned}
]]></fr:tex><html:p>Calling <html:code>rev_app xs ys</html:code> reverses the elements of <html:code>xs</html:code> and
prepends them to <html:code>ys</html:code>.  Now we may declare</html:p><html:pre><![CDATA[# let rev xs = rev_app xs []
val rev : 'a list -> 'a list = <fun>
# rev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><html:p>It is easy to see that this reverse function performs just <fr:tex
display="inline"><![CDATA[n]]></fr:tex> conses, given
an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element list.  For both reverse functions, we could count the number of
conses precisely—not just up to a constant factor.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-o-notation/"
title="Comparing Algorithms: O Notation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-o-notation/"
display-uri="focs-o-notation"
type="local"><fr:tex
display="inline"><![CDATA[O]]></fr:tex> notation</fr:link> is still
useful to describe the overall running time: the time taken by a cons
varies from one system to another.</html:p><html:p>The accumulator <fr:tex
display="inline"><![CDATA[y]]></fr:tex> makes the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>.  But the gain in complexity
arises from the removal of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.  Replacing an expensive operation (append)
by a series of cheap operations (cons) is called <html:em>reduction in strength</html:em>
and is a common technique in computer science.  It originated when many
computers did not have a hardware multiply instruction; the series of products
<fr:tex
display="inline"><![CDATA[i\times  r]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, <fr:tex
display="inline"><![CDATA[\ldots , n]]></fr:tex> could more efficiently be computed by
repeated addition.  Reduction in strength can be done in various ways; we
shall see many instances of removing append.</html:p><html:p>Consing to an accumulator produces the result in reverse.  If
that forces the use of an extra list reversal then the iterative function
may be much slower than the recursive one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-nrev/</fr:uri><fr:display-uri>focs-nrev</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-nrev/</fr:route><fr:title
text="Reversing a List in O(n^2)">Reversing a List in <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex></fr:title></fr:frontmatter><fr:mainmatter><html:p>Let us consider one way to reverse a list.</html:p><html:pre><![CDATA[# let rec nrev = function
  | [] -> []
  | x::xs -> (nrev xs) @ [x]
val nrev : 'a list -> 'a list = <fun>
# nrev [1; 2; 3]
- : int list = [3; 2; 1]]]></html:pre><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {nrev }[a; b; c] \Rightarrow  &\; \text {nrev }[b; c]\;@\;[a] \\
  \Rightarrow  &\;  (\text {nrev }[c]\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  ((\text {nrev }[]\;@\;[c])\;@\;[b])\;@\;[a] \\
  \Rightarrow  &\;  (([]\;@\;[c])\;@\;[b])\;@\;[a] \ \ldots  \ [c; b; a]
\end {aligned}
]]></fr:tex><html:p>This reverse function is grossly inefficient due to poor usage of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>, which
copies its first argument.  If <html:code>nrev</html:code> is given a list of length <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>, then
append makes <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> conses to copy the reversed tail.  Constructing the list
<html:code>[x]</html:code> calls <html:code>cons</html:code> again, for a total of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> calls.  Reversing the tail
requires <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> more conses, and so forth.  The total number of conses is:</html:p><fr:tex
display="block"><![CDATA[ 0 + 1 + 2 + \cdots  + n = {n(n+1)/2} ]]></fr:tex><html:p>The time complexity is therefore <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Space complexity is only <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>
because the copies don’t all exist at the same time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-curry-shorthand/</fr:uri><fr:display-uri>focs-curry-shorthand</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-curry-shorthand/</fr:route><fr:title
text="Shorthand for Curried Functions">Shorthand for Curried Functions</fr:title></fr:frontmatter><fr:mainmatter><html:p>A function-returning function is just a function of two arguments.</html:p><html:p>This <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link> syntax is nicer than nested <html:code>fun</html:code> binders:</html:p><html:pre><![CDATA[# let prefix a b = a ^ b
val prefix : string -> string -> string = <fun>
# let dub = prefix "Sir "
val dub : string -> string = <fun>]]></html:pre><html:p>Curried functions allows <html:em>partial application</html:em> (to the first argument).</html:p><html:p>In OCaml, an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-argument curried function <html:code>f</html:code> can be declared using the syntax:</html:p><fr:tex
display="block"><![CDATA[\tt  let \; f \; x_1 \: \ldots  \: x_{n} \: = \: E]]></fr:tex><html:p>and applied using the syntax:</html:p><fr:tex
display="block"><![CDATA[\tt  \; E_1 \; \ldots  \; E_n]]></fr:tex><html:p>If <html:code>f</html:code> is not recursive, then it is equivalent to the function expressed via nesting as follows:</html:p><fr:tex
display="block"><![CDATA[\tt  fun \; x_1 \; \rightarrow  \cdots  \rightarrow  fun \; x_{n} \rightarrow  E ]]></fr:tex><html:p>We now have two ways of expressing functions of multiple arguments: either by
passing a pair of arguments or by currying.  Currying allows <html:em>partial application</html:em>
which is useful when fixing the first argument yields a function
that is interesting in its own right.  An example from mathematics is the
function <fr:tex
display="inline"><![CDATA[x^y]]></fr:tex>, where fixing <fr:tex
display="inline"><![CDATA[y=2]]></fr:tex> yields a function in <fr:tex
display="inline"><![CDATA[x]]></fr:tex> alone, namely
squaring. Similarly, <fr:tex
display="inline"><![CDATA[y=3]]></fr:tex> yields cubing, while <fr:tex
display="inline"><![CDATA[y=1]]></fr:tex> yields the identity
function.</html:p><html:p>Though the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local"><html:code>hd</html:code></fr:link> (which returns the head of a list) is not
curried, it may be used with the curried application syntax in some
expressions:</html:p><html:pre><![CDATA[# List.hd [dub; promote] "Hamilton"
- : string = "Sir Hamilton"]]></html:pre><html:p>Here <html:code>List.hd</html:code> is applied to a list of functions, and the resulting function
<html:code>dub</html:code> is then applied to the string <html:code>"Hamilton"</html:code>.  The idea of
executing code stored in data structures reaches its full development in
<html:em>object-oriented</html:em> programming, like in Java.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/</fr:uri><fr:display-uri>focs-list-primitives</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-list-primitives/</fr:route><fr:title
text="The List Primitives">The List Primitives</fr:title></fr:frontmatter><fr:mainmatter><html:p>There are two kinds of lists:</html:p><html:ul><html:li><html:code>[]</html:code> represents the empty list</html:li>
  <html:li><html:code>x :: l</html:code> is the list with head <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and tail <fr:tex
display="inline"><![CDATA[l]]></fr:tex></html:li></html:ul><html:pre><![CDATA[# let nil = []
val nil : 'a list = []
# 1 :: nil
- : int list = [1]
# 1 :: 2 :: nil
- : int list = [1; 2]]]></html:pre><html:p>The operator <html:code>::</html:code> (also called <html:code>List.cons</html:code> for “construct”), puts a new element on
to the head of an existing list.  While we should not be too preoccupied with
implementation details, it is essential to know that <html:code>::</html:code> is an <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
operation.  It uses constant time and space, regardless of the length of the
resulting list.  Lists are represented internally with a linked structure;
adding a new element to a list merely hooks the new element to the front of
the existing structure.  Moreover, that structure continues to denote the same
list as it did before; to see the new list, one must look at the new <html:code>::</html:code> node
(or “cons cell”) just created.  We will explain the <html:code>'a</html:code> notation in the next
section.</html:p><html:p>Here we see the element <html:code>1</html:code> being consed to the front of the list <html:code>[3; 5; 9]</html:code>:</html:p><fr:tex
display="block"><![CDATA[\begin{array}{ccccccccccc}
:: & \to & \cdots & :: & \to &  :: & \to &  :: & \to & [] \\
\downarrow &  &        & \downarrow &  & \downarrow &  & \downarrow  \\
1     &  &        & 3     &  & 5     &  & 9
\end{array}]]></fr:tex><html:p>Given a list, taking its first element (its “head”) or its list of
remaining elements (its “tail”) also takes constant time.  Each
operation just follows a link.  In the diagram above, the first down arrow
leads to the head and the leftmost right arrow leads to the tail.  Once we
have the tail, its head is the second element of the original list, etc.</html:p><html:p>The tail is <html:em>not</html:em> the last element; it is the <html:em>list</html:em> of all elements
other than the head!</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:uri><fr:display-uri>focs-merge-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:route><fr:title
text="Top-down Merge sort">Top-down Merge sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec tmergesort = function
    | [] -> []
    | [x] -> [x]
    | xs ->
        let k = List.length xs / 2 in
        let l = tmergesort (take k xs) in
        let r = tmergesort (drop k xs) in
        merge (l, r)
val tmergesort : 'a list -> 'a list = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons in worst case</html:p><html:p>Mergesort’s <html:em>divide</html:em> stage divides the input not by choosing a pivot (as
in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>) but by simply counting out half of the elements.  The
<html:em>conquer</html:em> stage again involves recursive calls, and the <html:em>combine</html:em>
stage involves merging.  Function <html:code>tmergesort</html:code> takes roughly 1.4
seconds to sort the list <html:code>rs</html:code>.</html:p><html:p>In the worst case, mergesort does <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons, with the same
recurrence equation as in quicksort’s average case.  Because <fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>take</html:code></fr:link> and
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>drop</html:code></fr:link> divide the input in two equal parts (they differ at most by
one element), we always have <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>.</html:p><html:p>Quicksort is nearly 3 times as fast in the example.  But it risks a
quadratic worst case!  Merge sort is safe but slow.  So which algorithm is
best?</html:p><html:p>We have seen a <html:em>top-down</html:em> mergesort.  <html:em>Bottom-up</html:em> algorithms also
exist.  They start with a list of one-element lists and repeatedly merge
adjacent lists until only one is left.  A refinement, which exploits any
initial order among the input, is to start with a list of increasing or
decreasing runs of input items.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/</fr:uri><fr:display-uri>focs-map</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-map/</fr:route><fr:title
text="map: the “Apply to All” Function">map: the “Apply to All” Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec map f = function
    | [] -> []
    | x::xs -> (f x) :: map f xs
val map : ('a -> 'b) -> 'a list -> 'b list = <fun>
# map (fun s -> s ^ "ppy") ["Hi"; "Ho"]
- : string list = ["Hippy"; "Hoppy"]
# map (map double) [[1]; [2; 3]]
- : int list list = [[2]; [4; 6]]]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>map</html:code> applies a function to every element of a list,
returning a list of the function’s results.  “Apply to all” is a fundamental
operation and we shall see several applications of it below.  We
again see the advantages of <html:code>fun</html:code>-notation, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">currying</fr:link> and
<html:code>map</html:code>.  If we did not have them, the first use of <html:code>map</html:code> in the above code block
would require a preliminary function declaration:</html:p><html:pre><![CDATA[# let rec sillylist = function
    | [] -> []
    | s::ss -> (s ^ "ppy") :: sillylist ss
val sillylist : string list -> string list = <fun>]]></html:pre><html:p>An expression containing several applications of functionals—such as our
second example—can abbreviate a long series of declarations.  Sometimes this
coding style is cryptic, but it can be clear as crystal.  Treating functions
as values lets us capture common program structures once and for all.</html:p><html:p>In the second example, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-anonymous-functions/"
title="Functions Without Names"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-anonymous-functions/"
display-uri="focs-anonymous-functions"
type="local"><html:code>double</html:code></fr:link> is the obvious integer doubling function we
defined earlier.  Note that <html:code>map</html:code> is a built-in OCaml function in the
form of <html:code>List.map</html:code>.  OCaml’s standard library includes, among much else, many
list functions.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:uri><fr:display-uri>focs-ex-4-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:route><fr:title
text="Exercises › A non-exhaustive zip"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › A non-exhaustive zip</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>How does this version of <html:code>zip</html:code> differ from <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local">the one above</fr:link>?</html:p><html:pre><![CDATA[let rec zip xs ys =
  match xs, ys with
  | (x::xs, y::ys) -> (x, y) :: zip xs ys
  | ([], [])   -> []]]></html:pre><html:pre><![CDATA[Lines 2-4, characters 5-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(x::xs, [])]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:uri><fr:display-uri>focs-ex-9-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:route><fr:title
text="Exercises › All lists of zeroes and ones"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › All lists of zeroes and ones</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the lazy list whose elements are all ordinary lists of zeroes and ones, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 1]; [1; 0]; [1; 1]; [0; 0; 0]; </html:code>….  (Taken from the exam question
2003 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:uri><fr:display-uri>focs-ex-4-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-4/</fr:route><fr:title
text="Exercises › Assumptions in making change"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Assumptions in making change</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What assumptions do the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">‘making change’</fr:link> functions make about the variables <html:code>till</html:code> and <html:code>amt</html:code>?
Describe what could happen if these assumptions were violated.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:uri><fr:display-uri>focs-ex-9-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:route><fr:title
text="Exercises › Concatenating infinite sequences"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Concatenating infinite sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the list function <html:code>concat</html:code>, which concatenates a list of lists to form a single list. Can
it be generalised to concatenate a sequence of sequences? What can go wrong?</html:p><html:pre><![CDATA[let rec concat = function
| [] -> []
| l::ls -> l @ concat ls]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:uri><fr:display-uri>focs-ex-9-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:route><fr:title
text="Exercises › Enumerating palindromes"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Enumerating palindromes</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>(Continuing the previous exercise.)
A <html:em>palindrome</html:em> is a list that equals its own reverse. Code the lazy list whose elements are all
palindromes of 0s and 1s, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 0; 0]; [0; 1; 0]; [1; 1]; [1; 0; 1]; [1; 1; 1]; [0; 0; 0; 0]; </html:code>, …. You
may take the reversal function <html:code>List.rev</html:code> as given.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:uri><fr:display-uri>focs-ex-3-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-3/</fr:route><fr:title
text="Exercises › Even-numbered elements"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Even-numbered elements</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the list consisting of the even-numbered elements of the list given as its
argument. For example, given <html:code>[a; b; c; d]</html:code> it should return <html:code>[b; d]</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:uri><fr:display-uri>focs-ex-5-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:route><fr:title
text="Exercises › Implementing bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement bubble sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:uri><fr:display-uri>focs-ex-5-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:route><fr:title
text="Exercises › Implementing selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement selection sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:uri><fr:display-uri>focs-ex-3-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-2/</fr:route><fr:title
text="Exercises › Last element of a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Last element of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to return the last element of a non-empty list. How efficiently can this be done?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:uri><fr:display-uri>focs-ex-11-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:route><fr:title
text="Exercises › Lists of references"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Lists of references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Comment, with examples, on the differences between an <html:code>int ref list</html:code> and an <html:code>int list ref</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:uri><fr:display-uri>focs-ex-9-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:route><fr:title
text="Exercises › Making change lazily"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Making change lazily</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">make change</fr:link> using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, delivering the sequence of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all possible ways of
making change</fr:link>. Using sequences allows us to compute solutions one at a time when there exists an
astronomical number. Represent lists of coins using ordinary lists. (<html:em>Hint</html:em>: to  benefit from
laziness you may need to pass around the sequence of alternative solutions as a function of type
<html:code>unit -&gt; (int list) seq</html:code>.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:uri><fr:display-uri>focs-ex-8-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:route><fr:title
text="Exercises › Making change with map"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Making change with map</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Recall the making change function of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">More on Lists</fr:link>:</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Function <html:code>allc</html:code> applies the function ‘cons a <html:code>c</html:code>’ to every element of a list. Eliminate it by
declaring a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried</fr:link> cons function and applying <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:uri><fr:display-uri>focs-ex-8-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:route><fr:title
text="Exercises › Mapping over lists of lists"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Mapping over lists of lists</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Without using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> write a function <html:code>map2</html:code> such that <html:code>map2 f</html:code> is equivalent to <html:code>map (map f)</html:code>. The
obvious solution requires declaring two recursive functions. Try to get away with only one by
exploiting nested <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:uri><fr:display-uri>focs-ex-4-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-2/</fr:route><fr:title
text="Exercises › Partitioning integers by sign"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Partitioning integers by sign</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function that takes a list of integers and returns two lists, the first consisting of all
non-negative numbers found in the input and the second consisting of all the negative numbers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:uri><fr:display-uri>focs-ex-4-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:route><fr:title
text="Exercises › Reasoning from polymorphic types"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Reasoning from polymorphic types</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>We know nothing about the functions <html:code>f</html:code> and <html:code>g</html:code> other than their polymorphic types:
<html:code>val f : 'a * 'b -&gt; 'b * 'a</html:code> and <html:code>val g : 'a -&gt; 'a list</html:code>.
Suppose that <html:code>f (1, true)</html:code> and <html:code>g 0</html:code> are evaluated and return their results. State, with reasons,
what you think the resulting values will be.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:uri><fr:display-uri>focs-ex-4-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:route><fr:title
text="Exercises › Set union without repetitions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Set union without repetitions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Sets can be represented in OCaml using lists containing no duplicated items
(i.e. where no item is equal to another using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link> comparison).</html:p><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link> function defined above, code a function to implement set
union. It should avoid introducing repetitions, for example the union of the
lists <html:code>[4; 7; 1]</html:code> and <html:code>[6; 4; 7]</html:code> should be <html:code>[1; 6; 4; 7]</html:code> (though the order
does not matter).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:uri><fr:display-uri>focs-ex-3-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-1/</fr:route><fr:title
text="Exercises › Summing a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Summing a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function</fr:link> to compute the sum of a list’s elements. Then code an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> version
and comment on the improvement in efficiency.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:uri><fr:display-uri>focs-ex-3-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-5/</fr:route><fr:title
text="Exercises › Tails of a list"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Tails of a list</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function <html:code>tails</html:code> to return the list of the tails of its argument. For example, given
<html:code>[1; 2; 3]</html:code> it should return <html:code>[[1; 2; 3]; [2; 3]; [3]; []]</html:code>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-sorting/</fr:uri><fr:display-uri>focs-topic-sorting</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-sorting/</fr:route><fr:title
text="Sorting">Sorting</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:uri><fr:display-uri>focs-quicksort-append-free</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-append-free/</fr:route><fr:title
text="Append-Free Quicksort">Append-Free Quicksort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quik = function
    | ([], sorted) -> sorted
    | ([x], sorted) -> x::sorted
    | a::bs, sorted ->
       let rec part = function
         | l, r, [] -> quik (l, a :: quik (r, sorted))
         | l, r, x::xs ->
             if x <= a then
               part (x::l, r, xs)
             else
               part (l, x::r, xs)
       in
       part ([], [], bs)
val quik : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>The list <html:code>sorted</html:code> accumulates the result in the <html:em>combine</html:em> stage of
the quicksort algorithm.  We have again used the standard technique for
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-rev/"
title="Reversing a List in O(n)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-rev/"
display-uri="focs-rev"
type="local">eliminating append</fr:link>.  Calling <html:code>quik(xs, sorted)</html:code> reverses the elements of
<html:code>xs</html:code> and prepends them to the list <html:code>sorted</html:code>.</html:p><html:p>Looking closely at <html:code>part</html:code>, observe that <html:code>quik(r, sorted)</html:code> is
performed first.  Then <html:code>a</html:code> is consed to this sorted list.  Finally,
<html:code>quik</html:code> is called again to sort the elements of <html:code>l</html:code>.</html:p><html:p>The speedup is significant.  An imperative quicksort coded in Pascal (taken
from <fr:link
href="https://algs4.cs.princeton.edu/20sorting/"
type="external">Sedgewick</fr:link>) is just slightly faster than function
<html:code>quik</html:code>.  The near-agreement is surprising because the computational overheads
of lists exceed those of arrays.  In realistic applications, comparisons are
the dominant cost and the overheads matter even less.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting-bounds/</fr:uri><fr:display-uri>focs-sorting-bounds</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting-bounds/</fr:route><fr:title
text="How Fast Can We Sort?">How Fast Can We Sort?</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>typically count <html:em>comparisons</html:em> <fr:tex
display="inline"><![CDATA[C(n)]]></fr:tex></html:li>
  <html:li>there are <fr:tex
display="inline"><![CDATA[n!]]></fr:tex> permutations of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements</html:li>
  <html:li>each comparison eliminates <html:em>half</html:em> of the permutations <fr:tex
display="inline"><![CDATA[2^{C(n)}\geq  n!]]></fr:tex></html:li>
  <html:li>therefore <fr:tex
display="inline"><![CDATA[C(n)\geq  \log (n!)\approx  n\log  n-1.44n]]></fr:tex></html:li></html:ul><html:p>The usual measure of efficiency for sorting algorithms is the number of
comparison operations required.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">Mergesort</fr:link> requires only <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>
comparisons to sort an input of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> items.  It is straightforward to prove
that this complexity is the best possible.  There
are <fr:tex
display="inline"><![CDATA[n!]]></fr:tex> permutations of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements and each comparison distinguishes two
permutations.  The lower bound on the number of comparisons, <fr:tex
display="inline"><![CDATA[C(n)]]></fr:tex>, is
obtained by solving <fr:tex
display="inline"><![CDATA[2^{C(n)}\geq  n!]]></fr:tex>; therefore
<fr:tex
display="inline"><![CDATA[C(n)\geq  \log (n!)\approx  n\log  n-1.44n]]></fr:tex>.</html:p><html:p>In order to compare the sorting algorithms, we use the <fr:link
href="http://www.firstpr.com.au/dsp/rand31/p1192-park.pdf"
type="external">following source</fr:link> of
pseudo-random numbers. Never mind how this works: generating
statistically good random numbers is hard.  Much effort has gone into those few
lines of code.</html:p><html:pre><![CDATA[# let nextrandom seed =
    let a = 16807.0 in
    let m = 2147483647.0 in
    let t = a *. seed in
    t -. m *. (floor (t /. m))
val nextrandom : float -> float = <fun>
# let rec randlist (seed, seeds) = function
    | 0 -> (seed, seeds)
    | n -> randlist (nextrandom seed, seed::seeds) (n-1)
val randlist : float * float list -> int -> float * float list = <fun>]]></html:pre><html:p>We can now bind the identifier <html:code>rs</html:code> to a list of 10,000 random numbers.</html:p><html:pre><![CDATA[# let seed, rs = randlist (1.0, []) 10000
val seed : float = 1043618065.
val rs : float list =
  [1484786315.; 925166085.; 1614852353.; 721631166.; 173942219.; 1229443779.;
   789328014.; 570809709.; 1760109362.; 270600523.; 2108528931.; 16480421.;
   519782231.; 162430624.; 372212905.; 1954184989.; 898872741.; 1651521688.;
   1114791388.; 1325968501.; 1469981427.; 465437343.; 1732504088.;
   280054095.; 1924919450.; 1244369648.; 1524535715.; 706293012.;
   1372325856.; 1302473561.; 941382430.; 2137445578.; 1937168414.;
   1852570660.; 495231255.; 1092873378.; 140232191.; 328129841.; 632752255.;
   227857208.; 1616471915.; 719842438.; 1402481130.; 745001020.; 791471334.;
   2131048000.; 312659966.; 1389551813.; 443838892.; 854190041.; 741774068.;
   267473377.; 1372555293.; 1539748349.; 697860888.; 1261546017.; 734770781.;
   1512111397.; 813238415.; 1034499961.; 602256496.; 462191385.; 250718457.;
   246489360.; 295426232.; 468306241.; 877829533.; 1130589227.; 1914364883.;
   1479854970.; 878528585.; 1268712064.; 115837978.; 1803525169.; 689954646.;
   1174020926.; 651968560.; 391152461.; 1776325865.; 2015344107.; 246977673.;
   1381242649.; 1115030853.; 190703911.; 316761032.; 464218769.; 1537522160.;
   1958981931.; 390463588.; 224009597.; 235243732.; 620352731.; 1374109567.;
   832140633.; 675075162.; 1296171190.; 2009054653.; 1534419747.; 145880482.;
   1649432515.; 403989126.; 1112417244.; 1290575192.; 896661113.; 218545469.;
   1002393512.; 2131316096.; 551979127.; 932010335.; 665881436.; 1975412808.;
   639877791.; 1781707137.; 894518191.; 568004958.; 1331430214.; 629489848.;
   183264178.; 162027282.; 464592882.; 93302056.; 1178713033.; 1401486247.;
   1846150129.; 1646978216.; 1104441491.; 111995009.; 66193165.; 2038880392.;
   79340676.; 871801051.; 967550305.; 2067810758.; 1600354198.; 1746626663.;
   1516388116.; 1308870791.; 173082747.; 189881227.; 478010722.; 739707315.;
   255334803.; 164203714.; 1893097038.; 1587694259.; 292950569.; 918323194.;
   41453146.; 1217297445.; 256768724.; 586494122.; 586258194.; 660494391.;
   507554325.; 699716071.; 672895139.; 76065072.; 1594869218.; 1439459639.;
   641123634.; 1650611940.; 177447368.; 301427463.; 525804524.; 553672425.;
   926899509.; 794676486.; 690277940.; 2115070333.; 1062048650.; 1653192448.;
   1808855340.; 126475289.; 1028198214.; 1739565096.; 1515748830.;
   427491435.; 319330584.; 666483848.; 854842154.; 1853528448.; 1975611245.;
   1905343266.; 1229802342.; 1416055428.; 2091603253.; 1068308139.;
   198239748.; 982076370.; 1094563396.; 44402415.; 889814989.; 290736902.;
   417580014.; 1935788352.; 595665917.; 367638848.; 894945148.; 1868608068.;
   317883051.; 941451621.; 1595942893.; 789094274.; 1150772108.; 422742112.;
   1444245279.; 1273601104.; 256005435.; 1742330161.; 1514599036.;
   956344512.; 2113041793.; 293237373.; 1386995194.; 1509339194.; 891946522.;
   1020832915.; 592544922.; 1746311153.; 1471539715.; 143832370.;
   2041568248.; 1039556199.; 1608726047.; 1205124472.; 2123533995.;
   1560620058.; 1837598795.; 1028172251.; 98318742.; 1405510706.;
   1047695837.; 59221314.; 1822176683.; 1096018886.; 1528104537.;
   1270922857.; 812074106.; 291115596.; 795788616.; 638657646.; 2034314619.;
   1527649272.; 156357479.; 1010056202.; 1139413443.; 1110927723.;
   1216083346.; 846825145.; 2100385733.; 315213605.; 1629637749.;
   1139833627.; 895118866.; 296359237.; 1361440746.; 1188627020.;
   1964199872.; 166733080.; 54185744.; 575493576.; 1810324496.; 1765549585.;
   53514233.; 747348448.; 61758907.; 1710119765.; 188311628.; 8827553.;
   67975851.; 1808633248.; 1290488843.; 1264775607.; 1711469075.;
   1537468597.; 706677101.; 518290019.; 190285086.; 157683412.; 985907152.;
   1571668636.; 632570698.; 791081325.; 1773794197.; 1787141077.;
   1727982894.; 794213057.; 633163306.; 682601940.; 1573439414.; 1041956036.;
   1169697582.; 758914445.; 2096291761.; 1502226099.; 1665995955.;
   948048264.; 1596326605.; 1816773893.; ...]]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:uri><fr:display-uri>focs-insertion-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-insertion-sort/</fr:route><fr:title
text="Insertion Sort">Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:p>An insert operation does <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> comparisons on average.</html:p><html:pre><![CDATA[# let rec ins x = function
    | [] -> [x]
    | y::ys -> if x <= y then x :: y :: ys
               else y :: ins x ys
val ins : 'a -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Insertion sort</html:em> takes <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons on average:</html:p><html:pre><![CDATA[let rec insort = function
    | [] -> []
    | x::xs -> ins x (insort xs)]]></html:pre><html:p>Items from the input are copied one at a time to the output.  Each new item is
inserted into the right place so that the output is always in order.</html:p><html:p>We could easily write <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link> versions of these functions, but to no purpose.
Insertion sort is slow because it does <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> comparisons (and a lot of list
copying), not because it is recursive.  Its quadratic runtime makes it nearly
useless: it takes 174 seconds for our example while the next-worst figure is
1.4 seconds.</html:p><html:p>Insertion sort is worth considering because it is easy to code and illustrates
the concepts.  Two efficient sorting algorithms, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link> and heapsort, can be
regarded as refinements of insertion sort.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge/</fr:uri><fr:display-uri>focs-merge</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge/</fr:route><fr:title
text="Merging Two Lists">Merging Two Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Merge joins two sorted lists.</html:p><html:pre><![CDATA[# let rec merge = function
    | [], ys -> ys
    | xs, [] -> xs
    | x::xs, y::ys ->
        if x <= y then
          x :: merge (xs, y::ys)
        else
          y :: merge (x::xs, ys)
val merge : 'a list * 'a list -> 'a list = <fun>]]></html:pre><html:p>Generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insert</fr:link> to two lists, and does at most <fr:tex
display="inline"><![CDATA[m+n-1]]></fr:tex> comparisons.</html:p><html:p><html:em>Merging</html:em> means combining two sorted lists to form a larger sorted list.
It does at most <fr:tex
display="inline"><![CDATA[m+n]]></fr:tex> comparisons, where <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are the lengths of the
input lists.  If <fr:tex
display="inline"><![CDATA[m]]></fr:tex> and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> are roughly equal then we have a fast way of
constructing sorted lists; if <fr:tex
display="inline"><![CDATA[n=1]]></fr:tex> then merging degenerates to insertion,
doing much work for little gain.</html:p><html:p>Merging is the basis of several sorting algorithms; we look at a
divide-and-conquer one.  Mergesort is seldom found in conventional programming
because it is hard to code for arrays; it works nicely with lists.  It divides
the input (if non-trivial) into two roughly equal parts, sorts them
recursively, then merges them.</html:p><html:p>Function <html:code>merge</html:code> is not <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">iterative</fr:link>; the recursion is deep.  An iterative
version is of little benefit for the same reasons that apply to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">earlier lecture on Lists</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/</fr:uri><fr:display-uri>focs-partial-application</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-partial-application/</fr:route><fr:title
text="Partial Application: A Curried Insertion Sort">Partial Application: A Curried Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let insort lessequal =
    let rec ins x = function
      | [] -> [x]
      | y::ys -> if lessequal x y then x :: y :: ys
                 else y :: ins x ys
    in
    let rec sort = function
      | [] -> []
      | x::xs -> ins x (sort xs)
    in
    sort
val insort : ('a -> 'a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">sorting functions</fr:link> we discussed in earlier lectures are coded to sort floating-point
numbers.  They can be generalised to an arbitrary ordered type by passing the
ordering predicate <html:code>lessequal</html:code> as an argument.</html:p><html:p>Functions <html:code>ins</html:code> and <html:code>sort</html:code> are declared locally, referring to <html:code>lessequal</html:code>.
Though it may not be obvious, <html:code>insort</html:code> is a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link>.  Given its first
argument, a predicate for comparing some particular type of items, it returns
the function <html:code>sort</html:code> for sorting lists of that type of items.</html:p><html:p>Some examples of its use:</html:p><html:pre><![CDATA[# insort (<=) [5; 3; 9; 8]
- : int list = [3; 5; 8; 9]
# insort (<=) ["bitten"; "on"; "a"; "bee"]
- : string list = ["a"; "bee"; "bitten"; "on"]
# insort (>=) [5; 3; 9; 8]
- : int list = [9; 8; 5; 3]]]></html:pre><html:p>An obscure point: the syntax <html:code>(&lt;=)</html:code> denotes the comparison operator as a
function, which is then given to <html:code>insort</html:code>.  Passing the relation <fr:tex
display="inline"><![CDATA[\geq ]]></fr:tex> for
<html:code>lessequal</html:code> gives a decreasing sort.  This is no coding trick; it is justified
in mathematics, since if <fr:tex
display="inline"><![CDATA[\leq ]]></fr:tex> is a partial ordering then so is <fr:tex
display="inline"><![CDATA[\geq ]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:uri><fr:display-uri>focs-quicksort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort/</fr:route><fr:title
text="Quicksort: The Code">Quicksort: The Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec quick = function
    | [] -> []
    | [x] -> [x]
    | a::bs ->
        let rec part l r = function
          | [] -> (quick l) @ (a :: quick r)
          | x::xs ->
              if (x <= a) then
                part (x::l) r xs
              else
                part l (x::r) xs
        in
        part [] [] bs
val quick : 'a list -> 'a list = <fun>]]></html:pre><html:p>Our OCaml quicksort copies the items.  It is still pretty fast, and it is much
easier to understand.  It takes roughly 0.74 seconds to sort our list of random
numbers.</html:p><html:p>The function declaration consists of three clauses.  The first handles the
empty list; the second handles singleton lists (those of the form <html:code>[x]</html:code>); the
third handles lists of two or more elements.  Often, lists of length up to five
or so are treated as special cases to boost speed.</html:p><html:p>The locally declared function <html:code>part</html:code> partitions the input using <html:code>a</html:code> as the
pivot.  The arguments <html:code>l</html:code> and <html:code>r</html:code> accumulate items for the left (<fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>) and
right (<fr:tex
display="inline"><![CDATA[>a]]></fr:tex>) parts of the input, respectively.</html:p><html:p>It is not hard to prove that quicksort does <fr:tex
display="inline"><![CDATA[n\log  n]]></fr:tex> comparisons, <html:em>in the average case</html:em>
(see <fr:link
href="https://archive.org/details/designanalysisof00ahoarich"
type="external">page 94 of Aho</fr:link>).  With random data, the pivot
usually has an average value that divides the input in two approximately equal
parts.  We have the recurrence <fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>, which is
<fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex>.  In our example, it is about 235 times faster than <fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">insertion
sort</fr:link>.</html:p><html:p>In the worst case, quicksort's running time is quadratic!  An example is when
its input is almost sorted or reverse sorted.  Nearly all of the items end up
in one partition; work is not divided evenly.  We have the recurrence
<fr:tex
display="inline"><![CDATA[T(1) = 1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[T(n+1) = T(n)+n]]></fr:tex>, which is <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex>.  Randomising the input
makes the worst case highly unlikely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/</fr:uri><fr:display-uri>focs-quicksort-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-quicksort-idea/</fr:route><fr:title
text="Quicksort: The Idea">Quicksort: The Idea</fr:title></fr:frontmatter><fr:mainmatter><html:p>The Quicksort algorithm has the following flow:</html:p><html:ul><html:li>Choose a <html:em>pivot</html:em> element, <fr:tex
display="inline"><![CDATA[a]]></fr:tex></html:li>
  <html:li>Divide to partition the input into two sublists:
    <html:ul><html:li>those <html:em>at most</html:em> <fr:tex
display="inline"><![CDATA[a]]></fr:tex> in value</html:li>
      <html:li>those <html:em>exceeding</html:em> <fr:tex
display="inline"><![CDATA[a]]></fr:tex></html:li></html:ul></html:li>
  <html:li>Conquer using recursive calls to sort the sublists</html:li>
  <html:li>Combine the sorted lists by appending one to the other</html:li></html:ul><html:p>Quicksort was invented by Sir Anthony Hoare (1934–2026), who in later life worked at Microsoft
Research, Cambridge.  Quicksort works by <html:em>divide and conquer,</html:em> a basic algorithm design
principle.  Quicksort chooses from the input some value <fr:tex
display="inline"><![CDATA[a]]></fr:tex>, called the
<html:em>pivot</html:em>.  It partitions the remaining items into two parts: those <fr:tex
display="inline"><![CDATA[\leq  a]]></fr:tex>, and
those <fr:tex
display="inline"><![CDATA[>a]]></fr:tex>.  It sorts each part recursively, then puts the smaller part before
the greater.</html:p><html:p>The cleverest feature of Hoare's algorithm was that the partition could be done
<html:em>in place</html:em> by exchanging array elements.  Quicksort was invented before
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link> was well known, and people found it extremely hard to understand.  As
usual, we shall consider a list version based on functional programming.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting-summary/</fr:uri><fr:display-uri>focs-sorting-summary</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-sorting-summary/</fr:route><fr:title
text="Summary of Sorting Algorithms">Summary of Sorting Algorithms</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Optimal is <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
title="Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-insertion-sort/"
display-uri="focs-insertion-sort"
type="local">Insertion sort</fr:link>: simple to code; too slow (quadratic) [174 secs]</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort/"
title="Quicksort: The Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort/"
display-uri="focs-quicksort"
type="local">Quicksort</fr:link>: fast on average; quadratic in worst case [0.53 secs]</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">Mergesort</fr:link>: optimal in theory; often slower than quicksort [1.4 secs]</html:li>
  <html:li><html:em>Match the algorithm to the application</html:em></html:li></html:ul><html:p>Quicksort’s worst case cannot be ignored.  For large <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, a complexity of
<fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> is catastrophic.  Mergesort has an <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> worst case running
time, which is optimal, but it is typically slower than quicksort for random
data.</html:p><html:p>Non-comparison sorting deserves mentioning.  We can sort a large number of
small integers using their radix representation in <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time.  This result
does not contradict the comparison-counting argument because comparisons are
not used at all.  Linear time is achievable only if the greatest integer is
fixed in advance; as <fr:tex
display="inline"><![CDATA[n]]></fr:tex> goes to infinity, increasingly many of the items
are the same.  It is a simple special case.</html:p><html:p>Many other sorting algorithms exist. A few are outlined in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">the exercises</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:uri><fr:display-uri>focs-merge-sort</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-merge-sort/</fr:route><fr:title
text="Top-down Merge sort">Top-down Merge sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec tmergesort = function
    | [] -> []
    | [x] -> [x]
    | xs ->
        let k = List.length xs / 2 in
        let l = tmergesort (take k xs) in
        let r = tmergesort (drop k xs) in
        merge (l, r)
val tmergesort : 'a list -> 'a list = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons in worst case</html:p><html:p>Mergesort’s <html:em>divide</html:em> stage divides the input not by choosing a pivot (as
in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>) but by simply counting out half of the elements.  The
<html:em>conquer</html:em> stage again involves recursive calls, and the <html:em>combine</html:em>
stage involves merging.  Function <html:code>tmergesort</html:code> takes roughly 1.4
seconds to sort the list <html:code>rs</html:code>.</html:p><html:p>In the worst case, mergesort does <fr:tex
display="inline"><![CDATA[O(n\log  n)]]></fr:tex> comparisons, with the same
recurrence equation as in quicksort’s average case.  Because <fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>take</html:code></fr:link> and
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-take-drop/"
title="List Utilities: take and drop"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-take-drop/"
display-uri="focs-take-drop"
type="local"><html:code>drop</html:code></fr:link> divide the input in two equal parts (they differ at most by
one element), we always have <fr:tex
display="inline"><![CDATA[T(n) = 2T(n/2)+n]]></fr:tex>.</html:p><html:p>Quicksort is nearly 3 times as fast in the example.  But it risks a
quadratic worst case!  Merge sort is safe but slow.  So which algorithm is
best?</html:p><html:p>We have seen a <html:em>top-down</html:em> mergesort.  <html:em>Bottom-up</html:em> algorithms also
exist.  They start with a list of one-element lists and repeatedly merge
adjacent lists until only one is left.  A refinement, which exploits any
initial order among the input, is to start with a list of increasing or
decreasing runs of input items.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:uri><fr:display-uri>focs-ex-5-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-3/</fr:route><fr:title
text="Exercises › Complexity of bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Complexity of bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (bubble sort) consists of looking at adjacent pairs of elements,
exchanging them if they are out of order and repeating this process until no more exchanges are
possible. State, with justification, the time complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:uri><fr:display-uri>focs-ex-5-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-1/</fr:route><fr:title
text="Exercises › Complexity of selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Complexity of selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another sorting algorithm (selection sort) consists of looking at the elements to be sorted,
identifying and removing a minimal element, which is placed at the head of the result. The tail is
obtained by recursively sorting the remaining elements. State, with justification, the time
complexity of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:uri><fr:display-uri>focs-ex-5-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-4/</fr:route><fr:title
text="Exercises › Implementing bubble sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing bubble sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement bubble sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:uri><fr:display-uri>focs-ex-5-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-5-2/</fr:route><fr:title
text="Exercises › Implementing selection sort"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-5/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-5/"
display-uri="focs-ex-5"
type="local">Exercises</fr:link> › Implementing selection sort</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Implement selection sort (see previous exercise) using OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:uri><fr:display-uri>focs-ex-8-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:route><fr:title
text="Exercises › Lexicographic orderings"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Lexicographic orderings</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>There are many ways of combining orderings. The <html:code>lexicographic ordering</html:code> uses two keys for
comparisons. It is specified by</html:p><fr:tex
display="block"><![CDATA[(x',y')<(x,y)\iff  x'<x \vee  (x'=x \wedge  y'<y).]]></fr:tex><html:p>Write an OCaml function to lexicographically combine two orderings, supplied as functions. Explain
how it allows function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-partial-application/"
title="Partial Application: A Curried Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/"
display-uri="focs-partial-application"
type="local"><html:code>insort</html:code></fr:link> to sort a list of pairs.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-datatypes/</fr:uri><fr:display-uri>focs-topic-datatypes</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-datatypes/</fr:route><fr:title
text="Datatypes">Datatypes</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-constructors-args/</fr:uri><fr:display-uri>focs-constructors-args</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-constructors-args/</fr:route><fr:title
text="A Datatype whose Constructors have Arguments">A Datatype whose Constructors have Arguments</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike of int
               | Car       of bool
               | Lorry     of int
type vehicle = Bike | Motorbike of int | Car of bool | Lorry of int]]></html:pre><html:ul><html:li>Constructors with arguments (like <html:code>Lorry</html:code>) are <html:em>distinct values</html:em>. (So <html:code>Car true</html:code> is distinct from <html:code>Car false</html:code>).</html:li>
  <html:li>Different kinds of <html:code>vehicle</html:code> can belong to one list: <html:code>[Bike; Car true; Motorbike 450]</html:code></html:li></html:ul><html:p>OCaml generalises the notion of enumeration type to allow data to be associated
with each constructor.  The constructor <html:code>Bike</html:code> is a vehicle all by itself, but
the other three constructors create vehicles from arguments.</html:p><html:p>Since we might find it hard to remember what the various <html:code>int</html:code> and
<html:code>bool</html:code> components are for, it is wise to include <html:em>comments</html:em> in
complex declarations.  In OCaml, comments are enclosed in the brackets
<html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>. Programmers should comment their code to explain
design decisions and key features of the algorithms (sometimes by citing a
reference work).</html:p><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike of int  (* engine size in CCs *)
               | Car       of bool (* true if a Reliant Robin *)
               | Lorry     of int  (* number of wheels *)
type vehicle = Bike | Motorbike of int | Car of bool | Lorry of int]]></html:pre><html:p>The list <html:code>[Bike; Car true; Motorbike 450]</html:code> represents a bicycle, a Reliant Robin and a large
motorbike.  It can be almost seen as a mixed-type list containing integers and
booleans.  It is actually a list of vehicles; datatypes lessen the impact of
the restriction that all list elements must have the same type.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-wheels/</fr:uri><fr:display-uri>focs-wheels</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-wheels/</fr:route><fr:title
text="A Finer Wheel Computation">A Finer Wheel Computation</fr:title></fr:frontmatter><fr:mainmatter><html:p>We now define a <html:code>wheels</html:code> function to calculate the number of wheels
in any <html:code>vehicle</html:code>. This requires <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matching</fr:link> to retrieve the
constructors and their associated arguments, around which we build the
logic:</html:p><html:pre><![CDATA[# let wheels = function
  | Bike -> 2
  | Motorbike _ -> 2
  | Car robin -> if robin then 3 else 4
  | Lorry w -> w
val wheels : vehicle -> int = <fun>]]></html:pre><html:p>This function consists of four clauses:</html:p><html:ul><html:li>A Bike has two wheels.  This is a constant result.</html:li>
  <html:li>A Motorbike has two wheels. The <html:code>_</html:code> signifies a "wildcard" pattern match that we discard, since the engine size of the bike is not relevant to the number of wheels.</html:li>
  <html:li>A Reliant Robin has three wheels; all other cars have four. We bind <html:code>robin</html:code> to the <html:code>bool</html:code> argument and then use it in the right hand side of the pattern match, much like a <html:code>let</html:code> binding in normal code.</html:li>
  <html:li>A Lorry has the number of wheels stored with its constructor, and we simply return that.</html:li></html:ul><html:p>There is no overlap between the <html:code>Motorbike</html:code> and <html:code>Lorry</html:code> cases.  Although
<html:code>Motorbike</html:code> and <html:code>Lorry</html:code> both hold an integer, OCaml takes the
constructor into account and keeps any <html:code>Motorbike</html:code> distinct from any <html:code>Lorry</html:code>.</html:p><html:p>Vehicles are one example of a concept consisting of several varieties with
distinct features.  Most programming languages can represent such concepts
using something analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatypes</fr:link>.  (They are sometimes called
<html:em>union types</html:em> or <html:em>variant records</html:em> whose <html:em>tag fields</html:em> play the
role of the constructors.)</html:p><html:p>A pattern may be built from the constructors of several datatypes, including
lists. A pattern may also contain integer and string constants. There is no
limit to the size of patterns or the number of clauses in a function
declaration. OCaml performs pattern-matching <fr:link
href="https://dl.acm.org/citation.cfm?id=507641"
type="external">efficiently</fr:link>
(you do not need to understand the details of how it optimises pattern-matching at this stage).</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstract-data-type/</fr:uri><fr:display-uri>focs-def-abstract-data-type</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-abstract-data-type/</fr:route><fr:title
text="Abstract data type">Abstract data type</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent them. Before choosing the
internal representation for a data structure, you need to specify the full set of
operations. Abstract types can be declared in any modern programming language:
Java’s <html:em>objects</html:em> serve this role, as do OCaml’s modules.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">Dictionaries</fr:link>, and applied to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-queue-adt/"
title="An Abstract Data Type: Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/"
display-uri="focs-queue-adt"
type="local">queues</fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-stacks/"
title="Another Abstract Data Type: Stacks"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-stacks/"
display-uri="focs-stacks"
type="local">stacks</fr:link> later on.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/</fr:uri><fr:display-uri>focs-def-algebraic-datatype</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/</fr:route><fr:title
text="Algebraic datatype">Algebraic datatype</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>OCaml generalises the notion of enumeration type to allow data to be
associated with each constructor: some constructors are values all by themselves,
while others create values from arguments. Constructors with arguments are
<html:em>distinct values</html:em>, and values built from different constructors of one
datatype can belong to a single list.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-constructors-args/"
title="A Datatype whose Constructors have Arguments"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-constructors-args/"
display-uri="focs-constructors-args"
type="local">A Datatype whose Constructors have Arguments</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/</fr:uri><fr:display-uri>focs-queue-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-queue-adt/</fr:route><fr:title
text="An Abstract Data Type: Queues">An Abstract Data Type: Queues</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><html:code>qempty</html:code> is the <html:em>empty queue</html:em></html:li>
  <html:li><html:code>qnull</html:code> <html:em>tests</html:em> whether a queue is empty</html:li>
  <html:li><html:code>qhd</html:code> <html:em>returns</html:em> the element at the <html:em>head</html:em> of a queue</html:li>
  <html:li><html:code>deq</html:code> <html:em>discards</html:em> the element at the <html:em>head</html:em> of a queue</html:li>
  <html:li><html:code>enq</html:code> <html:em>adds</html:em> an element at the <html:em>end</html:em> of a queue</html:li></html:ul><html:p>Breadth-first search becomes much faster if we replace the lists by
<html:em>queues</html:em>.  A queue represents a sequence, allowing elements to be taken
from the head and added to the tail.  This is a First-In-First-Out (FIFO)
discipline: the item next to be removed is the one that has been in the queue
for the longest time.  Lists can implement queues, but <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link> is a poor means
of adding elements to the tail.</html:p><html:p>Our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional arrays</fr:link> are suitable, provided we
augment them with a function to delete the first array element.  (See <html:em>ML
  for the Working Programmer</html:em> page 156.)  Each operation would take <fr:tex
display="inline"><![CDATA[O(\log 
n)]]></fr:tex> time for a queue of length <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>We shall describe a representation of queues that is purely functional, based
upon lists, and efficient.  Operations take <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> time when “amortized”:
averaged over the lifetime of a queue.</html:p><html:p>A conventional programming technique is to represent a queue by an array.  Two
indices point to the front and back of the queue, which may wrap around the
end of the array.  The coding is somewhat tricky.  Worse, the length of the
queue must be given a fixed upper bound.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-enumeration/</fr:uri><fr:display-uri>focs-enumeration</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-enumeration/</fr:route><fr:title
text="An Enumeration Type">An Enumeration Type</fr:title></fr:frontmatter><fr:mainmatter><html:p>We will now learn how to define more expressive types than the
basic ones supplied with the core OCaml language.</html:p><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike
               | Car
               | Lorry
type vehicle = Bike | Motorbike | Car | Lorry]]></html:pre><html:ul><html:li>We have declared a <html:em>new type</html:em> named <html:code>vehicle</html:code>.</html:li>
  <html:li><fr:tex
display="inline"><![CDATA[\ldots ]]></fr:tex> along with four new constants.</html:li>
  <html:li>They are the <html:em>constructors</html:em> of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link>.</html:li></html:ul><html:p>The <html:code>type</html:code> declaration adds a new type to our OCaml session.  Type
<html:code>vehicle</html:code> is as good as any built-in type and even admits
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link> (as we used with the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">built-in list types</fr:link> earlier).
The four new identifiers of type <html:code>vehicle</html:code> are called <html:em>constructors</html:em>.</html:p><html:p>We could represent the various vehicles by the numbers 0–3.  However, the code would be
hard to read and even harder to maintain.  Consider adding <html:code>Tricycle</html:code>
as a new vehicle. If we wanted to add it before <html:code>Bike</html:code>, then all the
numbers would have to be changed.  Using <html:code>type</html:code>, such additions are
trivial and the compiler can (at least sometimes) warn us when it encounters a
function declaration that doesn’t yet have a case for <html:code>Tricycle</html:code>.</html:p><html:p>Representing vehicles by strings like <html:code>"Bike"</html:code>, <html:code>"Car"</html:code>, etc.,
is also bad.  Comparing string values is slow and the compiler
can’t warn us of misspellings like <html:code>"MOtorbike"</html:code>: they will make our
code fail.</html:p><html:p>Most programming languages allow the declaration of types like
<html:code>vehicle</html:code>.  Because they consist of a series of identifiers, they are
called <html:em>enumeration types</html:em>.  Other common examples are days of the week
or colours.  The compiler chooses the integers for us; type-checking prevents
us from confusing <html:code>Bike</html:code> with <html:code>Red</html:code> or <html:code>Sunday</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:uri><fr:display-uri>focs-binary-trees</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:route><fr:title
text="Binary Trees, a Recursive Datatype">Binary Trees, a Recursive Datatype</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a tree =
    Lf
  | Br of 'a * 'a tree * 'a tree
type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmihauytafmmc5evdkkihzsaxper2thnogxohktuubaoxtrpw24qazu.svg" /></html:figure><html:pre><![CDATA[# Br(1, Br(2, Br(4, Lf, Lf),
              Br(5, Lf, Lf)),
        Br(3, Lf, Lf))
- : int tree = Br (1, Br (2, Br (4, Lf, Lf), Br (5, Lf, Lf)), Br (3, Lf, Lf))]]></html:pre><html:p>A data structure with multiple branching is called a “tree”.  Trees can
represent mathematical expressions, logical formulae, computer programs, the
phrase structure of English sentences, etc.</html:p><html:p><html:em>Binary trees</html:em> are nearly as fundamental as lists.  They can provide
efficient storage and retrieval of information.  In a binary tree, each node
is empty (<fr:tex
display="inline"><![CDATA[Lf]]></fr:tex>), or is a branch (<fr:tex
display="inline"><![CDATA[Br]]></fr:tex>) with a label and two subtrees.</html:p><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">OCaml lists</fr:link> are a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> and could be declared as follows:</html:p><html:pre><![CDATA[# type 'a mylist =
  | Nil
  | Cons of 'a * 'a mylist
type 'a mylist = Nil | Cons of 'a * 'a mylist]]></html:pre><html:p>We could even declare <html:code>::</html:code> as an infix constructor.  The only
thing we could not define is the <html:code>[...]</html:code> notation, which is
part of the OCaml grammar (although there does exist a mechanism
to use a <html:em>similar</html:em> syntax for custom indexed datatypes).</html:p><html:p>A <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> type does not have to be <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.
For example, here is a simple datatype of tree shapes with no attached data
that is recursive but not polymorphic.</html:p><html:pre><![CDATA[# type shape =
  | Null
  | Join of shape * shape
type shape = Null | Join of shape * shape]]></html:pre><html:p>The datatype <html:code>'a option</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">mentioned above</fr:link>) is the opposite – it is
polymorphic, but not recursive.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-vehicles/</fr:uri><fr:display-uri>focs-vehicles</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-vehicles/</fr:route><fr:title
text="Declaring a Function on Vehicles">Declaring a Function on Vehicles</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let wheels = function
  | Bike -> 2
  | Motorbike -> 2
  | Car -> 4
  | Lorry -> 18
val wheels : vehicle -> int = <fun>]]></html:pre><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">Datatype constructors</fr:link> can be used in patterns.</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">Pattern-matching</fr:link> is fast, even complicated nested patterns.</html:li>
  <html:li>Notice the type of the argument is <html:code>vehicle</html:code>, which we defined earlier.</html:li></html:ul><html:p>The beauty of datatype declarations is that the new types behave as if they
were built into OCaml. Type-checking catches common errors, such as mixing up
different datatypes in a function like <html:code>wheels</html:code>, as well as missing
and redundant patterns.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/</fr:uri><fr:display-uri>focs-dates</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dates/</fr:route><fr:title
text="Example 1: Dates">Example 1: Dates</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">Abstract level</fr:link>: dates over a certain interval</html:li>
  <html:li>Concrete level: could be 6 characters: <html:code>YYMMDD</html:code> (where each character is represented by 8 bits)</html:li>
  <html:li>Date crises caused by <html:strong>inadequate</html:strong> internal formats:
    <html:ul><html:li>Digital’s PDP-10: using 12-bit dates (good for at most 11 years)</html:li>
      <html:li>2000 crisis: 48 bits could be good for lifetime of universe!</html:li></html:ul></html:li></html:ul><html:p>Digital Equipment Corporation’s date crisis occurred in 1975.  The
PDP-10 was a 36-bit mainframe computer. It represented dates using a 12-bit
format designed for the tiny PDP-8. With 12 bits, one can distinguish
<fr:tex
display="inline"><![CDATA[2^{12} = 4096]]></fr:tex> days or 11 years.</html:p><html:p>Last century, the most common industry format for dates used six characters: two for the
year, two for the month and two for the day. The most common “solution” to the
year 2000 crisis is to add two further characters, thereby altering file sizes.
Others have noticed that the existing six characters consist of 48 bits,
already sufficient to represent all dates over the projected lifetime of the
universe: <fr:tex
display="inline"><![CDATA[2^{48}]]></fr:tex> = <fr:tex
display="inline"><![CDATA[2.8\times  10^{14}]]></fr:tex> days = <fr:tex
display="inline"><![CDATA[7.7\times  10^{11}]]></fr:tex> years!</html:p><html:p>Mathematicians think in terms of unbounded ranges, but the representation we
choose for the computer usually imposes hard limits. A good programming
language like OCaml lets one easily change the representation used in the
program.  But if files in the old representation exist all over the place,
there will still be conversion problems. The need for compatibility with older
systems causes problems across the computer industry.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/</fr:uri><fr:display-uri>focs-ocaml-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/</fr:route><fr:title
text="Exceptions in OCaml">Exceptions in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Failure
exception Failure
# exception NoChange of int
exception NoChange of int
# raise Failure
Exception: Failure.]]></html:pre><html:p>Each <html:code>exception</html:code> declaration introduces a distinct sort of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link>, which can
be handled separately from others. If <fr:tex
display="inline"><![CDATA[E]]></fr:tex> raises an exception, then its
evaluation has failed; <html:em>handling</html:em> an exception means evaluating another
expression and returning its value instead. One exception handler can specify
separate expressions for different sorts of exceptions.</html:p><html:p>Exception names are <html:em>constructors</html:em> of the special <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> <html:code>exn</html:code>.  This is a
peculiarity of OCaml that lets exception-handlers use <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>. Note that
exception <html:code>Failure</html:code> is just an error indication, while <html:code>NoChange n</html:code> carries
further information: the integer <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# try
    print_endline "pre exception";
    raise (NoChange 1);
    print_endline "post exception";
  with
    | NoChange _ ->
        print_endline "handled a NoChange exception"
Line 3, characters 5-23:
Warning 21 [nonreturning-statement]: this statement never returns (or has an unsound type.)
pre exception
handled a NoChange exception

- : unit = ()]]></html:pre><html:p>The effect of <html:code>raise &lt;expr&gt;</html:code> is to jump to the most recently-encountered
handler that matches <html:code>&lt;expr&gt;</html:code>.  The matching handler can only be found
<html:em>dynamically</html:em> (during execution); contrast with how OCaml associates occurrences
of identifiers with their matching declarations, which does not require running
the program.  A handler is introduced via the <html:code>try</html:code> keyword, which executes
the subexpression and dispatches any exceptions encountered to the corresponding
pattern match for exceptions defined in the <html:code>with</html:code> block.</html:p><html:p>This is also the first time that we have encountered the <html:code>unit</html:code> type. This
represents a type that has no values, and is used to indicate that a block
has no meaningful return value.  We will come back to this when learning more
about <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural/"
title="Elements of Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/"
display-uri="focs-procedural"
type="local"><html:em>imperative</html:em> programming</fr:link> later on.  For now, it is sufficient to understand
that <html:code>print_endline</html:code> will print out the argument to the console output, and return
a <html:code>unit</html:code> type.  The semicolon at the end of the expression is a convenient way to
execute sequential statements that return the <html:code>unit</html:code> type.</html:p><html:p>One criticism of OCaml’s exceptions is that—unlike the Java language—nothing
in a function declaration indicates which exceptions it might raise. One
alternative to exceptions is to instead return a value of datatype <html:code>option</html:code>.</html:p><html:pre><![CDATA[# let x = Some 1
val x : int option = Some 1
# let y = None
val y : 'a option = None
# type 'a option = None | Some of 'a
type 'a option = None | Some of 'a]]></html:pre><html:p><html:code>None</html:code> signifies an error, while <html:code>Some x</html:code> returns the solution <fr:tex
display="inline"><![CDATA[x]]></fr:tex>.  This
approach looks clean, but the drawback is that many places in the code would
have to check for <html:code>None</html:code>.  Despite this, there is a builtin <html:code>option</html:code> type
in OCaml as it is so useful. We will see in later lectures how to define our
own version of <html:code>option</html:code> using polymorphic datatype definitions.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:uri><fr:display-uri>focs-lazy-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:route><fr:title
text="Lazy Lists in OCaml">Lazy Lists in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>The empty tuple <html:code>()</html:code> and its <html:em>type</html:em> <html:code>unit</html:code></html:li>
  <html:li>Delayed version of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> is <html:code>fun () -&gt; E</html:code></html:li></html:ul><html:pre><![CDATA[# type 'a seq =
  | Nil
  | Cons of 'a * (unit -> 'a seq)
type 'a seq = Nil | Cons of 'a * (unit -> 'a seq)
# let head (Cons (x, _)) = x
Line 1, characters 10-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val head : 'a seq -> 'a = <fun>
# let tail (Cons (_, xf)) = xf ()
Line 1, characters 10-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val tail : 'a seq -> 'a seq = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[\tt  Cons(x, xf)]]></fr:tex> has <html:em>head</html:em> <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and <html:em>tail function</html:em> <fr:tex
display="inline"><![CDATA[xf]]></fr:tex></html:p><html:p>The primitive OCaml type <html:code>unit</html:code> has one element, which is
written <html:code>()</html:code>.  This element may be regarded as a 0-tuple, and
<html:code>unit</html:code> as the nullary Cartesian product.  (Think of the connection
between multiplication and the number 1.)</html:p><html:p>The empty tuple serves as a placeholder in situations where no information is
required.  It may:</html:p><html:ul><html:li>appear in a data structure.  For example, a <html:code>unit</html:code>-valued <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">dictionary</fr:link> represents a set of keys.</html:li>
  <html:li>be the argument of a function, where its effect is to <html:em>delay evaluation</html:em>.</html:li>
  <html:li>be the argument or result of a procedure. (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
title="Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
display-uri="focs-procedural-programming"
type="local">Procedural Programming section</fr:link>)</html:li></html:ul><html:p>The empty tuple, like all tuples, is a constructor and is allowed in patterns;
for example: <html:code>let f () = ...</html:code></html:p><html:p>In particular <fr:tex
display="inline"><![CDATA[\tt  fun \, () \rightarrow  E]]></fr:tex> is the function that takes an argument of
type <html:code>unit</html:code> and returns the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as its result.  Expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>
is not evaluated until the function is called, even though the only possible
argument is <html:code>()</html:code>.  The function simply delays the evaluation of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/</fr:uri><fr:display-uri>focs-def-pattern-matching</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/</fr:route><fr:title
text="Pattern matching">Pattern matching</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Pattern matching takes a value apart by matching it against the forms that
value can have, letting <html:em>one</html:em> function declaration handle several cases,
separated by a vertical bar <html:code>|</html:code>. Taking a list apart using combinations of
<html:code>hd</html:code> and <html:code>tl</html:code> is hard to get right; fortunately, it is seldom necessary
because of pattern-matching.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">Getting at the Head and Tail</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:uri><fr:display-uri>focs-references-comparison</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:route><fr:title
text="References: OCaml vs conventional languages">References: OCaml vs conventional languages</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>We must write <html:code>!p</html:code> to get the <html:em>contents</html:em> of <html:code>p</html:code></html:li>
  <html:li>We write just <html:code>p</html:code> for the <html:em>address</html:em> of <html:code>p</html:code></html:li>
  <html:li>We can store private <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference cells</fr:link> (like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>balance</html:code></fr:link>) in functions—analogous to elements of <html:em>object-oriented programming</html:em></html:li>
  <html:li>OCaml’s assignment syntax is <fr:tex
display="inline"><![CDATA[\tt  V \, := \, E]]></fr:tex> instead of <fr:tex
display="inline"><![CDATA[V]]></fr:tex> = <fr:tex
display="inline"><![CDATA[E]]></fr:tex></html:li>
  <html:li>OCaml has few control structures: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-while/"
title="Iteration: the while command"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/"
display-uri="focs-while"
type="local"><html:code>while</html:code></fr:link>, <html:code>match</html:code>, <html:code>if</html:code> and <html:code>for</html:code> (the latter is not covered in this course)</html:li>
  <html:li>OCaml has syntax for updating an array via the <html:code>a.(i) &lt;- v</html:code> syntax which is the same as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-array-primitives/"
title="OCaml Primitives for Arrays"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/"
display-uri="focs-array-primitives"
type="local"><html:code>Array.set a i v</html:code></fr:link>.</html:li></html:ul><html:p>Conventional syntax for variables and assignments has hardly changed since
Fortran, the first high-level language. In conventional languages,
virtually all variables can be updated.  We declare something like
<html:code>p: int</html:code>, mentioning no reference type even if the language provides
them.  If we do not specify an initial value, we may get whatever bits were
previously at that address.  Illegal values arising from uninitialised
variables can cause errors that are almost impossible to diagnose.</html:p><html:p>Dereferencing operators (like OCaml’s <html:code>!</html:code>) are especially unpopular, because
they clutter the program text. Virtually all programming languages make dereferencing
implicit (that is, automatic).</html:p><html:p>It is generally accepted these days that a two-dimensional array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> is nothing
but an array of arrays.  An assignment to such an array is typically written
something like <fr:tex
display="inline"><![CDATA[A[i,j] {:=} x]]></fr:tex>; in C, the syntax is <html:code>A[i][j] = x</html:code>. Higher
dimensions are treated analogously.  The corresponding OCaml code can either
declare an array of arrays, or use the <html:code>A.(i)</html:code> syntax to calculate the linear
offset into a single array.</html:p><html:p>You can use the constructs we have learnt to easily create linked (mutable) lists as
an alternative to arrays.</html:p><html:pre><![CDATA[# type 'a mlist =
  | Nil
  | Cons of 'a * 'a mlist ref
type 'a mlist = Nil | Cons of 'a * 'a mlist ref]]></html:pre><html:p>It is worth mentioning that OCaml’s references fully suffice for coding the sort of linked data structures
taught in algorithms courses, as the <html:code>mlist</html:code> type above illustrates. The
programming style is a little different from the usual, but the principles are
the same.  OCaml also provides comprehensive input/output primitives for various
types of file and operating system.</html:p><html:p>OCaml’s system of modules include <html:em>structures,</html:em> which can be seen as encapsulated
groups of declarations, and <html:em>signatures,</html:em> which are specifications of
structures listing the name and type of each component.  Finally, there are
<html:em>functors,</html:em> which are analogous to functions that combine a number of argument
structures, and which can be used to plug program components together. These
primitives are useful for managing large programming projects.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/</fr:uri><fr:display-uri>focs-list-primitives</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-list-primitives/</fr:route><fr:title
text="The List Primitives">The List Primitives</fr:title></fr:frontmatter><fr:mainmatter><html:p>There are two kinds of lists:</html:p><html:ul><html:li><html:code>[]</html:code> represents the empty list</html:li>
  <html:li><html:code>x :: l</html:code> is the list with head <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and tail <fr:tex
display="inline"><![CDATA[l]]></fr:tex></html:li></html:ul><html:pre><![CDATA[# let nil = []
val nil : 'a list = []
# 1 :: nil
- : int list = [1]
# 1 :: 2 :: nil
- : int list = [1; 2]]]></html:pre><html:p>The operator <html:code>::</html:code> (also called <html:code>List.cons</html:code> for “construct”), puts a new element on
to the head of an existing list.  While we should not be too preoccupied with
implementation details, it is essential to know that <html:code>::</html:code> is an <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>
operation.  It uses constant time and space, regardless of the length of the
resulting list.  Lists are represented internally with a linked structure;
adding a new element to a list merely hooks the new element to the front of
the existing structure.  Moreover, that structure continues to denote the same
list as it did before; to see the new list, one must look at the new <html:code>::</html:code> node
(or “cons cell”) just created.  We will explain the <html:code>'a</html:code> notation in the next
section.</html:p><html:p>Here we see the element <html:code>1</html:code> being consed to the front of the list <html:code>[3; 5; 9]</html:code>:</html:p><fr:tex
display="block"><![CDATA[\begin{array}{ccccccccccc}
:: & \to & \cdots & :: & \to &  :: & \to &  :: & \to & [] \\
\downarrow &  &        & \downarrow &  & \downarrow &  & \downarrow  \\
1     &  &        & 3     &  & 5     &  & 9
\end{array}]]></fr:tex><html:p>Given a list, taking its first element (its “head”) or its list of
remaining elements (its “tail”) also takes constant time.  Each
operation just follows a link.  In the diagram above, the first down arrow
leads to the head and the leftmost right arrow leads to the tail.  Once we
have the tail, its head is the second element of the original list, etc.</html:p><html:p>The tail is <html:em>not</html:em> the last element; it is the <html:em>list</html:em> of all elements
other than the head!</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:uri><fr:display-uri>focs-ex-8-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:route><fr:title
text="Exercises › A map for options"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › A map for options</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The type <html:code>'a option</html:code>, declared below, can be viewed as a type of lists having at most one element.
(It is typically used as an alternative to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">exceptions</fr:link>.) Declare an analogue of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>
for type <html:code>'a option</html:code>.</html:p><html:pre><![CDATA[type 'a option = None | Some of 'a]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:uri><fr:display-uri>focs-ex-6-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:route><fr:title
text="Exercises › A type for arithmetic expressions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › A type for arithmetic expressions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for arithmetic expressions that have the following
possibilities: floating-point numbers, variables (represented by strings), or expressions of the form <fr:tex
display="inline"><![CDATA[-E]]></fr:tex>,
<fr:tex
display="inline"><![CDATA[E+E]]></fr:tex>, <fr:tex
display="inline"><![CDATA[E\times  E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:uri><fr:display-uri>focs-ex-6-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:route><fr:title
text="Exercises › Days of the week type"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Days of the week type</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for the days of the week. Comment on the practicality of such
a type in a calendar application.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:uri><fr:display-uri>focs-ex-6-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:route><fr:title
text="Exercises › Evaluating expressions with exceptions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Evaluating expressions with exceptions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, write a function that evaluates an expression. If the expression
contains any variables, your function should raise an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> indicating the variable name.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:uri><fr:display-uri>focs-ex-9-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:route><fr:title
text="Exercises › Lazy binary trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Lazy binary trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A <html:em>lazy binary tree</html:em> is either empty or is a branch containing a label and two lazy <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>,
possibly to infinite depth. Present an OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> to represent lazy binary trees, along with a
function that accepts a lazy binary tree and produces a lazy list that contains all of the tree’s
labels. (Taken from the exam question 2008 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-trees/</fr:uri><fr:display-uri>focs-topic-trees</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-trees/</fr:route><fr:title
text="Trees">Trees</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:uri><fr:display-uri>focs-search-methods</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:route><fr:title
text="A Survey of Search Methods">A Survey of Search Methods</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Depth-first: use a <html:em>stack</html:em>  (efficient but incomplete)</html:li>
  <html:li>Breadth-first: use a <html:em>queue</html:em> (uses too much space!)</html:li>
  <html:li>Iterative deepening: use depth-first to get benefits of breadth-first (trades time for space)</html:li>
  <html:li>Best-first: use a <html:em>priority queue</html:em> (heuristic search)</html:li></html:ul><html:p>The data structure determines the search!</html:p><html:p>Search procedures can be classified by the data structure used to store
pending subtrees.  Depth-first search stores them on a stack, which is
implicit in functions like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link>, but can be made explicit.
Breadth-first search stores such nodes in a queue.</html:p><html:p>An important variation is to store the nodes in a priority queue, which
is an ordered sequence.  The priority queue applies some sort of ranking
function to the nodes, placing higher-ranked nodes before lower-ranked ones.
The ranking function typically estimates the distance from the node to a
solution.  If the estimate is good, the solution is located swiftly.  This
method is called best-first search.</html:p><html:p>The priority queue can be kept as a sorted list, although this is slow.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary search trees</fr:link> would be much better on average, and fancier data
structures improve matters further.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:uri><fr:display-uri>focs-tree-traversal</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal/</fr:route><fr:title
text="Aside: Traversing Trees (3 Methods)">Aside: Traversing Trees (3 Methods)</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec preorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      [v] @ preorder t1 @ preorder t2
val preorder : 'a tree -> 'a list = <fun>
# let rec inorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      inorder t1 @ [v] @ inorder t2
val inorder : 'a tree -> 'a list = <fun>
# let rec postorder = function
  | Lf -> []
  | Br (v, t1, t2) ->
      postorder t1 @ postorder t2 @ [v]
val postorder : 'a tree -> 'a list = <fun>]]></html:pre><html:p><html:em>Tree traversal</html:em> means examining each node of a tree in some order.  <fr:link
href="https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming"
type="external">D. E.
Knuth</fr:link> has
identified three forms of tree traversal: preorder, inorder and
postorder.  We can code these “visiting orders” as functions
that convert trees into lists of labels.  Algorithms based on these notions
typically perform some action at each node; the functions above simply copy
the nodes into lists.  Consider the tree:</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmic3wbal56lpqlso6xcqsl6jfrutwygavrn3xds7c6ieywfjr7qdhm.svg" /></html:figure><html:ul><html:li><html:code>preorder</html:code> visits the label first (“Polish notation”), yielding <html:code>ABDECFG</html:code></html:li>
<html:li><html:code>inorder</html:code> visits the label midway, yielding <html:code>DBEAFCG</html:code></html:li>
<html:li><html:code>postorder</html:code> visits the label last (“Reverse Polish”), yielding <html:code>DEBFGCA</html:code>. You might be familiar with this concept if you own an ancient RPN calculator!</html:li></html:ul><html:p>What is the use of <html:code>inorder</html:code>? Consider applying it to a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>: the
result is a sorted list of pairs. We could use this, for example, to merge two
binary search trees. It is not difficult to transform a sorted list of pairs
into a binary search tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-properties/</fr:uri><fr:display-uri>focs-tree-properties</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-properties/</fr:route><fr:title
text="Basic Properties of Binary Trees">Basic Properties of Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec count = function
  | Lf -> 0  (* number of branch nodes *)
  | Br (v, t1, t2) -> 1 + count t1 + count t2
val count : 'a tree -> int = <fun>
# let rec depth = function
  | Lf -> 0  (* length of longest path *)
  | Br (v, t1, t2) -> 1 + max (depth t1) (depth t2)
val depth : 'a tree -> int = <fun>]]></html:pre><html:p>The invariant <fr:tex
display="inline"><![CDATA[\texttt {count}(t)\le  2^{\texttt {depth}(t)} - 1]]></fr:tex> holds in the functions above.</html:p><html:p>Functions on trees are expressed recursively using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.  Both
functions above are analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-length/"
title="Efficiently Computing the Length of a List"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-length/"
display-uri="focs-length"
type="local"><fr:tex
display="inline"><![CDATA[\texttt {length}]]></fr:tex> on lists</fr:link>.  Here is a third
measure of a tree’s size:</html:p><html:pre><![CDATA[# let rec leaves = function
  | Lf -> 1
  | Br (v, t1, t2) -> leaves t1 + leaves t2
val leaves : 'a tree -> int = <fun>]]></html:pre><html:p>This function is redundant because of a basic fact about trees, which can be
proved by induction: for every tree <fr:tex
display="inline"><![CDATA[t]]></fr:tex>, we have <fr:tex
display="inline"><![CDATA[\texttt {leaves}(t) =
\texttt {count}(t)+1]]></fr:tex>.  The invariant <fr:tex
display="inline"><![CDATA[\texttt {count}(t)\le  2^{\texttt {depth}(t)} - 1]]></fr:tex> stated above also has an elementary
proof by induction.</html:p><html:p>A tree of depth 20 can store <fr:tex
display="inline"><![CDATA[2^{20}-1]]></fr:tex> or approximately one million elements.
The access paths to these elements are short, particularly when compared with
a million-element list!</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/</fr:uri><fr:display-uri>focs-bst</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst/</fr:route><fr:title
text="Binary Search Trees">Binary Search Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>dictionary</html:em> associates <html:em>values</html:em> (here, numbers) with <html:em>keys</html:em>.</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifkdrvs6ut5buyf724655gdcinx637uevqiaejsmb2jgu36gaf4wq.svg" /></html:figure><html:p>Binary search trees are an important application of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>.  They work
for keys that have a total ordering, such as strings.  Each branch of the tree
carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree holds smaller keys; the right
subtree holds greater keys.  If the tree remains reasonably balanced, then
update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  These times
hold in the average case; given random data, the tree is likely to remain
balanced.</html:p><html:p>At a given node, all keys in the left subtree are smaller (or equal) while all
trees in the right subtree are greater.</html:p><html:p>An unbalanced tree has a linear access time in the worst case.  Examples
include building a tree by repeated insertions of elements in increasing or
decreasing order; there is a close resemblance to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>.  Building a binary
search tree, then converting it to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">inorder</fr:link>, yields a sorting algorithm called
<html:em>treesort</html:em>.</html:p><html:p>Self-balancing trees, such as Red-Black trees, attain <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> in the worst
case.  They are complicated to implement.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:uri><fr:display-uri>focs-binary-trees</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-binary-trees/</fr:route><fr:title
text="Binary Trees, a Recursive Datatype">Binary Trees, a Recursive Datatype</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a tree =
    Lf
  | Br of 'a * 'a tree * 'a tree
type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmihauytafmmc5evdkkihzsaxper2thnogxohktuubaoxtrpw24qazu.svg" /></html:figure><html:pre><![CDATA[# Br(1, Br(2, Br(4, Lf, Lf),
              Br(5, Lf, Lf)),
        Br(3, Lf, Lf))
- : int tree = Br (1, Br (2, Br (4, Lf, Lf), Br (5, Lf, Lf)), Br (3, Lf, Lf))]]></html:pre><html:p>A data structure with multiple branching is called a “tree”.  Trees can
represent mathematical expressions, logical formulae, computer programs, the
phrase structure of English sentences, etc.</html:p><html:p><html:em>Binary trees</html:em> are nearly as fundamental as lists.  They can provide
efficient storage and retrieval of information.  In a binary tree, each node
is empty (<fr:tex
display="inline"><![CDATA[Lf]]></fr:tex>), or is a branch (<fr:tex
display="inline"><![CDATA[Br]]></fr:tex>) with a label and two subtrees.</html:p><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">OCaml lists</fr:link> are a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> and could be declared as follows:</html:p><html:pre><![CDATA[# type 'a mylist =
  | Nil
  | Cons of 'a * 'a mylist
type 'a mylist = Nil | Cons of 'a * 'a mylist]]></html:pre><html:p>We could even declare <html:code>::</html:code> as an infix constructor.  The only
thing we could not define is the <html:code>[...]</html:code> notation, which is
part of the OCaml grammar (although there does exist a mechanism
to use a <html:em>similar</html:em> syntax for custom indexed datatypes).</html:p><html:p>A <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive</fr:link> type does not have to be <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>.
For example, here is a simple datatype of tree shapes with no attached data
that is recursive but not polymorphic.</html:p><html:pre><![CDATA[# type shape =
  | Null
  | Join of shape * shape
type shape = Null | Join of shape * shape]]></html:pre><html:p>The datatype <html:code>'a option</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">mentioned above</fr:link>) is the opposite – it is
polymorphic, but not recursive.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/</fr:uri><fr:display-uri>focs-def-binary-search-tree</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/</fr:route><fr:title
text="Binary search tree">Binary search tree</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A binary search tree works for keys that have a total ordering, such as
strings. Each branch of the tree carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree
holds smaller keys and its right subtree holds greater keys. If the tree remains
reasonably balanced, then update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of
size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary Search Trees</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:uri><fr:display-uri>focs-bfs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Append">Breadth-First Tree Traversal — Using Append</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nbreadth = function
  | [] -> []
  | Lf :: ts -> nbreadth ts
  | Br (v, t, u) :: ts ->
      v :: nbreadth (ts @ [t; u])
val nbreadth : 'a tree list -> 'a list = <fun>]]></html:pre><html:p>Keeps an <html:em>enormous queue</html:em> of nodes of search, and is a wasteful use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.</html:p><html:p>Breadth-first search can be inefficient, this naive implementation especially
so.  When the search is at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> of the tree, the list contains all the
remaining trees at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex>, followed by the subtrees (all at depth <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>) of
the trees that have already been visited.  At depth 10, the list could already
contain 1024 elements.  It requires a lot of space, and aggravates this with a
gross misuse of append.  Evaluating <html:code>ts@[t, u]</html:code> copies the long list
<html:code>ts</html:code> just to insert two elements.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:uri><fr:display-uri>focs-bfs-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Queues">Breadth-First Tree Traversal — Using Queues</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec breadth q =
    if qnull q then []
    else
      match qhd q with
      | Lf -> breadth (deq q)
      | Br (v, t, u) -> v :: breadth (enq (enq (deq q) t) u)
val breadth : 'a tree queue -> 'a list = <fun>]]></html:pre><html:p>This function implements the same algorithm as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-append/"
title="Breadth-First Tree Traversal — Using Append"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/"
display-uri="focs-bfs-append"
type="local"><html:code>nbreadth</html:code></fr:link> but uses a different
data structure.  It represents queues using type <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-queues/"
title="Efficient Functional Queues: Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/"
display-uri="focs-functional-queues"
type="local"><html:code>queue</html:code></fr:link> instead of type
<html:code>list</html:code>.</html:p><html:p>To compare their efficiency, I applied both functions to the full binary tree
of depth 12, which contains 4095 labels.  The function <html:code>nbreadth</html:code> took 30
seconds while <html:code>breadth</html:code> took only 0.15 seconds: faster by a factor of 200.</html:p><html:p>For larger trees, the speedup would be greater.  Choosing the right data
structure pays handsomely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/</fr:uri><fr:display-uri>focs-bfs-dfs</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-dfs/</fr:route><fr:title
text="Breadth-First v Depth-First Tree Traversal">Breadth-First v Depth-First Tree Traversal</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>binary trees as <html:em>decision trees</html:em></html:li>
  <html:li>look for <html:em>solution nodes</html:em>
    <html:ul><html:li>Depth-first: search one subtree in full before moving on</html:li>
      <html:li>Breadth-first: search all nodes at level <fr:tex
display="inline"><![CDATA[k]]></fr:tex> before moving to <fr:tex
display="inline"><![CDATA[k+1]]></fr:tex></html:li></html:ul></html:li>
  <html:li>finds <html:em>all</html:em> solutions — nearest first!</html:li></html:ul><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">Preorder, inorder and postorder tree traversals</fr:link> all have something in common:
they are depth-first.  At each node, the left subtree is entirely
traversed before the right subtree.  Depth-first traversals are easy to code
and can be efficient, but they are ill-suited for some problems.</html:p><html:p>Suppose the tree represents the possible moves in a puzzle, and the purpose
of the traversal is to search for a node containing a solution.  Then a
depth-first traversal may find one solution node deep in the left subtree,
when another solution is at the very top of the right subtree.  Often we
want the shortest path to a solution.</html:p><html:p>Suppose the tree is <html:em>infinite</html:em> or simply extremely large.  Depth-first search
is almost useless with such trees, for if the left subtree is infinite then the
search will never reach the right subtree.  OCaml can represent infinite trees by
the means discussed in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sequences/"
title="Sequences, or Lazy Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sequences/"
display-uri="focs-sequences"
type="local">lecture on laziness</fr:link>. Another tree representation (suitable
for solving solitaire, for example) is by a function <html:code>next : pos -&gt; pos list</html:code>,
which maps a board position to a list of the positions possible after
the next move.  For simplicity, the examples below use the OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link>
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local"><html:code>tree</html:code></fr:link>, which has only finite trees.</html:p><html:p>A <html:em>breadth-first</html:em> traversal explores the nodes horizontally rather than
vertically.  When visiting a node, it does not traverse the subtrees until
it has visited all other nodes at the current depth.  This is easily
implemented by keeping a list of trees to visit.  Initially, this list
consists of one element: the entire tree.  Each iteration removes a tree
from the head of the list and adds its subtrees after the end of the
list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:uri><fr:display-uri>focs-tree-traversal-efficient</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/</fr:route><fr:title
text="Efficiently Traversing Trees">Efficiently Traversing Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>Unfortunately, the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">traversal functions</fr:link> are quadratic in the
worst case: the appends in the recursive calls are inefficient.  To correct
that problem, we (as usual) add an accumulating argument.  Observe how
each function constructs its result list and compare with how appends were
eliminated from <html:code>quicksort</html:code> in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">Sorting lecture</fr:link>.</html:p><html:pre><![CDATA[# let rec preord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      v :: preord (t1, preord (t2, vs))
val preord : 'a tree * 'a list -> 'a list = <fun>
# let rec inord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      inord (t1, v::inord (t2, vs))
val inord : 'a tree * 'a list -> 'a list = <fun>
# let rec postord = function
  | Lf, vs -> vs
  | Br (v, t1, t2), vs ->
      postord (t1, postord (t2, v::vs))
val postord : 'a tree * 'a list -> 'a list = <fun>]]></html:pre><html:p>One can prove equations relating each of these functions to its counterpart on
the previous section.  For example:</html:p><fr:tex
display="block"><![CDATA[\texttt {inord}(t, vs) = \texttt {inorder}(t) @ vs]]></fr:tex><html:p>These three types of tree traversal are related in that all are depth-first.
They each traverse the left subtree in full before traversing the right
subtree.  Breadth-first search (from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queues/"
title="Queues and Search Strategies"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queues/"
display-uri="focs-queues"
type="local">Queues lecture</fr:link>) is another
possibility.  That involves going through the levels of a tree one at a time.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:uri><fr:display-uri>focs-functional-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:route><fr:title
text="Functional Arrays as Binary Trees">Functional Arrays as Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>The path to element <fr:tex
display="inline"><![CDATA[i]]></fr:tex> follows the <html:em>binary code</html:em> for <fr:tex
display="inline"><![CDATA[i]]></fr:tex> (its “subscript”).</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifetc2v73r7qxnzo6bthiblab2tezbaqvmovq7e4q6vgdl5ewr3wi.svg" /></html:figure><html:p>This simple representation (credited to W. Braun) ensures that the tree is
balanced.  Complexity of access is always <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>, which is optimal.  For
actual running time, access to conventional arrays is much faster: it requires
only a few hardware instructions.  Array access is often taken to be <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>,
which (as always) presumes that hardware limits are never exceeded.</html:p><html:p>The lower bound for array subscripts (or “indices”) is one.  The upper bound starts at zero
(which signifies the empty array) and can grow without limit.  Inspection of
the diagram above should make it clear that these trees are always balanced:
the left subtree can have at most one node more than the right subtree,
recursively all the way down.  (This assumes that the array is defined for
subscripts <fr:tex
display="inline"><![CDATA[1\ldots  n]]></fr:tex> with no gaps; an array defined only for odd numbers, for
example, would obviously be unbalanced.)</html:p><html:p>The numbers in the diagram above are not the labels of branch nodes, but
indicate the positions of array elements. For example, the label corresponding
to <fr:tex
display="inline"><![CDATA[A[2]]]></fr:tex> is at the position shown. The nodes of a functional array are
labelled with the data we want to store, not with these integers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:uri><fr:display-uri>focs-iterative-deepening</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:route><fr:title
text="Iterative deepening: Another Exhaustive Search">Iterative deepening: Another Exhaustive Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Breadth-first search examines <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> nodes:
    <fr:tex
display="block"><![CDATA[1 + b + \cdots  + b^d = {b^{d+1}-1 \over  b-1}
  \qquad  \begin {array}{rl}
            b & {} = \hbox {branching factor}\\
            d & {} = \hbox {depth}
          \end {array}]]></fr:tex></html:li>
  <html:li>Recompute nodes at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> instead of storing them</html:li>
  <html:li>Time factor is <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>; complexity is still <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex></html:li>
  <html:li>Space required at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> drops from <fr:tex
display="inline"><![CDATA[b^d]]></fr:tex> to <fr:tex
display="inline"><![CDATA[d]]></fr:tex></html:li></html:ul><html:p>Breadth-first search is not practical for infinite trees: it uses too much
space. Large parts of the tree have to be stored.
Consider the slightly more general problem of searching trees whose
branching factor is <fr:tex
display="inline"><![CDATA[b]]></fr:tex> (for binary trees, <fr:tex
display="inline"><![CDATA[b=2]]></fr:tex>).  Then breadth-first search
to depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> examines <fr:tex
display="inline"><![CDATA[(b^{d+1}-1)/(b-1)]]></fr:tex> nodes, which is <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>, ignoring
the constant factor of <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex>.  Since all nodes that are examined are also
stored, the space and time requirements are both <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.</html:p><html:p><html:em>Depth-first iterative deepening</html:em> combines the space efficiency of
depth-first with the “nearest-first” property of breadth-first search.  It
performs repeated depth-first searches with increasing depth bounds, each time
discarding the result of the previous search.  Thus it searches to depth 1,
then to depth 2, and so on until it finds a solution.  We can afford to
discard previous results because the number of nodes is growing exponentially.
There are <fr:tex
display="inline"><![CDATA[b^{d+1}]]></fr:tex> nodes at level <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>; if <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex>, this number actually
exceeds the total number of nodes of all previous levels put together, namely
<fr:tex
display="inline"><![CDATA[(b^{d+1}-1) / (b-1)]]></fr:tex>.</html:p><html:p><fr:link
href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.91.288"
type="external">Korf shows</fr:link> that the time needed for iterative deepening to reach
depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> is only <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> times that for breadth-first search, if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>.
This is a constant factor; both algorithms have the same time complexity,
<fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.  In typical applications where <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex> the extra factor of
<fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> is quite tolerable.  The reduction in the space requirement is
exponential, from <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> for breadth-first to <fr:tex
display="inline"><![CDATA[O(d)]]></fr:tex> for iterative
deepening. Of course, this assumes that the tree itself is not stored in memory.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:uri><fr:display-uri>focs-bst-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:route><fr:title
text="Lookup: Seeks Left or Right">Lookup: Seeks Left or Right</fr:title><fr:meta
name="ocaml-deps">focs-binary-trees</fr:meta></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Missing of string
exception Missing of string
# let rec lookup b = function
  | Br ((a, x), t1, t2) ->
      if b < a then
        lookup b t1
      else if a < b then
        lookup b t2
      else
        x
  | Lf -> raise (Missing b)
val lookup : string -> (string * 'a) tree -> 'a = <fun>]]></html:pre><html:p>This has guaranteed <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> access time <html:em>if</html:em> the tree is balanced!</html:p><html:p>Lookup in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
title="Binary search tree"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
display-uri="focs-def-binary-search-tree"
type="local">binary search tree</fr:link> goes to the left subtree if the desired
key is smaller than the current one and to the right if it is greater.
It raises <html:code>Missing</html:code> if it encounters an empty tree.</html:p><html:p>Since an ordering is involved, we have to declare the functions for a specific
type, here <html:code>string</html:code>.  Now <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Missing</html:code> mentions that type: if lookup
fails, the exception returns the missing key.  The exception could be
eliminated using type <html:code>option</html:code> of our earlier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-datatypes/"
title="Datatypes and Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-datatypes/"
display-uri="focs-datatypes"
type="local">Datatypes lecture</fr:link>, using the
constructor <html:code>None</html:code> for failure.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:uri><fr:display-uri>focs-funarray-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:route><fr:title
text="The Lookup Function">The Lookup Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Subscript
  let rec sub = function
  | Lf, _ -> raise Subscript  (* Not found *)
  | Br (v, t1, t2), k ->
      if k = 1 then v
      else if k mod 2 = 0 then
        sub (t1, k / 2)
      else
        sub (t2, k / 2)
exception Subscript
val sub : 'a tree * int -> 'a = <fun>
# let rec sub = function (* Alternative implementation *)
  | Lf, _ -> raise Subscript
  | Br (v, t1, t2), 1 -> v
  | Br (v, t1, t2), k when k mod 2 = 0 -> sub (t1, k / 2)
  | Br (v, t1, t2), k -> sub (t2, k / 2)
val sub : 'a tree * int -> 'a = <fun>]]></html:pre><html:p>Notice that we have used a new keyword <html:code>when</html:code> above, which changes
pattern clauses to be only matched if the expression evalutes to true.
This can be equivalently expressed by moving the corresponding
checks into an <html:code>if</html:code> clause on the right hand side of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern match</fr:link>,
but is often more readable using <html:code>when</html:code> (as above).</html:p><html:p>The lookup function <html:code>sub</html:code>, divides the subscript by 2 until 1 is
reached.  If the remainder is 0 then the function follows the left subtree,
otherwise the right.  If it reaches a leaf, it signals error by raising
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Subscript</html:code>.</html:p><html:p>Array access can also be understood in terms of the subscript’s binary code.
Because the subscript must be a positive integer, in binary it has a leading
one.  Discard this one and reverse the remaining bits.  Interpreting zero
as <html:em>left</html:em> and one as <html:em>right</html:em> yields the path from the root to the
subscript.</html:p><html:p>Popular literature often explains the importance of binary as being led by
hardware: because a circuit is either on or off.  The truth is almost the
opposite.  Designers of digital electronics go to a lot of trouble to suppress
the continuous behaviour that would naturally arise.  The real reason why
binary is important is its role in algorithms: an <html:code>if-then-else</html:code> decision leads
to binary branching.</html:p><html:p>Data structures, such as trees, and algorithms, such as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link>, use binary
branching in order to reduce a cost from <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  Two is the
smallest integer divisor that achieves this reduction.  (Larger divisors are
only occasionally helpful, as in the case of B-trees, where they reduce the
constant factor.)  The simplicity of binary arithmetic compared with decimal
arithmetic is just another instance of the simplicity of algorithms based on
binary choices.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:uri><fr:display-uri>focs-funarray-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:route><fr:title
text="The Update Function">The Update Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update = function
  | Lf, k, w ->
      if k = 1 then
        Br (w, Lf, Lf)
      else
        raise Subscript  (* Gap in tree *)
  | Br (v, t1, t2), k, w ->
      if k = 1 then
        Br (w, t1, t2)
      else if k mod 2 = 0 then
        Br (v, update (t1, k / 2, w), t2)
      else
        Br (v, t1, update (t2, k / 2, w))
val update : 'a tree * int * 'a -> 'a tree = <fun>]]></html:pre><html:p>The <html:code>update</html:code> function also divides the subscript repeatedly by two.  When it
reaches a value of one, it has identified the element position.  Then it
replaces the branch node by another branch with the new label.</html:p><html:p>A leaf may be replaced by a branch, extending the array, provided no
intervening nodes have to be generated.  This suffices for arrays without gaps
in their subscripting.  (The data structure can be modified to allow <html:em>sparse</html:em>
arrays, where most subscript positions are undefined.) Exception <fr:link
href="/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
title="The Lookup Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
display-uri="focs-funarray-lookup"
type="local"><html:code>Subscript</html:code></fr:link>
indicates that the subscript position does not exist and cannot be created.
This use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link> is not easily replaced by <html:code>None</html:code> and <html:code>Some</html:code>.</html:p><html:p>Note that there are two tests involving <fr:tex
display="inline"><![CDATA[k=1]]></fr:tex>.  If we have reached a leaf,
it returns a branch, extending the array by one.  If we are still at a branch
node, then the effect is to update an existing array element.</html:p><html:p>A similar function can <html:em>shrink</html:em> an array by one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:uri><fr:display-uri>focs-bst-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:route><fr:title
text="Update">Update</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update k v = function
  | Lf -> Br ((k, v), Lf, Lf)
  | Br ((a, x), t1, t2) ->
      if k < a then
        Br ((a, x), update k v t1, t2)
      else if a < k then
        Br ((a, x), t1, update k v t2)
      else (* a = k *)
        Br ((a, v), t1, t2)
val update : 'a -> 'b -> ('a * 'b) tree -> ('a * 'b) tree = <fun>]]></html:pre><html:p>This is also <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> as it copies the path only, and <html:em>not whole subtrees!</html:em></html:p><html:p>If you are familiar with the usual update operation for this sort of tree, you
may wonder whether it can be implemented in OCaml, where there is no direct way to
replace part of a data structure by something else.</html:p><html:p>The update operation is a nice piece of functional programming.  It searches
in the same manner as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
title="Lookup: Seeks Left or Right"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
display-uri="focs-bst-lookup"
type="local"><html:code>lookup</html:code></fr:link>, but the recursive calls reconstruct a
new tree around the result of the update.  One subtree is updated and the
other left unchanged.  The internal representation of trees ensures that
unchanged parts of the tree are not copied, but <html:em>shared</html:em>.
Therefore, update copies only the path from the root to the new
node.  Its time and space requirements, for a reasonably balanced tree, are
both <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.</html:p><html:p>The comparison between <fr:tex
display="inline"><![CDATA[b]]></fr:tex> and <fr:tex
display="inline"><![CDATA[a]]></fr:tex> allows three cases:</html:p><html:ul><html:li>smaller: update the left subtree; share the right</html:li>
<html:li>greater: update the right subtree; share the left</html:li>
<html:li>equal: update the label and share both subtrees</html:li></html:ul><html:p>Note: in the function definition, <html:code>(* a = k *)</html:code> is a comment.  Comments
in OCaml are enclosed in the brackets <html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:uri><fr:display-uri>focs-ex-10-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:route><fr:title
text="Exercises › An implicit infinite tree"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › An implicit infinite tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the following OCaml function.</html:p><html:pre><![CDATA[let next n = [2 * n; 2 * n + 1]]]></html:pre><html:p>If we regard it as representing a tree, where the subtrees are computed from the current label, what
tree does <html:code>next 1</html:code> represent?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:uri><fr:display-uri>focs-ex-7-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:route><fr:title
text="Exercises › Deleting from a search tree"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Deleting from a search tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Describe an algorithm for deleting an entry from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>. Comment on the suitability of
your approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:uri><fr:display-uri>focs-ex-7-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:route><fr:title
text="Exercises › Implementing deletion"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Implementing deletion</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the delete function outlined in the previous exercise.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:uri><fr:display-uri>focs-ex-7-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:route><fr:title
text="Exercises › Insertion order in search trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion order in search trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Draw the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link> that arises from successively inserting the following pairs into the
empty tree: <html:code>("Alice", 6)</html:code>, <html:code>("Tobias", 2)</html:code>, <html:code>("Gerald", 8)</html:code>, <html:code>("Lucy", 9)</html:code>. Then repeat this
task using the order <html:code>("Gerald", 8)</html:code>, <html:code>("Alice", 6)</html:code>, <html:code>("Lucy", 9)</html:code>, <html:code>("Tobias", 2)</html:code>. Why are
results different?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:uri><fr:display-uri>focs-ex-7-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:route><fr:title
text="Exercises › Insertion with collision detection"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion with collision detection</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an insertion function for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link>. It should resemble the existing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-update/"
title="Update"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/"
display-uri="focs-bst-update"
type="local"><html:code>update</html:code></fr:link>
function except that it should raise the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Collision</html:code> if the item to be inserted is already
present.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:uri><fr:display-uri>focs-ex-9-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:route><fr:title
text="Exercises › Lazy binary trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Lazy binary trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A <html:em>lazy binary tree</html:em> is either empty or is a branch containing a label and two lazy <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>,
possibly to infinite depth. Present an OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> to represent lazy binary trees, along with a
function that accepts a lazy binary tree and produces a lazy list that contains all of the tree’s
labels. (Taken from the exam question 2008 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:uri><fr:display-uri>focs-ex-7-7</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-7/</fr:route><fr:title
text="Exercises › Linear traversals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Linear traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>preord</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>inord</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
title="Efficiently Traversing Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal-efficient/"
display-uri="focs-tree-traversal-efficient"
type="local"><html:code>postord</html:code></fr:link> all take linear time in the size of the
tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:uri><fr:display-uri>focs-ex-7-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-6/</fr:route><fr:title
text="Exercises › Quadratic traversals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Quadratic traversals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Show that the functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>preorder</html:code></fr:link>, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>postorder</html:code></fr:link> all require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time in the worst
case, where <fr:tex
display="inline"><![CDATA[n]]></fr:tex> is the size of the tree.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:uri><fr:display-uri>focs-ex-10-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:route><fr:title
text="Exercises › Rewriting breadth with let"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Rewriting breadth with let</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
title="Breadth-First Tree Traversal — Using Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
display-uri="focs-bfs-queues"
type="local"><html:code>breadth</html:code></fr:link> using a nested <html:code>let</html:code> construction rather than
<html:code>match</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:uri><fr:display-uri>focs-ex-7-8</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:route><fr:title
text="Exercises › Shifting a functional array"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Shifting a functional array</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to remove the first element from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional array</fr:link>. All the other elements are to
have their subscripts reduced by one. The cost of this operation should be linear in the size of the
array.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:uri><fr:display-uri>focs-ex-6-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-2/</fr:route><fr:title
text="Exercises › Summing tree labels"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Summing tree labels</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write an OCaml function taking a binary tree labelled with integers and returning their sum.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:uri><fr:display-uri>focs-ex-10-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:route><fr:title
text="Exercises › Tree-based queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Tree-based queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Suppose that we have an implementation of queues, based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>, such that each operation
takes logarithmic time in the worst case. Outline the advantages and drawbacks of such an
implementation compared with one presented above.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:uri><fr:display-uri>focs-ex-6-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-3/</fr:route><fr:title
text="Exercises › What ftree builds"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › What ftree builds</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">definition of <html:code>'a tree</html:code></fr:link> from before:</html:p><html:pre><![CDATA[type 'a tree = Lf | Br of 'a * 'a tree * 'a tree]]></html:pre><html:p>Examine the following function declaration. What does <html:code>ftree (1, n)</html:code> accomplish?</html:p><html:pre><![CDATA[let rec ftree k n =
  if n = 0 then Lf
  else Br (k, ftree (2 * k) (n - 1), ftree (2 * k + 1) (n - 1))]]></html:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-exceptions/</fr:uri><fr:display-uri>focs-topic-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-exceptions/</fr:route><fr:title
text="Exceptions">Exceptions</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/</fr:uri><fr:display-uri>focs-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-exceptions/</fr:route><fr:title
text="Error Handling: Exceptions">Error Handling: Exceptions</fr:title></fr:frontmatter><fr:mainmatter><html:p>During a computation, what happens if something goes <html:em>wrong?</html:em></html:p><html:ul><html:li>Division by zero</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">Pattern matching</fr:link> failure</html:li></html:ul><html:p><html:em>Exception-handling</html:em> lets us recover gracefully.</html:p><html:ul><html:li>Raising an exception abandons the current computation.</html:li>
  <html:li>Handling the exception attempts an alternative computation.</html:li>
  <html:li>The raising and handling can be far apart in the code.</html:li>
  <html:li>Errors of <html:em>different sorts</html:em> can be handled separately.</html:li></html:ul><html:p>Exceptions are necessary because it is not always possible to tell in advance
whether or not a search will lead to a dead end or whether a numerical
calculation will encounter errors such as overflow or divide by zero. Rather
than just crashing, programs should check whether things have gone wrong, and
perhaps attempt an alternative computation (perhaps using a different algorithm
or higher precision). A number of modern languages provide exception handling.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/</fr:uri><fr:display-uri>focs-def-exception</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-exception/</fr:route><fr:title
text="Exception">Exception</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>An exception signals that something has gone <html:em>wrong</html:em> during a computation,
such as division by zero or pattern matching failure. Raising an exception
abandons the current computation; handling the exception attempts an alternative
computation. The raising and the handling can be far apart in the code, and
errors of <html:em>different sorts</html:em> can be handled separately.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">Error Handling: Exceptions</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/</fr:uri><fr:display-uri>focs-ocaml-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/</fr:route><fr:title
text="Exceptions in OCaml">Exceptions in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Failure
exception Failure
# exception NoChange of int
exception NoChange of int
# raise Failure
Exception: Failure.]]></html:pre><html:p>Each <html:code>exception</html:code> declaration introduces a distinct sort of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link>, which can
be handled separately from others. If <fr:tex
display="inline"><![CDATA[E]]></fr:tex> raises an exception, then its
evaluation has failed; <html:em>handling</html:em> an exception means evaluating another
expression and returning its value instead. One exception handler can specify
separate expressions for different sorts of exceptions.</html:p><html:p>Exception names are <html:em>constructors</html:em> of the special <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> <html:code>exn</html:code>.  This is a
peculiarity of OCaml that lets exception-handlers use <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>. Note that
exception <html:code>Failure</html:code> is just an error indication, while <html:code>NoChange n</html:code> carries
further information: the integer <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:pre><![CDATA[# try
    print_endline "pre exception";
    raise (NoChange 1);
    print_endline "post exception";
  with
    | NoChange _ ->
        print_endline "handled a NoChange exception"
Line 3, characters 5-23:
Warning 21 [nonreturning-statement]: this statement never returns (or has an unsound type.)
pre exception
handled a NoChange exception

- : unit = ()]]></html:pre><html:p>The effect of <html:code>raise &lt;expr&gt;</html:code> is to jump to the most recently-encountered
handler that matches <html:code>&lt;expr&gt;</html:code>.  The matching handler can only be found
<html:em>dynamically</html:em> (during execution); contrast with how OCaml associates occurrences
of identifiers with their matching declarations, which does not require running
the program.  A handler is introduced via the <html:code>try</html:code> keyword, which executes
the subexpression and dispatches any exceptions encountered to the corresponding
pattern match for exceptions defined in the <html:code>with</html:code> block.</html:p><html:p>This is also the first time that we have encountered the <html:code>unit</html:code> type. This
represents a type that has no values, and is used to indicate that a block
has no meaningful return value.  We will come back to this when learning more
about <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural/"
title="Elements of Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/"
display-uri="focs-procedural"
type="local"><html:em>imperative</html:em> programming</fr:link> later on.  For now, it is sufficient to understand
that <html:code>print_endline</html:code> will print out the argument to the console output, and return
a <html:code>unit</html:code> type.  The semicolon at the end of the expression is a convenient way to
execute sequential statements that return the <html:code>unit</html:code> type.</html:p><html:p>One criticism of OCaml’s exceptions is that—unlike the Java language—nothing
in a function declaration indicates which exceptions it might raise. One
alternative to exceptions is to instead return a value of datatype <html:code>option</html:code>.</html:p><html:pre><![CDATA[# let x = Some 1
val x : int option = Some 1
# let y = None
val y : 'a option = None
# type 'a option = None | Some of 'a
type 'a option = None | Some of 'a]]></html:pre><html:p><html:code>None</html:code> signifies an error, while <html:code>Some x</html:code> returns the solution <fr:tex
display="inline"><![CDATA[x]]></fr:tex>.  This
approach looks clean, but the drawback is that many places in the code would
have to check for <html:code>None</html:code>.  Despite this, there is a builtin <html:code>option</html:code> type
in OCaml as it is so useful. We will see in later lectures how to define our
own version of <html:code>option</html:code> using polymorphic datatype definitions.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:uri><fr:display-uri>focs-bst-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:route><fr:title
text="Lookup: Seeks Left or Right">Lookup: Seeks Left or Right</fr:title><fr:meta
name="ocaml-deps">focs-binary-trees</fr:meta></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Missing of string
exception Missing of string
# let rec lookup b = function
  | Br ((a, x), t1, t2) ->
      if b < a then
        lookup b t1
      else if a < b then
        lookup b t2
      else
        x
  | Lf -> raise (Missing b)
val lookup : string -> (string * 'a) tree -> 'a = <fun>]]></html:pre><html:p>This has guaranteed <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> access time <html:em>if</html:em> the tree is balanced!</html:p><html:p>Lookup in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
title="Binary search tree"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
display-uri="focs-def-binary-search-tree"
type="local">binary search tree</fr:link> goes to the left subtree if the desired
key is smaller than the current one and to the right if it is greater.
It raises <html:code>Missing</html:code> if it encounters an empty tree.</html:p><html:p>Since an ordering is involved, we have to declare the functions for a specific
type, here <html:code>string</html:code>.  Now <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Missing</html:code> mentions that type: if lookup
fails, the exception returns the missing key.  The exception could be
eliminated using type <html:code>option</html:code> of our earlier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-datatypes/"
title="Datatypes and Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-datatypes/"
display-uri="focs-datatypes"
type="local">Datatypes lecture</fr:link>, using the
constructor <html:code>None</html:code> for failure.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:uri><fr:display-uri>focs-change-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:route><fr:title
text="Making Change with Exceptions">Making Change with Exceptions</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Change
  let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise Change
    | c::till, amt -> if amt < 0 then raise Change
                      else try c :: change (c::till) (amt - c)
                           with Change -> change till amt
exception Change
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>In the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">Lists lectures</fr:link>, we considered the problem of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.  The greedy
algorithm presented there could not express “6 using 5 and 2” because it always
took the largest coin.  Returning <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">the list of all possible solutions</fr:link> avoids
that problem rather expensively: we only need one solution.</html:p><html:p>Using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>, we can code a <html:em>backtracking</html:em> algorithm: one that can undo
past decisions if it comes to a dead end.  The exception <html:code>Change</html:code> is raised if
we run out of coins (with a non-zero amount) or if the amount goes negative.
We always try the largest coin, but enclose the recursive call in an exception
handler, which undoes the choice if it goes wrong.</html:p><html:p>Carefully observe how exceptions interact with <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  The exception
handler always undoes the <html:em>most recent</html:em> choice, leaving others possibly to
be undone later.  If making change really is impossible, then eventually
<html:code>exception Change</html:code> will be raised with no handler to catch it, and it
will be reported at top level.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-trace/</fr:uri><fr:display-uri>focs-change-trace</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-trace/</fr:route><fr:title
text="Making Change: A Trace">Making Change: A Trace</fr:title></fr:frontmatter><fr:mainmatter><html:p>Here is the full execution. Observe how the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception handlers</fr:link> nest and how
they drop away once the given expression has returned a value.</html:p><fr:tex
display="block"><![CDATA[\begin{aligned}
\text{change [5; 2] 6}
  \Rightarrow &\; \text{try 5::change [5; 2] 1}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{try 5::(try 5::change [5; 2] (-4)}\\
              &\; \text{with Change -> change [2] 1)}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{5::(change [2] 1)}\\
              &\; \text{with Change -> change [2] 6}\\
  \Rightarrow &\; \text{try 5::(try 2::change [2] (-1)}\\
              &\; \text{with Change -> change [] 1)}\\
              &\; \text{with Change -> change [2] 6} \\
  \Rightarrow &\; \text{try 5::(change [] 1)}\\
              &\; \text{with Change -> change [2] 6} \\
  \Rightarrow &\; \text{change [2] 6} \\
  \Rightarrow &\; \text{try 2::change [2] 4}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::change [2] 2}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::(try 2::change [2] 0 }\\
              &\; \text{with Change -> change [] 2)}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::(try 2::[2]}\\
              &\; \text{with Change -> change [] 4)}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{try 2::[2; 2]}\\
              &\; \text{with Change -> change [] 6} \\
  \Rightarrow &\; \text{[2; 2; 2]}
\end{aligned}]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/</fr:uri><fr:display-uri>focs-private-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-private-references/</fr:route><fr:title
text="Private, Persistent References">Private, Persistent References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception TooMuch of int
exception TooMuch of int
# let makeAccount initBalance =
    let balance = ref initBalance in
    let withdraw amt =
       if amt > !balance then
         raise (TooMuch (amt - !balance))
       else begin
         balance := !balance - amt;
         !balance
       end
    in
    withdraw
val makeAccount : int -> int -> int = <fun>]]></html:pre><html:p>As you may have noticed, OCaml’s programming style looks clumsy compared with
that of languages like C.  OCaml omits the defaults and abbreviations they
provide to shorten programs.  However, OCaml’s explicitness makes it ideal for
teaching the fine points of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> and arrays.  OCaml’s references are more
flexible than those found in other languages.</html:p><html:p>The function <html:code>makeAccount</html:code> models a bank.  Calling the function with a
specified initial balance creates a new reference (<html:code>balance</html:code>) to
maintain the account balance and returns a function (<html:code>withdraw</html:code>) having
sole access to that reference.  Calling <html:code>withdraw</html:code> reduces the balance
by the specified amount and returns the new balance.  You can pay money in by
withdrawing a negative amount.  The <html:code>if</html:code>-construct prevents the account
from going overdrawn, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">raising an exception</fr:link>.</html:p><html:p>Look at the <fr:tex
display="inline"><![CDATA[E_1; E_2]]></fr:tex> sequence inside <html:code>begin</html:code> … <html:code>end</html:code> in the <html:em>else</html:em> part above.
The first expression updates the account balance and returns the trivial
value ().  The second expression, <html:code>!balance</html:code>, returns the current
balance but does not return the reference itself: that would allow
unauthorised updates.</html:p><html:p>This example is based on one by Dr A C Norman.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:uri><fr:display-uri>focs-funarray-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:route><fr:title
text="The Lookup Function">The Lookup Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Subscript
  let rec sub = function
  | Lf, _ -> raise Subscript  (* Not found *)
  | Br (v, t1, t2), k ->
      if k = 1 then v
      else if k mod 2 = 0 then
        sub (t1, k / 2)
      else
        sub (t2, k / 2)
exception Subscript
val sub : 'a tree * int -> 'a = <fun>
# let rec sub = function (* Alternative implementation *)
  | Lf, _ -> raise Subscript
  | Br (v, t1, t2), 1 -> v
  | Br (v, t1, t2), k when k mod 2 = 0 -> sub (t1, k / 2)
  | Br (v, t1, t2), k -> sub (t2, k / 2)
val sub : 'a tree * int -> 'a = <fun>]]></html:pre><html:p>Notice that we have used a new keyword <html:code>when</html:code> above, which changes
pattern clauses to be only matched if the expression evalutes to true.
This can be equivalently expressed by moving the corresponding
checks into an <html:code>if</html:code> clause on the right hand side of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern match</fr:link>,
but is often more readable using <html:code>when</html:code> (as above).</html:p><html:p>The lookup function <html:code>sub</html:code>, divides the subscript by 2 until 1 is
reached.  If the remainder is 0 then the function follows the left subtree,
otherwise the right.  If it reaches a leaf, it signals error by raising
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Subscript</html:code>.</html:p><html:p>Array access can also be understood in terms of the subscript’s binary code.
Because the subscript must be a positive integer, in binary it has a leading
one.  Discard this one and reverse the remaining bits.  Interpreting zero
as <html:em>left</html:em> and one as <html:em>right</html:em> yields the path from the root to the
subscript.</html:p><html:p>Popular literature often explains the importance of binary as being led by
hardware: because a circuit is either on or off.  The truth is almost the
opposite.  Designers of digital electronics go to a lot of trouble to suppress
the continuous behaviour that would naturally arise.  The real reason why
binary is important is its role in algorithms: an <html:code>if-then-else</html:code> decision leads
to binary branching.</html:p><html:p>Data structures, such as trees, and algorithms, such as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link>, use binary
branching in order to reduce a cost from <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  Two is the
smallest integer divisor that achieves this reduction.  (Larger divisors are
only occasionally helpful, as in the case of B-trees, where they reduce the
constant factor.)  The simplicity of binary arithmetic compared with decimal
arithmetic is just another instance of the simplicity of algorithms based on
binary choices.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:uri><fr:display-uri>focs-funarray-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:route><fr:title
text="The Update Function">The Update Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update = function
  | Lf, k, w ->
      if k = 1 then
        Br (w, Lf, Lf)
      else
        raise Subscript  (* Gap in tree *)
  | Br (v, t1, t2), k, w ->
      if k = 1 then
        Br (w, t1, t2)
      else if k mod 2 = 0 then
        Br (v, update (t1, k / 2, w), t2)
      else
        Br (v, t1, update (t2, k / 2, w))
val update : 'a tree * int * 'a -> 'a tree = <fun>]]></html:pre><html:p>The <html:code>update</html:code> function also divides the subscript repeatedly by two.  When it
reaches a value of one, it has identified the element position.  Then it
replaces the branch node by another branch with the new label.</html:p><html:p>A leaf may be replaced by a branch, extending the array, provided no
intervening nodes have to be generated.  This suffices for arrays without gaps
in their subscripting.  (The data structure can be modified to allow <html:em>sparse</html:em>
arrays, where most subscript positions are undefined.) Exception <fr:link
href="/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
title="The Lookup Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
display-uri="focs-funarray-lookup"
type="local"><html:code>Subscript</html:code></fr:link>
indicates that the subscript position does not exist and cannot be created.
This use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link> is not easily replaced by <html:code>None</html:code> and <html:code>Some</html:code>.</html:p><html:p>Note that there are two tests involving <fr:tex
display="inline"><![CDATA[k=1]]></fr:tex>.  If we have reached a leaf,
it returns a branch, extending the array by one.  If we are still at a branch
node, then the effect is to update an existing array element.</html:p><html:p>A similar function can <html:em>shrink</html:em> an array by one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:uri><fr:display-uri>focs-ex-6-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-5/</fr:route><fr:title
text="Exercises › Evaluating expressions with exceptions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Evaluating expressions with exceptions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, write a function that evaluates an expression. If the expression
contains any variables, your function should raise an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> indicating the variable name.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:uri><fr:display-uri>focs-ex-7-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:route><fr:title
text="Exercises › Insertion with collision detection"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion with collision detection</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an insertion function for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link>. It should resemble the existing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-update/"
title="Update"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/"
display-uri="focs-bst-update"
type="local"><html:code>update</html:code></fr:link>
function except that it should raise the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Collision</html:code> if the item to be inserted is already
present.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:uri><fr:display-uri>focs-ex-7-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:route><fr:title
text="Exercises › Returning the old value on collision"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Returning the old value on collision</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, it would be natural for exceptional <html:code>Collision</html:code> to return the
value previously stored in the dictionary. Why is that goal difficult to achieve?</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-dictionaries/</fr:uri><fr:display-uri>focs-topic-dictionaries</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-dictionaries/</fr:route><fr:title
text="Dictionaries">Dictionaries</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstract-data-type/</fr:uri><fr:display-uri>focs-def-abstract-data-type</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-abstract-data-type/</fr:route><fr:title
text="Abstract data type">Abstract data type</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent them. Before choosing the
internal representation for a data structure, you need to specify the full set of
operations. Abstract types can be declared in any modern programming language:
Java’s <html:em>objects</html:em> serve this role, as do OCaml’s modules.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">Dictionaries</fr:link>, and applied to
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-queue-adt/"
title="An Abstract Data Type: Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/"
display-uri="focs-queue-adt"
type="local">queues</fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-stacks/"
title="Another Abstract Data Type: Stacks"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-stacks/"
display-uri="focs-stacks"
type="local">stacks</fr:link> later on.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-arrays/</fr:uri><fr:display-uri>focs-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-arrays/</fr:route><fr:title
text="Arrays">Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>A conventional array is an indexed storage area.
  <html:ul><html:li>It is updated <html:em>in place</html:em> by the command <html:code>a.(k) &lt;- x</html:code></html:li>
  <html:li>The concept is inherently <html:em>imperative</html:em>.</html:li></html:ul></html:li>
<html:li>A <html:em>functional array</html:em> is a finite map from integers to data.
  <html:ul><html:li>Updating implies <html:em>copying</html:em> to return <html:code>update(A, k, x)</html:code></html:li>
  <html:li>The new array equals <html:code>A</html:code> except that <html:code>A.(k) = x</html:code>.</html:li></html:ul></html:li>
<html:li>Can we do updates efficiently?</html:li></html:ul><html:p>The elements of a list can only be reached by counting from the front.
Elements of a tree are reached by following a path from the root.  An
<html:em>array</html:em> hides such structural matters; its elements are uniformly
designated by number.  Immediate access to arbitrary parts of a data structure
is called <html:em>random access</html:em>.</html:p><html:p>Arrays are the dominant data structure in conventional programming languages.
The ingenious use of arrays is the key to many of the great classical
algorithms, such as Hoare’s original <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link> (the partition step) and
Warshall’s transitive-closure algorithm.</html:p><html:p>The drawback is that subscripting is a chief cause of programmer error.  That
is why arrays play little role in this introductory course.</html:p><html:p>Functional arrays are described below in order to illustrate another way of
using trees to organise data.  Here is a summary of basic dictionary data
structures in order of decreasing generality and increasing efficiency:</html:p><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link>: Most general, needing only equality on keys, but inefficient: linear time.</html:li>
<html:li>Binary search: Needs an ordering on keys.  Logarithmic access time in the average case, but our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link> are linear in the worst case.</html:li>
<html:li>Array subscripting: Least general, requiring keys to be integers, but even worst-case time is logarithmic.</html:li></html:ul></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/</fr:uri><fr:display-uri>focs-bst</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst/</fr:route><fr:title
text="Binary Search Trees">Binary Search Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>dictionary</html:em> associates <html:em>values</html:em> (here, numbers) with <html:em>keys</html:em>.</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifkdrvs6ut5buyf724655gdcinx637uevqiaejsmb2jgu36gaf4wq.svg" /></html:figure><html:p>Binary search trees are an important application of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>.  They work
for keys that have a total ordering, such as strings.  Each branch of the tree
carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree holds smaller keys; the right
subtree holds greater keys.  If the tree remains reasonably balanced, then
update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  These times
hold in the average case; given random data, the tree is likely to remain
balanced.</html:p><html:p>At a given node, all keys in the left subtree are smaller (or equal) while all
trees in the right subtree are greater.</html:p><html:p>An unbalanced tree has a linear access time in the worst case.  Examples
include building a tree by repeated insertions of elements in increasing or
decreasing order; there is a close resemblance to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>.  Building a binary
search tree, then converting it to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">inorder</fr:link>, yields a sorting algorithm called
<html:em>treesort</html:em>.</html:p><html:p>Self-balancing trees, such as Red-Black trees, attain <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> in the worst
case.  They are complicated to implement.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/</fr:uri><fr:display-uri>focs-def-binary-search-tree</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/</fr:route><fr:title
text="Binary search tree">Binary search tree</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A binary search tree works for keys that have a total ordering, such as
strings. Each branch of the tree carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree
holds smaller keys and its right subtree holds greater keys. If the tree remains
reasonably balanced, then update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of
size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary Search Trees</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:uri><fr:display-uri>focs-dictionary-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:route><fr:title
text="Dictionaries">Dictionaries</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>lookup: find an item in the dictionary</html:li>
<html:li>update (insert): replace (store) an item in the dictionary</html:li>
<html:li>delete: remove an item from the dictionary</html:li>
<html:li>empty: the null dictionary</html:li>
<html:li>Missing: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> for errors in <html:code>lookup</html:code> and <html:code>delete</html:code></html:li></html:ul><html:p>Ideally, an <html:em>abstract type</html:em> should provide these operations and hide the internal data structures.</html:p><html:p>A dictionary attaches values to identifiers, called “keys”.  Before choosing
the internal representation for a data structure, you need to specify the full
set of operations. In fact, here we only consider <html:code>update</html:code> (associating a
value with an identifier) and <html:code>lookup</html:code> (retrieving such a value). Deletion
is more difficult and would limit our choices. Some applications may need
additional operations, such as <html:code>merge</html:code> (combining two dictionaries). We
shall see that update can be done efficiently in a functional style, without
excessive copying.</html:p><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent dictionaries. Abstract
types can be declared in any modern programming language. Java’s <html:em>objects</html:em>
serve this role, as do OCaml’s modules. This course does not cover modules, and we
simply declare the dictionary operations individually.</html:p><html:p>An <html:em>association list</html:em> (a list of pairs) is the simplest dictionary representation.
Lookup is by <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link>, and therefore slow: <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>. Association lists are
only usable if there are few keys in use. However, they are general in that the
keys do not need a concept of ordering, only equality.</html:p><html:pre><![CDATA[# exception Missing
exception Missing
# let rec lookup a = function
  | [] -> raise Missing
  | (x, y) :: pairs ->
      if a = x then y
      else lookup a pairs
val lookup : 'a -> ('a * 'b) list -> 'b = <fun>
# let update (l, b, y) = (b, y) :: l
val update : ('a * 'b) list * 'a * 'b -> ('a * 'b) list = <fun>]]></html:pre><html:p>To enter a new <html:code>(key, value)</html:code> pair, simply “cons” it to the list with <html:code>update</html:code>.
This takes constant time, which is the best we could hope for.  But the space
requirement is huge: linear in the number of updates, not in the number of
distinct keys. Obsolete entries are never deleted: that would require first
finding them, increasing the update time from <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:uri><fr:display-uri>focs-bst-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-lookup/</fr:route><fr:title
text="Lookup: Seeks Left or Right">Lookup: Seeks Left or Right</fr:title><fr:meta
name="ocaml-deps">focs-binary-trees</fr:meta></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Missing of string
exception Missing of string
# let rec lookup b = function
  | Br ((a, x), t1, t2) ->
      if b < a then
        lookup b t1
      else if a < b then
        lookup b t2
      else
        x
  | Lf -> raise (Missing b)
val lookup : string -> (string * 'a) tree -> 'a = <fun>]]></html:pre><html:p>This has guaranteed <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> access time <html:em>if</html:em> the tree is balanced!</html:p><html:p>Lookup in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
title="Binary search tree"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-binary-search-tree/"
display-uri="focs-def-binary-search-tree"
type="local">binary search tree</fr:link> goes to the left subtree if the desired
key is smaller than the current one and to the right if it is greater.
It raises <html:code>Missing</html:code> if it encounters an empty tree.</html:p><html:p>Since an ordering is involved, we have to declare the functions for a specific
type, here <html:code>string</html:code>.  Now <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Missing</html:code> mentions that type: if lookup
fails, the exception returns the missing key.  The exception could be
eliminated using type <html:code>option</html:code> of our earlier <fr:link
href="/teaching/2627/FoundsCS/forest/focs-datatypes/"
title="Datatypes and Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-datatypes/"
display-uri="focs-datatypes"
type="local">Datatypes lecture</fr:link>, using the
constructor <html:code>None</html:code> for failure.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:uri><fr:display-uri>focs-bst-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst-update/</fr:route><fr:title
text="Update">Update</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update k v = function
  | Lf -> Br ((k, v), Lf, Lf)
  | Br ((a, x), t1, t2) ->
      if k < a then
        Br ((a, x), update k v t1, t2)
      else if a < k then
        Br ((a, x), t1, update k v t2)
      else (* a = k *)
        Br ((a, v), t1, t2)
val update : 'a -> 'b -> ('a * 'b) tree -> ('a * 'b) tree = <fun>]]></html:pre><html:p>This is also <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> as it copies the path only, and <html:em>not whole subtrees!</html:em></html:p><html:p>If you are familiar with the usual update operation for this sort of tree, you
may wonder whether it can be implemented in OCaml, where there is no direct way to
replace part of a data structure by something else.</html:p><html:p>The update operation is a nice piece of functional programming.  It searches
in the same manner as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
title="Lookup: Seeks Left or Right"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-lookup/"
display-uri="focs-bst-lookup"
type="local"><html:code>lookup</html:code></fr:link>, but the recursive calls reconstruct a
new tree around the result of the update.  One subtree is updated and the
other left unchanged.  The internal representation of trees ensures that
unchanged parts of the tree are not copied, but <html:em>shared</html:em>.
Therefore, update copies only the path from the root to the new
node.  Its time and space requirements, for a reasonably balanced tree, are
both <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.</html:p><html:p>The comparison between <fr:tex
display="inline"><![CDATA[b]]></fr:tex> and <fr:tex
display="inline"><![CDATA[a]]></fr:tex> allows three cases:</html:p><html:ul><html:li>smaller: update the left subtree; share the right</html:li>
<html:li>greater: update the right subtree; share the left</html:li>
<html:li>equal: update the label and share both subtrees</html:li></html:ul><html:p>Note: in the function definition, <html:code>(* a = k *)</html:code> is a comment.  Comments
in OCaml are enclosed in the brackets <html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:uri><fr:display-uri>focs-ex-7-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-4/</fr:route><fr:title
text="Exercises › Deleting from a search tree"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Deleting from a search tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Describe an algorithm for deleting an entry from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link>. Comment on the suitability of
your approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:uri><fr:display-uri>focs-ex-7-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-5/</fr:route><fr:title
text="Exercises › Implementing deletion"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Implementing deletion</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the delete function outlined in the previous exercise.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:uri><fr:display-uri>focs-ex-7-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-1/</fr:route><fr:title
text="Exercises › Insertion order in search trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion order in search trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Draw the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search tree</fr:link> that arises from successively inserting the following pairs into the
empty tree: <html:code>("Alice", 6)</html:code>, <html:code>("Tobias", 2)</html:code>, <html:code>("Gerald", 8)</html:code>, <html:code>("Lucy", 9)</html:code>. Then repeat this
task using the order <html:code>("Gerald", 8)</html:code>, <html:code>("Alice", 6)</html:code>, <html:code>("Lucy", 9)</html:code>, <html:code>("Tobias", 2)</html:code>. Why are
results different?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:uri><fr:display-uri>focs-ex-7-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-2/</fr:route><fr:title
text="Exercises › Insertion with collision detection"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Insertion with collision detection</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an insertion function for <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link>. It should resemble the existing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst-update/"
title="Update"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst-update/"
display-uri="focs-bst-update"
type="local"><html:code>update</html:code></fr:link>
function except that it should raise the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Collision</html:code> if the item to be inserted is already
present.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:uri><fr:display-uri>focs-ex-7-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-3/</fr:route><fr:title
text="Exercises › Returning the old value on collision"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Returning the old value on collision</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Continuing the previous exercise, it would be natural for exceptional <html:code>Collision</html:code> to return the
value previously stored in the dictionary. Why is that goal difficult to achieve?</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-arrays/</fr:uri><fr:display-uri>focs-topic-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-arrays/</fr:route><fr:title
text="Arrays">Arrays</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-examples/</fr:uri><fr:display-uri>focs-array-examples</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-array-examples/</fr:route><fr:title
text="Array Examples">Array Examples</fr:title></fr:frontmatter><fr:mainmatter><html:p>In the following session, the identifier <html:code>ar</html:code> is bound to an array of 20 elements, which
are initially set to the squares of their subscripts.  The array’s third
element (which actually has subscript 2) is inspected and found to be four. The
second call to <html:code>Array.get</html:code> supplies a subscript that is out of range, so OCaml
rejects it.</html:p><html:pre><![CDATA[# let ar = Array.init 20 (fun i -> i * i)
val ar : int array =
  [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81; 100; 121; 144; 169; 196; 225; 256;
    289; 324; 361|]
# Array.get ar 2
- : int = 4
# Array.get ar 20
Exception: Invalid_argument "index out of bounds".
# Array.set ar 2 33; ar
- : int array =
[|0; 1; 33; 9; 16; 25; 36; 49; 64; 81; 100; 121; 144; 169; 196; 225; 256;
  289; 324; 361|]]]></html:pre><html:p>By calling <html:code>Array.set</html:code>, we then modify the element with subscript 2. Note
however that we cannot modify the array’s length. If we outgrow the array, we
have to create a new one, copy the data into it, and then forget the old array.
Typically the new array would be double the size of the old one, so that the
cost of copying is insignificant.</html:p><html:p>OCaml provides numerous operators for modifying, computing over and searching in
arrays. Many are analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">functions on lists</fr:link>. For example,
<html:code>Array.exists</html:code> takes a boolean-valued function and returns <html:code>true</html:code> if an
array element satisfies it.</html:p><html:pre><![CDATA[# Array.exists (fun i -> i > 200) ar
- : bool = true
# Array.exists (fun i -> i < 0) ar
- : bool = false]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-arrays/</fr:uri><fr:display-uri>focs-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-arrays/</fr:route><fr:title
text="Arrays">Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>A conventional array is an indexed storage area.
  <html:ul><html:li>It is updated <html:em>in place</html:em> by the command <html:code>a.(k) &lt;- x</html:code></html:li>
  <html:li>The concept is inherently <html:em>imperative</html:em>.</html:li></html:ul></html:li>
<html:li>A <html:em>functional array</html:em> is a finite map from integers to data.
  <html:ul><html:li>Updating implies <html:em>copying</html:em> to return <html:code>update(A, k, x)</html:code></html:li>
  <html:li>The new array equals <html:code>A</html:code> except that <html:code>A.(k) = x</html:code>.</html:li></html:ul></html:li>
<html:li>Can we do updates efficiently?</html:li></html:ul><html:p>The elements of a list can only be reached by counting from the front.
Elements of a tree are reached by following a path from the root.  An
<html:em>array</html:em> hides such structural matters; its elements are uniformly
designated by number.  Immediate access to arbitrary parts of a data structure
is called <html:em>random access</html:em>.</html:p><html:p>Arrays are the dominant data structure in conventional programming languages.
The ingenious use of arrays is the key to many of the great classical
algorithms, such as Hoare’s original <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link> (the partition step) and
Warshall’s transitive-closure algorithm.</html:p><html:p>The drawback is that subscripting is a chief cause of programmer error.  That
is why arrays play little role in this introductory course.</html:p><html:p>Functional arrays are described below in order to illustrate another way of
using trees to organise data.  Here is a summary of basic dictionary data
structures in order of decreasing generality and increasing efficiency:</html:p><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link>: Most general, needing only equality on keys, but inefficient: linear time.</html:li>
<html:li>Binary search: Needs an ordering on keys.  Logarithmic access time in the average case, but our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link> are linear in the worst case.</html:li>
<html:li>Array subscripting: Least general, requiring keys to be integers, but even worst-case time is logarithmic.</html:li></html:ul></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:uri><fr:display-uri>focs-functional-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-arrays/</fr:route><fr:title
text="Functional Arrays as Binary Trees">Functional Arrays as Binary Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>The path to element <fr:tex
display="inline"><![CDATA[i]]></fr:tex> follows the <html:em>binary code</html:em> for <fr:tex
display="inline"><![CDATA[i]]></fr:tex> (its “subscript”).</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifetc2v73r7qxnzo6bthiblab2tezbaqvmovq7e4q6vgdl5ewr3wi.svg" /></html:figure><html:p>This simple representation (credited to W. Braun) ensures that the tree is
balanced.  Complexity of access is always <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>, which is optimal.  For
actual running time, access to conventional arrays is much faster: it requires
only a few hardware instructions.  Array access is often taken to be <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>,
which (as always) presumes that hardware limits are never exceeded.</html:p><html:p>The lower bound for array subscripts (or “indices”) is one.  The upper bound starts at zero
(which signifies the empty array) and can grow without limit.  Inspection of
the diagram above should make it clear that these trees are always balanced:
the left subtree can have at most one node more than the right subtree,
recursively all the way down.  (This assumes that the array is defined for
subscripts <fr:tex
display="inline"><![CDATA[1\ldots  n]]></fr:tex> with no gaps; an array defined only for odd numbers, for
example, would obviously be unbalanced.)</html:p><html:p>The numbers in the diagram above are not the labels of branch nodes, but
indicate the positions of array elements. For example, the label corresponding
to <fr:tex
display="inline"><![CDATA[A[2]]]></fr:tex> is at the position shown. The nodes of a functional array are
labelled with the data we want to store, not with these integers.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/</fr:uri><fr:display-uri>focs-array-primitives</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-array-primitives/</fr:route><fr:title
text="OCaml Primitives for Arrays">OCaml Primitives for Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# [|"a"; "b"; "c"|] (* allocate a fresh string array *)
- : string array = [|"a"; "b"; "c"|]
# Array.make 3 'a'   (* array[3] with cell containing 'a' *)
- : char array = [|'a'; 'a'; 'a'|]
# let aa = Array.init 5 (fun i -> i * 10) (* array[5] initialised to (fun i) *)
val aa : int array = [|0; 10; 20; 30; 40|]
# Array.get aa 3  (* retrieve the 4th cell in the array *)
- : int = 30
# Array.set aa 3 42 (* set the 4th cell's value to 42 *)
- : unit = ()]]></html:pre><html:p>There are many other array operations in the <html:code>Array</html:code> module in the OCaml standard
library.</html:p><html:pre><![CDATA[# Array.make
- : int -> 'a -> 'a array = <fun>
# Array.init
- : int -> (int -> 'a) -> 'a array = <fun>
# Array.get
- : 'a array -> int -> 'a = <fun>
# Array.set
- : 'a array -> int -> 'a -> unit = <fun>]]></html:pre><html:p>OCaml arrays are like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> that hold several elements instead of one.  The
elements of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element array are designated by the integers from 0
to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex>.  The <fr:tex
display="inline"><![CDATA[i]]></fr:tex>th array element is usually written <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex>.
If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is a type then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>array</html:code> is the
type of arrays (of any size) with elements from <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.</html:p><html:p>Calling <html:code>Array.init n f</html:code> creates an array of the size specified in <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
by function <fr:tex
display="inline"><![CDATA[f]]></fr:tex>.  Initially, element <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex> holds the value of <fr:tex
display="inline"><![CDATA[f(i)]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex>.
Like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local"><html:code>ref</html:code></fr:link>, it allocates mutable storage to hold the specified values.</html:p><html:p>Calling <html:code>Array.get A i</html:code> returns the contents of <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex>.</html:p><html:p>Calling <html:code>Array.set A i E</html:code> modifies the array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by storing the
value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as the new contents of <fr:tex
display="inline"><![CDATA[A[i]]]></fr:tex>; it returns <html:code>()</html:code> as its value.</html:p><html:p>OCaml’s arrays are much safer than C’s. In C, an array is nothing more than an
address indicating the start of a storage area. Nothing indicates the size of
the area.  Therefore C programs are vulnerable to <html:em>buffer overrun attacks:</html:em> an
attacker sends more data than the receiving program expects, overrunning the
area of storage set aside to hold it. The attack eventually overwrites the
program itself, replacing it with code controlled by the attacker.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:uri><fr:display-uri>focs-references-comparison</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:route><fr:title
text="References: OCaml vs conventional languages">References: OCaml vs conventional languages</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>We must write <html:code>!p</html:code> to get the <html:em>contents</html:em> of <html:code>p</html:code></html:li>
  <html:li>We write just <html:code>p</html:code> for the <html:em>address</html:em> of <html:code>p</html:code></html:li>
  <html:li>We can store private <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference cells</fr:link> (like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>balance</html:code></fr:link>) in functions—analogous to elements of <html:em>object-oriented programming</html:em></html:li>
  <html:li>OCaml’s assignment syntax is <fr:tex
display="inline"><![CDATA[\tt  V \, := \, E]]></fr:tex> instead of <fr:tex
display="inline"><![CDATA[V]]></fr:tex> = <fr:tex
display="inline"><![CDATA[E]]></fr:tex></html:li>
  <html:li>OCaml has few control structures: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-while/"
title="Iteration: the while command"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/"
display-uri="focs-while"
type="local"><html:code>while</html:code></fr:link>, <html:code>match</html:code>, <html:code>if</html:code> and <html:code>for</html:code> (the latter is not covered in this course)</html:li>
  <html:li>OCaml has syntax for updating an array via the <html:code>a.(i) &lt;- v</html:code> syntax which is the same as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-array-primitives/"
title="OCaml Primitives for Arrays"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/"
display-uri="focs-array-primitives"
type="local"><html:code>Array.set a i v</html:code></fr:link>.</html:li></html:ul><html:p>Conventional syntax for variables and assignments has hardly changed since
Fortran, the first high-level language. In conventional languages,
virtually all variables can be updated.  We declare something like
<html:code>p: int</html:code>, mentioning no reference type even if the language provides
them.  If we do not specify an initial value, we may get whatever bits were
previously at that address.  Illegal values arising from uninitialised
variables can cause errors that are almost impossible to diagnose.</html:p><html:p>Dereferencing operators (like OCaml’s <html:code>!</html:code>) are especially unpopular, because
they clutter the program text. Virtually all programming languages make dereferencing
implicit (that is, automatic).</html:p><html:p>It is generally accepted these days that a two-dimensional array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> is nothing
but an array of arrays.  An assignment to such an array is typically written
something like <fr:tex
display="inline"><![CDATA[A[i,j] {:=} x]]></fr:tex>; in C, the syntax is <html:code>A[i][j] = x</html:code>. Higher
dimensions are treated analogously.  The corresponding OCaml code can either
declare an array of arrays, or use the <html:code>A.(i)</html:code> syntax to calculate the linear
offset into a single array.</html:p><html:p>You can use the constructs we have learnt to easily create linked (mutable) lists as
an alternative to arrays.</html:p><html:pre><![CDATA[# type 'a mlist =
  | Nil
  | Cons of 'a * 'a mlist ref
type 'a mlist = Nil | Cons of 'a * 'a mlist ref]]></html:pre><html:p>It is worth mentioning that OCaml’s references fully suffice for coding the sort of linked data structures
taught in algorithms courses, as the <html:code>mlist</html:code> type above illustrates. The
programming style is a little different from the usual, but the principles are
the same.  OCaml also provides comprehensive input/output primitives for various
types of file and operating system.</html:p><html:p>OCaml’s system of modules include <html:em>structures,</html:em> which can be seen as encapsulated
groups of declarations, and <html:em>signatures,</html:em> which are specifications of
structures listing the name and type of each component.  Finally, there are
<html:em>functors,</html:em> which are analogous to functions that combine a number of argument
structures, and which can be used to plug program components together. These
primitives are useful for managing large programming projects.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:uri><fr:display-uri>focs-funarray-lookup</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-lookup/</fr:route><fr:title
text="The Lookup Function">The Lookup Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Subscript
  let rec sub = function
  | Lf, _ -> raise Subscript  (* Not found *)
  | Br (v, t1, t2), k ->
      if k = 1 then v
      else if k mod 2 = 0 then
        sub (t1, k / 2)
      else
        sub (t2, k / 2)
exception Subscript
val sub : 'a tree * int -> 'a = <fun>
# let rec sub = function (* Alternative implementation *)
  | Lf, _ -> raise Subscript
  | Br (v, t1, t2), 1 -> v
  | Br (v, t1, t2), k when k mod 2 = 0 -> sub (t1, k / 2)
  | Br (v, t1, t2), k -> sub (t2, k / 2)
val sub : 'a tree * int -> 'a = <fun>]]></html:pre><html:p>Notice that we have used a new keyword <html:code>when</html:code> above, which changes
pattern clauses to be only matched if the expression evalutes to true.
This can be equivalently expressed by moving the corresponding
checks into an <html:code>if</html:code> clause on the right hand side of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern match</fr:link>,
but is often more readable using <html:code>when</html:code> (as above).</html:p><html:p>The lookup function <html:code>sub</html:code>, divides the subscript by 2 until 1 is
reached.  If the remainder is 0 then the function follows the left subtree,
otherwise the right.  If it reaches a leaf, it signals error by raising
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Subscript</html:code>.</html:p><html:p>Array access can also be understood in terms of the subscript’s binary code.
Because the subscript must be a positive integer, in binary it has a leading
one.  Discard this one and reverse the remaining bits.  Interpreting zero
as <html:em>left</html:em> and one as <html:em>right</html:em> yields the path from the root to the
subscript.</html:p><html:p>Popular literature often explains the importance of binary as being led by
hardware: because a circuit is either on or off.  The truth is almost the
opposite.  Designers of digital electronics go to a lot of trouble to suppress
the continuous behaviour that would naturally arise.  The real reason why
binary is important is its role in algorithms: an <html:code>if-then-else</html:code> decision leads
to binary branching.</html:p><html:p>Data structures, such as trees, and algorithms, such as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-merge-sort/"
title="Top-down Merge sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-merge-sort/"
display-uri="focs-merge-sort"
type="local">mergesort</fr:link>, use binary
branching in order to reduce a cost from <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex>.  Two is the
smallest integer divisor that achieves this reduction.  (Larger divisors are
only occasionally helpful, as in the case of B-trees, where they reduce the
constant factor.)  The simplicity of binary arithmetic compared with decimal
arithmetic is just another instance of the simplicity of algorithms based on
binary choices.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:uri><fr:display-uri>focs-funarray-update</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-funarray-update/</fr:route><fr:title
text="The Update Function">The Update Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec update = function
  | Lf, k, w ->
      if k = 1 then
        Br (w, Lf, Lf)
      else
        raise Subscript  (* Gap in tree *)
  | Br (v, t1, t2), k, w ->
      if k = 1 then
        Br (w, t1, t2)
      else if k mod 2 = 0 then
        Br (v, update (t1, k / 2, w), t2)
      else
        Br (v, t1, update (t2, k / 2, w))
val update : 'a tree * int * 'a -> 'a tree = <fun>]]></html:pre><html:p>The <html:code>update</html:code> function also divides the subscript repeatedly by two.  When it
reaches a value of one, it has identified the element position.  Then it
replaces the branch node by another branch with the new label.</html:p><html:p>A leaf may be replaced by a branch, extending the array, provided no
intervening nodes have to be generated.  This suffices for arrays without gaps
in their subscripting.  (The data structure can be modified to allow <html:em>sparse</html:em>
arrays, where most subscript positions are undefined.) Exception <fr:link
href="/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
title="The Lookup Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-funarray-lookup/"
display-uri="focs-funarray-lookup"
type="local"><html:code>Subscript</html:code></fr:link>
indicates that the subscript position does not exist and cannot be created.
This use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link> is not easily replaced by <html:code>None</html:code> and <html:code>Some</html:code>.</html:p><html:p>Note that there are two tests involving <fr:tex
display="inline"><![CDATA[k=1]]></fr:tex>.  If we have reached a leaf,
it returns a branch, extending the array by one.  If we are still at a branch
node, then the effect is to update an existing array element.</html:p><html:p>A similar function can <html:em>shrink</html:em> an array by one.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:uri><fr:display-uri>focs-ex-10-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:route><fr:title
text="Exercises › Array-based circular queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Array-based circular queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The traditional way to implement queues uses a fixed-length array. Two indices into the array
indicate the start and end of the queue, which wraps around from the end of the array to the start.
How appropriate is such a data structure for implementing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
title="Breadth-First v Depth-First Tree Traversal"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
display-uri="focs-bfs-dfs"
type="local">breadth-first search</fr:link>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:uri><fr:display-uri>focs-ex-11-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:route><fr:title
text="Exercises › Matrix operations on arrays"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Matrix operations on arrays</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Arrays of multiple dimensions are represented in OCaml by arrays of arrays. Write functions to
(a) create an <fr:tex
display="inline"><![CDATA[n\times  n]]></fr:tex> identity matrix, given <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, and
(b) to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local">transpose</fr:link> an <fr:tex
display="inline"><![CDATA[m\times  n]]></fr:tex> matrix. Identity matrices have the following form:</html:p><fr:tex
display="block"><![CDATA[
\left ( {
\begin {array}{cccc}
   1 & 0 &  \cdots   & 0  \\
   0 & 1 &  \cdots   & 0  \\
    \vdots   &  \vdots   &  \ddots   &  \vdots    \\
   0 & 0 &  \cdots   & 1  \\
 \end {array}
 } \right )
]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:uri><fr:display-uri>focs-ex-7-8</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-7-8/</fr:route><fr:title
text="Exercises › Shifting a functional array"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-7/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-7/"
display-uri="focs-ex-7"
type="local">Exercises</fr:link> › Shifting a functional array</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to remove the first element from a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional array</fr:link>. All the other elements are to
have their subscripts reduced by one. The cost of this operation should be linear in the size of the
array.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-higher-order-functions/</fr:uri><fr:display-uri>focs-topic-higher-order-functions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-higher-order-functions/</fr:route><fr:title
text="Higher order functions">Higher order functions</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:uri><fr:display-uri>focs-predicate-applications</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:route><fr:title
text="Applications of the Predicate Functionals">Applications of the Predicate Functionals</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let member y xs =
    exists (fun x -> x=y) xs
val member : 'a -> 'a list -> bool = <fun>
# let inter xs ys =
    filter (fun x -> member x ys) xs
val inter : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Testing whether two lists have no common elements</html:em></html:p><html:pre><![CDATA[# let disjoint xs ys =
    all (fun x -> all (fun y -> x<>y) ys) xs
val disjoint : 'a list -> 'a list -> bool = <fun>]]></html:pre><html:p>The Lists lecture presented the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link>, which tests whether a
specified value can be found as a list element, and <html:code>inter</html:code>, which returns the
“intersection” of two lists: the list of elements they have in common.</html:p><html:p>But remember: the purpose of list <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> is not to replace the
declarations of popular functions, which probably are available already.  It is
to eliminate the need for separate declarations of ad-hoc functions.  When they
are nested, like the calls to <html:code>all</html:code> in <html:code>disjoint</html:code> above, the
inner functions are almost certainly one-offs, not worth declaring separately.</html:p><html:p>Our primitives themselves can be seen as a programming language.  Part of the
task of programming is to extend our programming language with notation for
solving the problem at hand.  The levels of notation that we define should
correspond to natural <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">levels of abstraction</fr:link> in the problem domain.</html:p><html:p>Historical Note:
Alonzo Church’s <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus gave a simple syntax, <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-notation,
for expressing functions.  It is the direct precursor of OCaml’s
<html:code>fun</html:code>-notation.  It was soon shown that his system was equivalent in
computational power to Turing machines, and <html:em>Church’s thesis</html:em> states that
this defines precisely the set of functions that can be computed effectively.</html:p><html:p>The <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus had a tremendous influence on the design of functional
programming languages.  McCarthy’s Lisp was something of a false start; it
interpreted variable binding incorrectly, an error that stood for some 20
years.  But in 1966, Peter Landin (of Queen Mary College, University of London)
sketched out the main features of functional languages.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/</fr:uri><fr:display-uri>focs-currying</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-currying/</fr:route><fr:title
text="Curried Functions">Curried Functions</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>curried function</html:em> returns another function as its result. We use
the string concatenation operator <html:code>(^)</html:code> to illustrate how this works.</html:p><html:pre><![CDATA[# (^)
- : string -> string -> string = <fun>
# let prefix = fun a -> fun b -> a ^ b
val prefix : string -> string -> string = <fun>
# let promote = prefix "Senior "
val promote : string -> string = <fun>
# prefix "Junior " "Professor"
- : string = "Junior Professor"
# promote "Professor"
- : string = "Senior Professor"]]></html:pre><html:p>A short form for the definition of <html:code>prefix</html:code> is simply to pass multiple
arguments to the function definition.  The following two definitions
are equivalent in OCaml:</html:p><html:pre><![CDATA[# let prefix = fun a -> fun b -> a ^ b
val prefix : string -> string -> string = <fun>
# let prefix a b = a ^ b
val prefix : string -> string -> string = <fun>]]></html:pre><html:p>Currying is the technique of expressing a function taking multiple arguments as nested functions, each taking a single argument.
The <html:code>fun</html:code>-notation lets us package <html:code>n*2</html:code> as the function
<html:code>fun n -&gt; n * 2</html:code>, but what if there are several variables, as in
<html:code>fun n -&gt; n * 2 + k</html:code>?  A function of two arguments could be coded using
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link> on pairs, writing <html:code>fun (n, k) -&gt; n * 2 + k</html:code>.</html:p><html:p>Currying is an alternative, where we <html:em>nest</html:em> the <html:code>fun</html:code>-notation:</html:p><html:pre><![CDATA[# fun k -> fun n -> n * 2 + k
- : int -> int -> int = <fun>]]></html:pre><html:p>Applying this curried function to the argument 1 yields another function, in which <html:code>k</html:code> has been replaced by 1:</html:p><html:pre><![CDATA[# let fn = fun k -> fun n -> n * 2 + k
val fn : int -> int -> int = <fun>
# let fn' = fn 1 (* n * 2 + 1 *)
val fn' : int -> int = <fun>
# fn' 3  (* 3 * 2 + 1 *)
- : int = 7]]></html:pre><html:p>And this function, when applied to 3, yields the result 7. The two arguments are supplied one after another.</html:p><html:p>The earlier <html:code>prefix</html:code> example is similar and uses the expression <html:code>a ^ b</html:code>,
where <html:code>^</html:code> is the infix operator for string concatenation. Function <html:code>promote</html:code> binds the first argument of <html:code>prefix</html:code> to
<html:code>"Senior "</html:code>; the resulting function prefixes that title
to any string to which it is applied.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/</fr:uri><fr:display-uri>focs-def-currying</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-currying/</fr:route><fr:title
text="Currying">Currying</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Currying is the technique of expressing a function taking multiple arguments
as nested functions, each taking a single argument. A <html:em>curried function</html:em>
returns another function as its result, so the arguments are supplied one after
another.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-currying/"
title="Curried Functions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/"
display-uri="focs-currying"
type="local">Curried Functions</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/</fr:uri><fr:display-uri>focs-transpose</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-transpose/</fr:route><fr:title
text="Example: Matrix Transpose">Example: Matrix Transpose</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {pmatrix}
           a   & b & c \\
           d   & e & f
   \end {pmatrix}^T =
   \begin {pmatrix}
        a & d     \\
        b & e     \\
        c & f
\end {pmatrix}
]]></fr:tex><html:pre><![CDATA[# let rec transp = function
    | []::_ -> []
    | rows -> (map List.hd rows) ::
              (transp (map List.tl rows))
val transp : 'a list list -> 'a list list = <fun>]]></html:pre><html:p>A matrix can be viewed as a list of rows, each row a list of matrix elements.
This representation is not especially efficient compared with the conventional
one (using arrays).  Lists of lists turn up often, though, and we can see how
to deal with them by taking familiar matrix operations as examples.
<html:em>ML for the Working Programmer</html:em> goes as far as Gaussian elimination,
which presents surprisingly few difficulties.</html:p><html:p>The transpose of the matrix
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix} a & b & c \\
                           d & e & f\end {smallmatrix}\right )]]></fr:tex>
is
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix}
        a & d     \\
        b & e     \\
        c & f
   \end {smallmatrix}\right )]]></fr:tex>,
which in OCaml corresponds to the following transformation on lists of lists:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {[[a; b; c]; [d; e; f]]} \Rightarrow & \text { [[a; d]; [b; e]; [c; f]]}
\end {aligned}
]]></fr:tex><html:p>The workings of function <html:code>transp</html:code> are simple.  If <html:code>rows</html:code> is the
matrix to be transposed, then <html:code>map hd</html:code> extracts its first column and
<html:code>map tl</html:code> extracts its second column:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {map hd rows} \Rightarrow  & \text { [a; d]}\\
\text {map tl rows} \Rightarrow  & \text { [[b; c]; [e; f]]}
\end {aligned}
]]></fr:tex><html:p>A recursive call transposes the latter matrix, which is then given the column
<html:code>[a; d]</html:code> as its first row.
The two functions expressed using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> would otherwise have to be declared
separately.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-functionals/</fr:uri><fr:display-uri>focs-seq-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-functionals/</fr:route><fr:title
text="Functionals for Lazy Lists">Functionals for Lazy Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Filtering <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>:</html:p><html:pre><![CDATA[# let rec filterq p = function
  | Nil -> Nil
  | Cons (x, xf) ->
      if p x then
        Cons (x, fun () -> filterq p (xf ()))
      else
        filterq p (xf ())
val filterq : ('a -> bool) -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>The infinite sequence <fr:tex
display="inline"><![CDATA[x]]></fr:tex>, <fr:tex
display="inline"><![CDATA[f(x)]]></fr:tex>, <fr:tex
display="inline"><![CDATA[f(f(x))]]></fr:tex>, …</html:p><html:pre><![CDATA[# let rec iterates f x =
    Cons (x, fun () -> iterates f (f x))
val iterates : ('a -> 'a) -> 'a -> 'a seq = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>filterq</html:code> demands elements of <html:code>xq</html:code> until it finds
one satisfying <html:code>p</html:code>.  (Recall <fr:link
href="/teaching/2627/FoundsCS/forest/focs-predicate-functionals/"
title="List Functionals for Predicates"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/"
display-uri="focs-predicate-functionals"
type="local"><html:code>filter</html:code></fr:link>, the analogous operation for ordinary lists.)  It
contains a <html:em>force</html:em> not protected by a <html:em>delay</html:em>.  If <html:code>xq</html:code> is
infinite and contains no satisfactory element, then <html:code>filterq</html:code> runs
forever.</html:p><html:p>The functional <html:code>iterates</html:code> generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-infinite-sequence/"
title="The Infinite Sequence: k, k+1, k+2, …"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-infinite-sequence/"
display-uri="focs-infinite-sequence"
type="local"><html:code>from</html:code></fr:link>.  It creates the
next element not by adding one but by calling the function <html:code>f</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-anonymous-functions/</fr:uri><fr:display-uri>focs-anonymous-functions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-anonymous-functions/</fr:route><fr:title
text="Functions Without Names">Functions Without Names</fr:title></fr:frontmatter><fr:mainmatter><html:p>If functions are to be regarded as computational values, then we need a
notation for them.  The <html:code>fun</html:code> notation expresses a non-recursive function
value without giving the function a name.</html:p><html:p><fr:tex
display="inline"><![CDATA[\tt  fun\;x\;\rightarrow  E]]></fr:tex> is the function <fr:tex
display="inline"><![CDATA[f]]></fr:tex> such that <fr:tex
display="inline"><![CDATA[f(x)=E]]></fr:tex>.
The function <html:code>fun n -&gt; n*2</html:code> is a <html:em>doubling function</html:em>.</html:p><html:pre><![CDATA[# fun n -> n * 2
- : int -> int = <fun>
# (fun n -> n * 2) 17
- : int = 34]]></html:pre><html:p>The main purpose of <html:code>fun</html:code>-notation is to package up small expressions that are to be
applied repeatedly using some other function.
The expression <html:code>fun n -&gt; n*2</html:code> has the same value as the identifier
<html:code>double</html:code>, declared as follows:</html:p><html:pre><![CDATA[# let double n = n * 2
val double : int -> int = <fun>]]></html:pre><html:p>The <html:code>fun</html:code> notation can also do <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matching</fr:link>, and the <html:code>function</html:code> keyword
adds an anonymous variable name to pattern match against.  The following functions
are all equivalent, with the latter definitions bound to the <html:code>is_zero</html:code> value and the earlier ones anonymous:</html:p><html:pre><![CDATA[# fun x -> match x with 0 -> true | _ -> false
- : int -> bool = <fun>
# function 0 -> true | _ -> false
- : int -> bool = <fun>
# let is_zero = fun x -> match x with 0 -> true | _ -> false
val is_zero : int -> bool = <fun>
# let is_zero = function 0 -> true | _ -> false
val is_zero : int -> bool = <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/</fr:uri><fr:display-uri>focs-def-higher-order-function</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/</fr:route><fr:title
text="Higher-order function">Higher-order function</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>In mathematics, a <html:em>functional</html:em> or <html:em>higher-order function</html:em> is a function
that operates on other functions. In OCaml, functions can be passed as arguments
to other functions, returned as results, and put into lists, trees and so on—but
<html:em>not</html:em> tested for equality.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functions/"
title="Functions as Values"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/"
display-uri="focs-functions"
type="local">Functions as Values</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:uri><fr:display-uri>focs-predicate-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:route><fr:title
text="List Functionals for Predicates">List Functionals for Predicates</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec exists p = function
  | [] -> false
  | x::xs -> (p x) || (exists p xs)
val exists : ('a -> bool) -> 'a list -> bool = <fun>
# let rec filter p = function
  | [] -> []
  | x::xs ->
      if p x then
        x :: filter p xs
      else
        filter p xs
val filter : ('a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>A <html:em>predicate</html:em> is a <html:em>boolean-valued</html:em> function.</html:p><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>exists</html:code> transforms a predicate into a predicate over
lists.  Given a list, <html:code>exists p</html:code> tests whether or not some list element
satisfies <html:code>p</html:code> (making it return <html:code>true</html:code>).  If it finds one, it stops
searching immediately, thanks to the behaviour of the lazy <html:code>||</html:code> operator.</html:p><html:p>Dually, we have a functional to test whether all list elements satisfy the
predicate.  If it finds a counterexample then it, too, stops searching.</html:p><html:pre><![CDATA[# let rec all p = function
  | [] -> true
  | x::xs -> (p x) && all p xs
val all : ('a -> bool) -> 'a list -> bool = <fun>]]></html:pre><html:p>The <html:code>filter</html:code> functional, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>, transforms lists.  It applies a
predicate to all the list elements, but instead of returning the
resulting values (which could only be <html:code>true</html:code> or <html:code>false</html:code>), it returns
the list of elements satisfying the predicate.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:uri><fr:display-uri>focs-matmul-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:route><fr:title
text="Matrix Multiplication in OCaml">Matrix Multiplication in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:p><html:em>Dot product</html:em> of two vectors—a <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link></html:em></html:p><html:pre><![CDATA[# let rec dotprod xs ys =
    match xs, ys with
    | [], [] -> 0.0
    | x::xs, y::ys ->  (x *. y) +. (dotprod xs ys)
Lines 2-4, characters 5-51:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
([], _::_)

val dotprod : float list -> float list -> float = <fun>]]></html:pre><html:p><html:em>Matrix product</html:em></html:p><html:pre><![CDATA[# let rec matprod arows brows =
    let cols = transp brows in
    map (fun row -> map (dotprod row) cols) arows
val matprod : float list list -> float list list -> float list list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local"><html:code>transp brows</html:code></fr:link> converts <fr:tex
display="inline"><![CDATA[B]]></fr:tex> into a list of columns, yielding a
list whose elements are the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Each row of <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is
obtained by multiplying a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><html:p>Because <html:code>dotprod</html:code> is curried, it can be applied to a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The
resulting function is applied to all the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  We have another
example of currying and partial application.</html:p><html:p>The outer <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> applies <html:code>dotprod</html:code> to each row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The inner
<html:code>map</html:code>, using <html:code>fun</html:code>-notation, applies <html:code>dotprod row</html:code> to each
column of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Compare with the version in <html:em>ML for the Working
  Programmer</html:em> (page 89) which does not use <html:code>map</html:code> and requires two
additional function declarations.</html:p><html:p>In the dot product function, the two vectors must have the same length.
Otherwise, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Match_failure</html:code> is raised.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-numerical/</fr:uri><fr:display-uri>focs-seq-numerical</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-numerical/</fr:route><fr:title
text="Numerical Computations on Infinite Sequences">Numerical Computations on Infinite Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let next a x = (a /. x +. x) /. 2.0
val next : float -> float -> float = <fun>]]></html:pre><html:p>Close enough?</html:p><html:pre><![CDATA[# let rec within eps = function
  | Cons (x, xf) ->
      match xf () with
      | Cons (y, yf) ->
          if abs_float (x -. y) <= eps then y
          else within eps (Cons (y, yf))
Lines 3-6, characters 7-41:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

Lines 1-6, characters 22-41:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val within : float -> float seq -> float = <fun>]]></html:pre><html:p>Square Roots:</html:p><html:pre><![CDATA[# let root a = within 1e-6 (iterates (next a) 1.0)
val root : float -> float = <fun>]]></html:pre><html:p>The <html:em>Newton-Raphson method</html:em> is widely used for computing square roots.
The infinite series <fr:tex
display="inline"><![CDATA[x_0, (a/x_0+x_0)/2, \ldots {}]]></fr:tex> converges rapidly to <fr:tex
display="inline"><![CDATA[\sqrt {a}]]></fr:tex>.
The initial approximation, <fr:tex
display="inline"><![CDATA[x_0]]></fr:tex>, is typically retrieved from a table, and is accurate enough
that only a few iterations of the method are necessary.
Calling <html:code>iterates (next a) x0</html:code> generates the <html:em>infinite series</html:em> of
approximations to the square root of <fr:tex
display="inline"><![CDATA[a]]></fr:tex> using the Newton-Raphson method.
To compute <fr:tex
display="inline"><![CDATA[\sqrt 2]]></fr:tex>, the resulting series begins 1, 1.5, 1.41667, 1.4142157, 1.414213562, …,
and this last figure is already accurate to 10 significant digits!</html:p><html:p>Function <html:code>within</html:code> searches down the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy list</fr:link> for two points whose
difference is less than <html:code>eps</html:code>.  It tests their absolute difference.
Relative difference and other “close enough” tests can be coded.  Such
components can be used to implement other numerical functions directly as
functions over sequences.  The point is to build programs from small,
interchangeable parts.</html:p><html:p>Function <html:code>root</html:code> uses <html:code>within</html:code>, <html:code>iterates</html:code> and <html:code>next</html:code> to
to apply Newton-Raphson with a tolerance of <fr:tex
display="inline"><![CDATA[10^{-6}]]></fr:tex>
and a (poor) initial approximation of 1.0.</html:p><html:pre><![CDATA[# root 2.0;;
- : float = 1.41421356237309492]]></html:pre><html:p>This treatment of numerical computation has received some attention in the
research literature; a recurring example is Richardson extrapolation.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/</fr:uri><fr:display-uri>focs-partial-application</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-partial-application/</fr:route><fr:title
text="Partial Application: A Curried Insertion Sort">Partial Application: A Curried Insertion Sort</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let insort lessequal =
    let rec ins x = function
      | [] -> [x]
      | y::ys -> if lessequal x y then x :: y :: ys
                 else y :: ins x ys
    in
    let rec sort = function
      | [] -> []
      | x::xs -> ins x (sort xs)
    in
    sort
val insort : ('a -> 'a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sorting/"
title="Sorting"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sorting/"
display-uri="focs-sorting"
type="local">sorting functions</fr:link> we discussed in earlier lectures are coded to sort floating-point
numbers.  They can be generalised to an arbitrary ordered type by passing the
ordering predicate <html:code>lessequal</html:code> as an argument.</html:p><html:p>Functions <html:code>ins</html:code> and <html:code>sort</html:code> are declared locally, referring to <html:code>lessequal</html:code>.
Though it may not be obvious, <html:code>insort</html:code> is a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link>.  Given its first
argument, a predicate for comparing some particular type of items, it returns
the function <html:code>sort</html:code> for sorting lists of that type of items.</html:p><html:p>Some examples of its use:</html:p><html:pre><![CDATA[# insort (<=) [5; 3; 9; 8]
- : int list = [3; 5; 8; 9]
# insort (<=) ["bitten"; "on"; "a"; "bee"]
- : string list = ["a"; "bee"; "bitten"; "on"]
# insort (>=) [5; 3; 9; 8]
- : int list = [9; 8; 5; 3]]]></html:pre><html:p>An obscure point: the syntax <html:code>(&lt;=)</html:code> denotes the comparison operator as a
function, which is then given to <html:code>insort</html:code>.  Passing the relation <fr:tex
display="inline"><![CDATA[\geq ]]></fr:tex> for
<html:code>lessequal</html:code> gives a decreasing sort.  This is no coding trick; it is justified
in mathematics, since if <fr:tex
display="inline"><![CDATA[\leq ]]></fr:tex> is a partial ordering then so is <fr:tex
display="inline"><![CDATA[\geq ]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/</fr:uri><fr:display-uri>focs-private-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-private-references/</fr:route><fr:title
text="Private, Persistent References">Private, Persistent References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception TooMuch of int
exception TooMuch of int
# let makeAccount initBalance =
    let balance = ref initBalance in
    let withdraw amt =
       if amt > !balance then
         raise (TooMuch (amt - !balance))
       else begin
         balance := !balance - amt;
         !balance
       end
    in
    withdraw
val makeAccount : int -> int -> int = <fun>]]></html:pre><html:p>As you may have noticed, OCaml’s programming style looks clumsy compared with
that of languages like C.  OCaml omits the defaults and abbreviations they
provide to shorten programs.  However, OCaml’s explicitness makes it ideal for
teaching the fine points of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> and arrays.  OCaml’s references are more
flexible than those found in other languages.</html:p><html:p>The function <html:code>makeAccount</html:code> models a bank.  Calling the function with a
specified initial balance creates a new reference (<html:code>balance</html:code>) to
maintain the account balance and returns a function (<html:code>withdraw</html:code>) having
sole access to that reference.  Calling <html:code>withdraw</html:code> reduces the balance
by the specified amount and returns the new balance.  You can pay money in by
withdrawing a negative amount.  The <html:code>if</html:code>-construct prevents the account
from going overdrawn, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">raising an exception</fr:link>.</html:p><html:p>Look at the <fr:tex
display="inline"><![CDATA[E_1; E_2]]></fr:tex> sequence inside <html:code>begin</html:code> … <html:code>end</html:code> in the <html:em>else</html:em> part above.
The first expression updates the account balance and returns the trivial
value ().  The second expression, <html:code>!balance</html:code>, returns the current
balance but does not return the reference itself: that would allow
unauthorised updates.</html:p><html:p>This example is based on one by Dr A C Norman.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-curry-shorthand/</fr:uri><fr:display-uri>focs-curry-shorthand</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-curry-shorthand/</fr:route><fr:title
text="Shorthand for Curried Functions">Shorthand for Curried Functions</fr:title></fr:frontmatter><fr:mainmatter><html:p>A function-returning function is just a function of two arguments.</html:p><html:p>This <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link> syntax is nicer than nested <html:code>fun</html:code> binders:</html:p><html:pre><![CDATA[# let prefix a b = a ^ b
val prefix : string -> string -> string = <fun>
# let dub = prefix "Sir "
val dub : string -> string = <fun>]]></html:pre><html:p>Curried functions allows <html:em>partial application</html:em> (to the first argument).</html:p><html:p>In OCaml, an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-argument curried function <html:code>f</html:code> can be declared using the syntax:</html:p><fr:tex
display="block"><![CDATA[\tt  let \; f \; x_1 \: \ldots  \: x_{n} \: = \: E]]></fr:tex><html:p>and applied using the syntax:</html:p><fr:tex
display="block"><![CDATA[\tt  \; E_1 \; \ldots  \; E_n]]></fr:tex><html:p>If <html:code>f</html:code> is not recursive, then it is equivalent to the function expressed via nesting as follows:</html:p><fr:tex
display="block"><![CDATA[\tt  fun \; x_1 \; \rightarrow  \cdots  \rightarrow  fun \; x_{n} \rightarrow  E ]]></fr:tex><html:p>We now have two ways of expressing functions of multiple arguments: either by
passing a pair of arguments or by currying.  Currying allows <html:em>partial application</html:em>
which is useful when fixing the first argument yields a function
that is interesting in its own right.  An example from mathematics is the
function <fr:tex
display="inline"><![CDATA[x^y]]></fr:tex>, where fixing <fr:tex
display="inline"><![CDATA[y=2]]></fr:tex> yields a function in <fr:tex
display="inline"><![CDATA[x]]></fr:tex> alone, namely
squaring. Similarly, <fr:tex
display="inline"><![CDATA[y=3]]></fr:tex> yields cubing, while <fr:tex
display="inline"><![CDATA[y=1]]></fr:tex> yields the identity
function.</html:p><html:p>Though the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local"><html:code>hd</html:code></fr:link> (which returns the head of a list) is not
curried, it may be used with the curried application syntax in some
expressions:</html:p><html:pre><![CDATA[# List.hd [dub; promote] "Hamilton"
- : string = "Sir Hamilton"]]></html:pre><html:p>Here <html:code>List.hd</html:code> is applied to a list of functions, and the resulting function
<html:code>dub</html:code> is then applied to the string <html:code>"Hamilton"</html:code>.  The idea of
executing code stored in data structures reaches its full development in
<html:em>object-oriented</html:em> programming, like in Java.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bank-accounts/</fr:uri><fr:display-uri>focs-bank-accounts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bank-accounts/</fr:route><fr:title
text="Two Bank Accounts">Two Bank Accounts</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let student = makeAccount 500
val student : int -> int = <fun>
# let director = makeAccount 4000000
val director : int -> int = <fun>
# student 5        (* coach fare *)
- : int = 495
# director 150000  (* Tesla *)
- : int = 3850000
# student 500      (* oh oh *)
Exception: TooMuch 5.]]></html:pre><html:p>Each call to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>makeAccount</html:code></fr:link> returns a copy of <html:code>withdraw</html:code> holding
a <html:em>fresh</html:em> instance of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference</fr:link> <html:code>balance</html:code>.  As with a real bank
pass-book, there is no access to the account balance except via the
corresponding <html:code>withdraw</html:code> function.  If that function is discarded, the
reference cell becomes unreachable; the computer will eventually reclaim it,
just as banks close down dormant accounts.</html:p><html:p>Here we see two people managing their accounts.  For better or worse, neither
can take money from the other.</html:p><html:p>We could generalise <html:code>makeAccount</html:code> to return several functions that
jointly manage information held in shared references.  The functions might be
packaged using OCaml records, which are not discussed in this course.
Most procedural languages do not properly support the concept of private
references, although <html:em>object-oriented</html:em> languages take them as a basic theme.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/</fr:uri><fr:display-uri>focs-map</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-map/</fr:route><fr:title
text="map: the “Apply to All” Function">map: the “Apply to All” Function</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec map f = function
    | [] -> []
    | x::xs -> (f x) :: map f xs
val map : ('a -> 'b) -> 'a list -> 'b list = <fun>
# map (fun s -> s ^ "ppy") ["Hi"; "Ho"]
- : string list = ["Hippy"; "Hoppy"]
# map (map double) [[1]; [2; 3]]
- : int list list = [[2]; [4; 6]]]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>map</html:code> applies a function to every element of a list,
returning a list of the function’s results.  “Apply to all” is a fundamental
operation and we shall see several applications of it below.  We
again see the advantages of <html:code>fun</html:code>-notation, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">currying</fr:link> and
<html:code>map</html:code>.  If we did not have them, the first use of <html:code>map</html:code> in the above code block
would require a preliminary function declaration:</html:p><html:pre><![CDATA[# let rec sillylist = function
    | [] -> []
    | s::ss -> (s ^ "ppy") :: sillylist ss
val sillylist : string list -> string list = <fun>]]></html:pre><html:p>An expression containing several applications of functionals—such as our
second example—can abbreviate a long series of declarations.  Sometimes this
coding style is cryptic, but it can be clear as crystal.  Treating functions
as values lets us capture common program structures once and for all.</html:p><html:p>In the second example, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-anonymous-functions/"
title="Functions Without Names"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-anonymous-functions/"
display-uri="focs-anonymous-functions"
type="local"><html:code>double</html:code></fr:link> is the obvious integer doubling function we
defined earlier.  Note that <html:code>map</html:code> is a built-in OCaml function in the
form of <html:code>List.map</html:code>.  OCaml’s standard library includes, among much else, many
list functions.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:uri><fr:display-uri>focs-ex-8-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-4/</fr:route><fr:title
text="Exercises › A map for options"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › A map for options</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The type <html:code>'a option</html:code>, declared below, can be viewed as a type of lists having at most one element.
(It is typically used as an alternative to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">exceptions</fr:link>.) Declare an analogue of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>
for type <html:code>'a option</html:code>.</html:p><html:pre><![CDATA[type 'a option = None | Some of 'a]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:uri><fr:display-uri>focs-ex-9-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:route><fr:title
text="Exercises › A map for sequences"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › A map for sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an analogue of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> for sequences.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:uri><fr:display-uri>focs-ex-8-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-2/</fr:route><fr:title
text="Exercises › Lexicographic orderings"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Lexicographic orderings</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>There are many ways of combining orderings. The <html:code>lexicographic ordering</html:code> uses two keys for
comparisons. It is specified by</html:p><fr:tex
display="block"><![CDATA[(x',y')<(x,y)\iff  x'<x \vee  (x'=x \wedge  y'<y).]]></fr:tex><html:p>Write an OCaml function to lexicographically combine two orderings, supplied as functions. Explain
how it allows function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-partial-application/"
title="Partial Application: A Curried Insertion Sort"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-partial-application/"
display-uri="focs-partial-application"
type="local"><html:code>insort</html:code></fr:link> to sort a list of pairs.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:uri><fr:display-uri>focs-ex-8-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-5/</fr:route><fr:title
text="Exercises › Making change with map"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Making change with map</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Recall the making change function of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">More on Lists</fr:link>:</html:p><html:pre><![CDATA[# let rec change till amt =
    match till, amt with
    | _       , 0   -> [ [] ]
    | []      , _   -> []
    | c::till , amt -> if amt < c then change till amt
                      else let rec allc = function
                             | [] -> []
                             | cs :: css -> (c::cs) :: allc css
                           in
                             allc (change (c::till) (amt - c)) @
                                   change till amt
val change : int list -> int -> int list list = <fun>]]></html:pre><html:p>Function <html:code>allc</html:code> applies the function ‘cons a <html:code>c</html:code>’ to every element of a list. Eliminate it by
declaring a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried</fr:link> cons function and applying <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:uri><fr:display-uri>focs-ex-8-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-3/</fr:route><fr:title
text="Exercises › Mapping over lists of lists"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › Mapping over lists of lists</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Without using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> write a function <html:code>map2</html:code> such that <html:code>map2 f</html:code> is equivalent to <html:code>map (map f)</html:code>. The
obvious solution requires declaring two recursive functions. Try to get away with only one by
exploiting nested <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8-1/</fr:uri><fr:display-uri>focs-ex-8-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-8-1/</fr:route><fr:title
text="Exercises › The argument-swapping functional"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-8/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-8/"
display-uri="focs-ex-8"
type="local">Exercises</fr:link> › The argument-swapping functional</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What does the following function do, and what are its uses?</html:p><html:pre><![CDATA[let sw f x y = f y x]]></html:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-laziness/</fr:uri><fr:display-uri>focs-topic-laziness</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-laziness/</fr:route><fr:title
text="Laziness">Laziness</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-pipeline/</fr:uri><fr:display-uri>focs-pipeline</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-pipeline/</fr:route><fr:title
text="A Pipeline">A Pipeline</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\fbox {\textit {Producer}} \to  \fbox {\textit {Filter}} \to \cdots \to 
 \fbox {\textit {Filter}} \to  \fbox {\textit {Consumer}}
]]></fr:tex><html:ul><html:li>Produce sequence of items</html:li>
  <html:li>Filter sequence in stages</html:li>
  <html:li>Consume results as needed</html:li>
  <html:li><html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">Lazy lists</fr:link></html:em> join the stages together</html:li></html:ul><html:p>Two types of program can be distinguished.  A sequential program
accepts a problem to solve, processes for a while, and finally terminates
with its result.  A typical example is the huge numerical simulations that are
run on supercomputers.  Most of our OCaml functions also fit this model.</html:p><html:p>At the other extreme are <html:em>reactive</html:em> programs, whose job is to interact
with the environment.  They communicate constantly during their operation and
run for as long as is necessary.  A typical example is the software that
controls many modern aircraft.  Reactive programs often consist of
<html:em>concurrent processes</html:em> running at the same time and communicating with
one another.</html:p><html:p>Concurrency is too difficult to consider in this course, but we can model
simple pipelines such as that shown above.  The <html:em>Producer</html:em> represents one
or more sources of data, which it outputs as a stream.  The <html:em>Filter</html:em>
stages convert the input stream to an output stream, perhaps consuming several
input items to yield a single output item.  The <html:em>Consumer</html:em> takes as many
elements as necessary.</html:p><html:p>The Consumer drives the pipeline: nothing is computed except in response to
its demand for an additional datum.  Execution of the Filter stages is
interleaved as required for the computation to go through.  The programmer
sets up the data dependencies but has no clear idea of what happens when.  We
have the illusion of concurrent computation.</html:p><html:p>The Unix operating system provides similar ideas through its <html:em>pipes</html:em> that
link processes together.  In OCaml, we can model pipelines using <html:em>lazy lists</html:em>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:uri><fr:display-uri>focs-seq-consume</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-consume/</fr:route><fr:title
text="Consuming a Sequence">Consuming a Sequence</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec get n s =
    match n, s with
    | 0, _            -> []
    | n, Nil          -> []
    | n, Cons (x, xf) -> x :: get (n-1) (xf ())
val get : int -> 'a seq -> 'a list = <fun>]]></html:pre><html:p>The above code gets the first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements as a list.
<html:code>xf ()</html:code> <html:em>forces</html:em> evaluation.</html:p><html:p>The function <html:code>get</html:code> converts a sequence to a list.  It takes the
first <fr:tex
display="inline"><![CDATA[n]]></fr:tex> elements; it takes all of them if <fr:tex
display="inline"><![CDATA[n<0]]></fr:tex>, which can terminate only if
the sequence is finite.</html:p><html:p>In the last line of <html:code>get</html:code>, the expression <html:code>xf()</html:code> calls the tail
function, demanding evaluation of the next element.  This operation is called
<html:em>forcing</html:em> the sequence.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-functionals/</fr:uri><fr:display-uri>focs-seq-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-functionals/</fr:route><fr:title
text="Functionals for Lazy Lists">Functionals for Lazy Lists</fr:title></fr:frontmatter><fr:mainmatter><html:p>Filtering <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>:</html:p><html:pre><![CDATA[# let rec filterq p = function
  | Nil -> Nil
  | Cons (x, xf) ->
      if p x then
        Cons (x, fun () -> filterq p (xf ()))
      else
        filterq p (xf ())
val filterq : ('a -> bool) -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>The infinite sequence <fr:tex
display="inline"><![CDATA[x]]></fr:tex>, <fr:tex
display="inline"><![CDATA[f(x)]]></fr:tex>, <fr:tex
display="inline"><![CDATA[f(f(x))]]></fr:tex>, …</html:p><html:pre><![CDATA[# let rec iterates f x =
    Cons (x, fun () -> iterates f (f x))
val iterates : ('a -> 'a) -> 'a -> 'a seq = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>filterq</html:code> demands elements of <html:code>xq</html:code> until it finds
one satisfying <html:code>p</html:code>.  (Recall <fr:link
href="/teaching/2627/FoundsCS/forest/focs-predicate-functionals/"
title="List Functionals for Predicates"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/"
display-uri="focs-predicate-functionals"
type="local"><html:code>filter</html:code></fr:link>, the analogous operation for ordinary lists.)  It
contains a <html:em>force</html:em> not protected by a <html:em>delay</html:em>.  If <html:code>xq</html:code> is
infinite and contains no satisfactory element, then <html:code>filterq</html:code> runs
forever.</html:p><html:p>The functional <html:code>iterates</html:code> generalises <fr:link
href="/teaching/2627/FoundsCS/forest/focs-infinite-sequence/"
title="The Infinite Sequence: k, k+1, k+2, …"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-infinite-sequence/"
display-uri="focs-infinite-sequence"
type="local"><html:code>from</html:code></fr:link>.  It creates the
next element not by adding one but by calling the function <html:code>f</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:uri><fr:display-uri>focs-seq-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-append/</fr:route><fr:title
text="Joining Two Sequences">Joining Two Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec appendq xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons(x, fun () -> appendq (xf ()) yq)
val appendq : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>A more fair alternative:</html:p><html:pre><![CDATA[# let rec interleave xq yq =
    match xq with
    | Nil -> yq
    | Cons (x, xf) -> Cons (x, fun () -> interleave yq (xf ()))
val interleave : 'a seq -> 'a seq -> 'a seq = <fun>]]></html:pre><html:p>Most list functions and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> have analogues on sequences, but strange
things can happen.  Can an infinite list be reversed?</html:p><html:p>Function <html:code>appendq</html:code> is precisely the same idea as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>
from the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">Lists lecture</fr:link>; it concatenates two sequences.  If the first
argument is infinite, then <html:code>appendq</html:code> never gets to its second argument,
which is lost.  Concatenation of infinite sequences is not terribly
interesting.</html:p><html:p>The function <html:code>interleave</html:code> avoids this problem by exchanging the two
arguments in each recursive call.  It combines the two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, losing no
elements.  Interleaving is the right way to combine two potentially infinite
information sources into one.</html:p><html:p>In both function declarations, observe that each <html:code>xf ()</html:code> is enclosed
within a <fr:tex
display="inline"><![CDATA[{\tt  fun () \rightarrow  \ldots }]]></fr:tex>.  Each <html:em>force</html:em> is enclosed within a
<html:em>delay</html:em>.  This practice makes the functions lazy.  A force not enclosed
in a delay, as in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-seq-consume/"
title="Consuming a Sequence"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-consume/"
display-uri="focs-seq-consume"
type="local"><html:code>get</html:code></fr:link> above, runs the risk of evaluating the sequence
in full.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-lists/</fr:uri><fr:display-uri>focs-lazy-lists</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-lists/</fr:route><fr:title
text="Lazy Lists (or Streams)">Lazy Lists (or Streams)</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Lists of possibly <html:em>infinite</html:em> length</html:li>
  <html:li>Elements <html:em>computed upon demand</html:em></html:li>
  <html:li><html:em>Avoids waste</html:em> if there are many solutions</html:li>
  <html:li><html:em>Infinite</html:em> values are a useful abstraction</html:li></html:ul><html:p>In OCaml, we can implement laziness by <html:em>delaying evaluation</html:em> of the tail of
the list.</html:p><html:p>Lazy lists have practical uses.  Some algorithms, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>, can
yield many solutions when only a few are required.  Sometimes the original
problem concerns infinite series: with lazy lists, we can pretend they really
exist!</html:p><html:p>We are now dealing with <html:em>infinite</html:em> (or at least unbounded) computations.
A potentially infinite source of data is processed one element at a time, upon
demand.  Such programs are harder to understand than terminating ones and have
more ways of going wrong.</html:p><html:p>Some purely functional languages, such as Haskell, use lazy evaluation
everywhere.  Even the if-then-else construct can be a function, and all lists
are lazy.  In OCaml, we can declare a type of lists such that evaluation of the
tail does not occur until demanded.  <html:em>Delayed</html:em> evaluation is weaker than
<html:em>lazy</html:em> evaluation, but it is good enough for our purposes and often the
best compromise for performance and memory usage.</html:p><html:p>The traditional word “stream” is reserved in OCaml parlance for
input/output channels.  Let us call lazy lists <html:em>sequences</html:em> instead.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:uri><fr:display-uri>focs-lazy-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:route><fr:title
text="Lazy Lists in OCaml">Lazy Lists in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>The empty tuple <html:code>()</html:code> and its <html:em>type</html:em> <html:code>unit</html:code></html:li>
  <html:li>Delayed version of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> is <html:code>fun () -&gt; E</html:code></html:li></html:ul><html:pre><![CDATA[# type 'a seq =
  | Nil
  | Cons of 'a * (unit -> 'a seq)
type 'a seq = Nil | Cons of 'a * (unit -> 'a seq)
# let head (Cons (x, _)) = x
Line 1, characters 10-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val head : 'a seq -> 'a = <fun>
# let tail (Cons (_, xf)) = xf ()
Line 1, characters 10-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val tail : 'a seq -> 'a seq = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[\tt  Cons(x, xf)]]></fr:tex> has <html:em>head</html:em> <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and <html:em>tail function</html:em> <fr:tex
display="inline"><![CDATA[xf]]></fr:tex></html:p><html:p>The primitive OCaml type <html:code>unit</html:code> has one element, which is
written <html:code>()</html:code>.  This element may be regarded as a 0-tuple, and
<html:code>unit</html:code> as the nullary Cartesian product.  (Think of the connection
between multiplication and the number 1.)</html:p><html:p>The empty tuple serves as a placeholder in situations where no information is
required.  It may:</html:p><html:ul><html:li>appear in a data structure.  For example, a <html:code>unit</html:code>-valued <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">dictionary</fr:link> represents a set of keys.</html:li>
  <html:li>be the argument of a function, where its effect is to <html:em>delay evaluation</html:em>.</html:li>
  <html:li>be the argument or result of a procedure. (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
title="Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
display-uri="focs-procedural-programming"
type="local">Procedural Programming section</fr:link>)</html:li></html:ul><html:p>The empty tuple, like all tuples, is a constructor and is allowed in patterns;
for example: <html:code>let f () = ...</html:code></html:p><html:p>In particular <fr:tex
display="inline"><![CDATA[\tt  fun \, () \rightarrow  E]]></fr:tex> is the function that takes an argument of
type <html:code>unit</html:code> and returns the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as its result.  Expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>
is not evaluated until the function is called, even though the only possible
argument is <html:code>()</html:code>.  The function simply delays the evaluation of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/</fr:uri><fr:display-uri>focs-def-lazy-list</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-lazy-list/</fr:route><fr:title
text="Lazy list">Lazy list</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A lazy list is a list of possibly <html:em>infinite</html:em> length whose elements are
<html:em>computed upon demand</html:em>; in OCaml we implement laziness by <html:em>delaying
evaluation</html:em> of the tail of the list. The traditional word “stream” is reserved in
OCaml parlance for input/output channels, so we call lazy lists <html:em>sequences</html:em>
instead.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lazy-lists/"
title="Lazy Lists (or Streams)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-lists/"
display-uri="focs-lazy-lists"
type="local">Lazy Lists</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-numerical/</fr:uri><fr:display-uri>focs-seq-numerical</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-numerical/</fr:route><fr:title
text="Numerical Computations on Infinite Sequences">Numerical Computations on Infinite Sequences</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let next a x = (a /. x +. x) /. 2.0
val next : float -> float -> float = <fun>]]></html:pre><html:p>Close enough?</html:p><html:pre><![CDATA[# let rec within eps = function
  | Cons (x, xf) ->
      match xf () with
      | Cons (y, yf) ->
          if abs_float (x -. y) <= eps then y
          else within eps (Cons (y, yf))
Lines 3-6, characters 7-41:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

Lines 1-6, characters 22-41:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val within : float -> float seq -> float = <fun>]]></html:pre><html:p>Square Roots:</html:p><html:pre><![CDATA[# let root a = within 1e-6 (iterates (next a) 1.0)
val root : float -> float = <fun>]]></html:pre><html:p>The <html:em>Newton-Raphson method</html:em> is widely used for computing square roots.
The infinite series <fr:tex
display="inline"><![CDATA[x_0, (a/x_0+x_0)/2, \ldots {}]]></fr:tex> converges rapidly to <fr:tex
display="inline"><![CDATA[\sqrt {a}]]></fr:tex>.
The initial approximation, <fr:tex
display="inline"><![CDATA[x_0]]></fr:tex>, is typically retrieved from a table, and is accurate enough
that only a few iterations of the method are necessary.
Calling <html:code>iterates (next a) x0</html:code> generates the <html:em>infinite series</html:em> of
approximations to the square root of <fr:tex
display="inline"><![CDATA[a]]></fr:tex> using the Newton-Raphson method.
To compute <fr:tex
display="inline"><![CDATA[\sqrt 2]]></fr:tex>, the resulting series begins 1, 1.5, 1.41667, 1.4142157, 1.414213562, …,
and this last figure is already accurate to 10 significant digits!</html:p><html:p>Function <html:code>within</html:code> searches down the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy list</fr:link> for two points whose
difference is less than <html:code>eps</html:code>.  It tests their absolute difference.
Relative difference and other “close enough” tests can be coded.  Such
components can be used to implement other numerical functions directly as
functions over sequences.  The point is to build programs from small,
interchangeable parts.</html:p><html:p>Function <html:code>root</html:code> uses <html:code>within</html:code>, <html:code>iterates</html:code> and <html:code>next</html:code> to
to apply Newton-Raphson with a tolerance of <fr:tex
display="inline"><![CDATA[10^{-6}]]></fr:tex>
and a (poor) initial approximation of 1.0.</html:p><html:pre><![CDATA[# root 2.0;;
- : float = 1.41421356237309492]]></html:pre><html:p>This treatment of numerical computation has received some attention in the
research literature; a recurring example is Richardson extrapolation.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-seq-evaluation/</fr:uri><fr:display-uri>focs-seq-evaluation</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-seq-evaluation/</fr:route><fr:title
text="Sample Evaluation">Sample Evaluation</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {aligned}
\tt  get(2,\, from \; 6) \\
\tt  get(2,\, Cons(6, fun \; () \rightarrow  from \; (6+1))) \\
\tt  6 :: get(1,\, from \; (6+1)) \\
\tt  6 :: get(1,\, Cons \; (7,\, fun \; () \rightarrow  from \; (7+1))) \\
\tt  6 :: 7 :: get(0,\, Cons \; (8,\, fun \; () \rightarrow  from \; (8+1))) \\
\tt  6 :: 7 :: [] \\
\tt  [6; 7]
\end {aligned}
]]></fr:tex><html:p>Here we ask for two elements of the infinite sequence.  In fact, three
elements are computed: 6, 7 and 8.  Our implementation is slightly too eager.
A more complicated <html:code>type</html:code> declaration could avoid this problem.
Another problem is that if one repeatedly examines some particular list
element using forcing, that element is repeatedly evaluated.  In a lazy
programming language, the result of the first evaluation would be stored for
later reference.  To get the same effect in OCaml requires the use of
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local">references</fr:link>.</html:p><html:p>We should be grateful that the potentially infinite computation is kept
finite.  The tail of the original sequence even contains the unevaluated
expression 6+1.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-infinite-sequence/</fr:uri><fr:display-uri>focs-infinite-sequence</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-infinite-sequence/</fr:route><fr:title
text="The Infinite Sequence: k, k+1, k+2, …">The Infinite Sequence: <fr:tex
display="inline"><![CDATA[k]]></fr:tex>, <fr:tex
display="inline"><![CDATA[k+1]]></fr:tex>, <fr:tex
display="inline"><![CDATA[k+2]]></fr:tex>, …</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec from k = Cons (k, fun () -> from (k+1))
val from : int -> int seq = <fun>
# let it = from 1
val it : int seq = Cons (1, <fun>)
# let it = tail it
val it : int seq = Cons (2, <fun>)
# let it = tail it
val it : int seq = Cons (3, <fun>)]]></html:pre><html:p>Function <html:code>from</html:code> constructs the infinite sequence of integers starting
from <fr:tex
display="inline"><![CDATA[k]]></fr:tex>.  Execution terminates because of the <html:code>fun</html:code> enclosing the
recursive call.  OCaml displays the tail of a sequence as <html:code>fun</html:code>, which
stands for some function value.  Each call to <html:code>tail</html:code> generates the next
sequence element.  We could do this forever.</html:p><html:p>This example is of little practical value because the cost of computing a
sequence element will be dominated by that of creating the dummy function.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">Lazy lists</fr:link> tend to have high overheads.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:uri><fr:display-uri>focs-ex-9-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-1/</fr:route><fr:title
text="Exercises › A map for sequences"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › A map for sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code an analogue of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> for sequences.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:uri><fr:display-uri>focs-ex-9-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-5/</fr:route><fr:title
text="Exercises › All lists of zeroes and ones"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › All lists of zeroes and ones</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code the lazy list whose elements are all ordinary lists of zeroes and ones, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 1]; [1; 0]; [1; 1]; [0; 0; 0]; </html:code>….  (Taken from the exam question
2003 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:uri><fr:display-uri>focs-ex-9-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-2/</fr:route><fr:title
text="Exercises › Concatenating infinite sequences"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Concatenating infinite sequences</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the list function <html:code>concat</html:code>, which concatenates a list of lists to form a single list. Can
it be generalised to concatenate a sequence of sequences? What can go wrong?</html:p><html:pre><![CDATA[let rec concat = function
| [] -> []
| l::ls -> l @ concat ls]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:uri><fr:display-uri>focs-ex-9-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-6/</fr:route><fr:title
text="Exercises › Enumerating palindromes"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Enumerating palindromes</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>(Continuing the previous exercise.)
A <html:em>palindrome</html:em> is a list that equals its own reverse. Code the lazy list whose elements are all
palindromes of 0s and 1s, namely
<html:code>[]; [0]; [1]; [0; 0]; [0; 0; 0]; [0; 1; 0]; [1; 1]; [1; 0; 1]; [1; 1; 1]; [0; 0; 0; 0]; </html:code>, …. You
may take the reversal function <html:code>List.rev</html:code> as given.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:uri><fr:display-uri>focs-ex-9-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-4/</fr:route><fr:title
text="Exercises › Lazy binary trees"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Lazy binary trees</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A <html:em>lazy binary tree</html:em> is either empty or is a branch containing a label and two lazy <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>,
possibly to infinite depth. Present an OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> to represent lazy binary trees, along with a
function that accepts a lazy binary tree and produces a lazy list that contains all of the tree’s
labels. (Taken from the exam question 2008 Paper 1 Question 5.)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:uri><fr:display-uri>focs-ex-9-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-9-3/</fr:route><fr:title
text="Exercises › Making change lazily"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-9/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-9/"
display-uri="focs-ex-9"
type="local">Exercises</fr:link> › Making change lazily</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Code a function to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">make change</fr:link> using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
title="Lazy list"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-lazy-list/"
display-uri="focs-def-lazy-list"
type="local">lazy lists</fr:link>, delivering the sequence of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">all possible ways of
making change</fr:link>. Using sequences allows us to compute solutions one at a time when there exists an
astronomical number. Represent lists of coins using ordinary lists. (<html:em>Hint</html:em>: to  benefit from
laziness you may need to pass around the sequence of alternative solutions as a function of type
<html:code>unit -&gt; (int list) seq</html:code>.)</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-queues/</fr:uri><fr:display-uri>focs-topic-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-queues/</fr:route><fr:title
text="Queues">Queues</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:uri><fr:display-uri>focs-search-methods</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:route><fr:title
text="A Survey of Search Methods">A Survey of Search Methods</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Depth-first: use a <html:em>stack</html:em>  (efficient but incomplete)</html:li>
  <html:li>Breadth-first: use a <html:em>queue</html:em> (uses too much space!)</html:li>
  <html:li>Iterative deepening: use depth-first to get benefits of breadth-first (trades time for space)</html:li>
  <html:li>Best-first: use a <html:em>priority queue</html:em> (heuristic search)</html:li></html:ul><html:p>The data structure determines the search!</html:p><html:p>Search procedures can be classified by the data structure used to store
pending subtrees.  Depth-first search stores them on a stack, which is
implicit in functions like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link>, but can be made explicit.
Breadth-first search stores such nodes in a queue.</html:p><html:p>An important variation is to store the nodes in a priority queue, which
is an ordered sequence.  The priority queue applies some sort of ranking
function to the nodes, placing higher-ranked nodes before lower-ranked ones.
The ranking function typically estimates the distance from the node to a
solution.  If the estimate is good, the solution is located swiftly.  This
method is called best-first search.</html:p><html:p>The priority queue can be kept as a sorted list, although this is slow.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary search trees</fr:link> would be much better on average, and fancier data
structures improve matters further.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/</fr:uri><fr:display-uri>focs-queue-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-queue-adt/</fr:route><fr:title
text="An Abstract Data Type: Queues">An Abstract Data Type: Queues</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><html:code>qempty</html:code> is the <html:em>empty queue</html:em></html:li>
  <html:li><html:code>qnull</html:code> <html:em>tests</html:em> whether a queue is empty</html:li>
  <html:li><html:code>qhd</html:code> <html:em>returns</html:em> the element at the <html:em>head</html:em> of a queue</html:li>
  <html:li><html:code>deq</html:code> <html:em>discards</html:em> the element at the <html:em>head</html:em> of a queue</html:li>
  <html:li><html:code>enq</html:code> <html:em>adds</html:em> an element at the <html:em>end</html:em> of a queue</html:li></html:ul><html:p>Breadth-first search becomes much faster if we replace the lists by
<html:em>queues</html:em>.  A queue represents a sequence, allowing elements to be taken
from the head and added to the tail.  This is a First-In-First-Out (FIFO)
discipline: the item next to be removed is the one that has been in the queue
for the longest time.  Lists can implement queues, but <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local">append</fr:link> is a poor means
of adding elements to the tail.</html:p><html:p>Our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
title="Functional Arrays as Binary Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-arrays/"
display-uri="focs-functional-arrays"
type="local">functional arrays</fr:link> are suitable, provided we
augment them with a function to delete the first array element.  (See <html:em>ML
  for the Working Programmer</html:em> page 156.)  Each operation would take <fr:tex
display="inline"><![CDATA[O(\log 
n)]]></fr:tex> time for a queue of length <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.</html:p><html:p>We shall describe a representation of queues that is purely functional, based
upon lists, and efficient.  Operations take <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> time when “amortized”:
averaged over the lifetime of a queue.</html:p><html:p>A conventional programming technique is to represent a queue by an array.  Two
indices point to the front and back of the queue, which may wrap around the
end of the array.  The coding is somewhat tricky.  Worse, the length of the
queue must be given a fixed upper bound.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-stacks/</fr:uri><fr:display-uri>focs-stacks</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-stacks/</fr:route><fr:title
text="Another Abstract Data Type: Stacks">Another Abstract Data Type: Stacks</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><html:code>empty</html:code> is the <html:em>empty stack</html:em></html:li>
  <html:li><html:code>null</html:code> tests whether a stack is empty</html:li>
  <html:li><html:code>top</html:code> returns the element at the <html:em>top</html:em> of a stack</html:li>
  <html:li><html:code>pop</html:code> discards the element at the <html:em>top</html:em> of a stack</html:li>
  <html:li><html:code>push</html:code> adds an element at the <html:em>top</html:em> of a stack</html:li></html:ul><html:p>A <html:em>stack</html:em> is a sequence such that items can be added or removed from the head
only.  A stack obeys a Last-In-First-Out (LIFO) discipline: the item next to be
removed is the one that has been on the stack for the <html:em>shortest</html:em> time.  Lists
can easily implement stacks because both <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local"><html:code>hd</html:code></fr:link> affect the head.  But
unlike lists, stacks are often regarded as an imperative data structure: the
effect of <html:code>push</html:code> or <html:code>pop</html:code> is to change an existing stack, not return a new one.</html:p><html:p>In conventional programming languages, a stack is often implemented by storing
the elements in an array, using a variable (the “stack pointer”) to count them.
Most language processors keep track of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function calls</fr:link> using an
internal stack.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:uri><fr:display-uri>focs-bfs-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Queues">Breadth-First Tree Traversal — Using Queues</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec breadth q =
    if qnull q then []
    else
      match qhd q with
      | Lf -> breadth (deq q)
      | Br (v, t, u) -> v :: breadth (enq (enq (deq q) t) u)
val breadth : 'a tree queue -> 'a list = <fun>]]></html:pre><html:p>This function implements the same algorithm as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-append/"
title="Breadth-First Tree Traversal — Using Append"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/"
display-uri="focs-bfs-append"
type="local"><html:code>nbreadth</html:code></fr:link> but uses a different
data structure.  It represents queues using type <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-queues/"
title="Efficient Functional Queues: Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/"
display-uri="focs-functional-queues"
type="local"><html:code>queue</html:code></fr:link> instead of type
<html:code>list</html:code>.</html:p><html:p>To compare their efficiency, I applied both functions to the full binary tree
of depth 12, which contains 4095 labels.  The function <html:code>nbreadth</html:code> took 30
seconds while <html:code>breadth</html:code> took only 0.15 seconds: faster by a factor of 200.</html:p><html:p>For larger trees, the speedup would be greater.  Choosing the right data
structure pays handsomely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:uri><fr:display-uri>focs-functional-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues/</fr:route><fr:title
text="Efficient Functional Queues: Code">Efficient Functional Queues: Code</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type 'a queue =
  | Q of 'a list * 'a list
type 'a queue = Q of 'a list * 'a list
# let norm = function
  | Q ([], tls) -> Q (List.rev tls, [])
  | q -> q
val norm : 'a queue -> 'a queue = <fun>
# let qnull = function
  | Q ([], []) -> true
  | _ -> false
val qnull : 'a queue -> bool = <fun>
# let enq (Q (hds, tls)) x = norm (Q (hds, x::tls))
val enq : 'a queue -> 'a -> 'a queue = <fun>
# exception Empty
exception Empty
# let deq = function
  | Q (x::hds, tls) -> norm (Q (hds, tls))
  | _ -> raise Empty
val deq : 'a queue -> 'a queue = <fun>
# let qempty = Q ([], [])
val qempty : 'a queue = Q ([], [])
# let qhd = function
  | Q (x::_, _) -> x
  | _ -> raise Empty
val qhd : 'a queue -> 'a = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link> of queues prevents confusion with other pairs of lists.  The empty
queue has both parts empty.</html:p><html:p>The function <html:code>norm</html:code> puts a queue into normal form, ensuring that the front part
is never empty unless the entire queue is empty.  Functions <html:code>deq</html:code> and <html:code>enq</html:code>
call <html:code>norm</html:code> to normalise their result.</html:p><html:p>Because queues are in normal form, their head is certain to be in their
front part, so <html:code>qhd</html:code> looks there.</html:p><html:p>Let us analyse the cost of an execution comprising (in any possible order) <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
<html:code>enq</html:code> operations and <fr:tex
display="inline"><![CDATA[n]]></fr:tex> <html:code>deq</html:code> operations, starting with an
empty queue.  Each <html:code>enq</html:code> operation will perform one cons, adding an
element to the rear part.  Since the final queue must be empty, each element
of the rear part gets transferred to the front part.  The corresponding
reversals perform one cons per element.  Thus, the total cost of the series of
queue operations is <fr:tex
display="inline"><![CDATA[2n]]></fr:tex> cons operations, an average of 2 per operation.  The
amortized time is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.</html:p><html:p>There is a catch.  The conses need not be distributed evenly; reversing a long
list could take up to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex> of them.  Unpredictable delays make the approach
unsuitable for <html:em>real-time programming</html:em> where deadlines must be met.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:uri><fr:display-uri>focs-functional-queues-idea</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-functional-queues-idea/</fr:route><fr:title
text="Efficient Functional Queues: Idea">Efficient Functional Queues: Idea</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Represent the queue <fr:tex
display="inline"><![CDATA[x_1\; x_2\; \ldots \; x_m\; y_n\; \ldots \; y_1]]></fr:tex> by any <html:em>pair of lists</html:em>
    <fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \; [y_1,y_2,\ldots ,y_n])]]></fr:tex></html:li>
  <html:li>Add new items to the <html:em>rear list</html:em></html:li>
  <html:li>Remove items from <html:em>front list</html:em> and if empty move <html:em>rear</html:em> to <html:em>front</html:em></html:li>
  <html:li><html:em>Amortized</html:em> time per operation is <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p>Queues require efficient access at both ends: at the front, for removal, and
at the back, for insertion.  Ideally, access should take constant time,
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.  It may appear that lists cannot provide such access.  If
<html:code>enq(q, x)</html:code> performs <html:code>q@[x]</html:code>, then this operation will be <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  We
could represent queues by reversed lists, implementing <html:code>enq(q, x)</html:code> by
<html:code>x::q</html:code>, but then the <html:code>deq</html:code> and <html:code>qhd</html:code> operations would be
<fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Linear time is intolerable: a series of <fr:tex
display="inline"><![CDATA[n]]></fr:tex> queue operations
could then require <fr:tex
display="inline"><![CDATA[O(n^2)]]></fr:tex> time.</html:p><html:p>The solution is to represent a queue by a pair of lists, where</html:p><fr:tex
display="block"><![CDATA[([x_1,x_2,\ldots ,x_m], \, [y_1,y_2,\ldots ,y_n])]]></fr:tex><html:p>represents the queue <fr:tex
display="inline"><![CDATA[x_1 x_2 \ldots  x_m y_n \ldots  y_1]]></fr:tex>.</html:p><html:p>The front part of the queue is stored in order, and the rear part is stored in
reverse order.  The <html:code>enq</html:code> operation adds elements to the rear part
using cons, since this list is reversed; thus, <html:code>enq</html:code> takes constant
time.  The <html:code>deq</html:code> and <html:code>qhd</html:code> operations look at the front part,
which normally takes constant time, since this list is stored in order.  But
sometimes <html:code>deq</html:code> removes the last element from the front part; when this
happens, it reverses the rear part, which becomes the new front part.</html:p><html:p><html:em>Amortized</html:em> time refers to the cost per operation averaged over the
lifetime of any complete execution.  Even for the worst possible execution,
the average cost per operation turns out to be constant; see the analysis
below.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:uri><fr:display-uri>focs-ex-10-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:route><fr:title
text="Exercises › Array-based circular queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Array-based circular queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The traditional way to implement queues uses a fixed-length array. Two indices into the array
indicate the start and end of the queue, which wraps around from the end of the array to the start.
How appropriate is such a data structure for implementing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
title="Breadth-First v Depth-First Tree Traversal"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
display-uri="focs-bfs-dfs"
type="local">breadth-first search</fr:link>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:uri><fr:display-uri>focs-ex-10-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-3/</fr:route><fr:title
text="Exercises › Rewriting breadth with let"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Rewriting breadth with let</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
title="Breadth-First Tree Traversal — Using Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/"
display-uri="focs-bfs-queues"
type="local"><html:code>breadth</html:code></fr:link> using a nested <html:code>let</html:code> construction rather than
<html:code>match</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:uri><fr:display-uri>focs-ex-10-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-1/</fr:route><fr:title
text="Exercises › Tree-based queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Tree-based queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Suppose that we have an implementation of queues, based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>, such that each operation
takes logarithmic time in the worst case. Outline the advantages and drawbacks of such an
implementation compared with one presented above.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-search/</fr:uri><fr:display-uri>focs-topic-search</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-search/</fr:route><fr:title
text="Search">Search</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:uri><fr:display-uri>focs-search-methods</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-search-methods/</fr:route><fr:title
text="A Survey of Search Methods">A Survey of Search Methods</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Depth-first: use a <html:em>stack</html:em>  (efficient but incomplete)</html:li>
  <html:li>Breadth-first: use a <html:em>queue</html:em> (uses too much space!)</html:li>
  <html:li>Iterative deepening: use depth-first to get benefits of breadth-first (trades time for space)</html:li>
  <html:li>Best-first: use a <html:em>priority queue</html:em> (heuristic search)</html:li></html:ul><html:p>The data structure determines the search!</html:p><html:p>Search procedures can be classified by the data structure used to store
pending subtrees.  Depth-first search stores them on a stack, which is
implicit in functions like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local"><html:code>inorder</html:code></fr:link>, but can be made explicit.
Breadth-first search stores such nodes in a queue.</html:p><html:p>An important variation is to store the nodes in a priority queue, which
is an ordered sequence.  The priority queue applies some sort of ranking
function to the nodes, placing higher-ranked nodes before lower-ranked ones.
The ranking function typically estimates the distance from the node to a
solution.  If the estimate is good, the solution is located swiftly.  This
method is called best-first search.</html:p><html:p>The priority queue can be kept as a sorted list, although this is slow.
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">Binary search trees</fr:link> would be much better on average, and fancier data
structures improve matters further.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:uri><fr:display-uri>focs-predicate-applications</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-applications/</fr:route><fr:title
text="Applications of the Predicate Functionals">Applications of the Predicate Functionals</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let member y xs =
    exists (fun x -> x=y) xs
val member : 'a -> 'a list -> bool = <fun>
# let inter xs ys =
    filter (fun x -> member x ys) xs
val inter : 'a list -> 'a list -> 'a list = <fun>]]></html:pre><html:p><html:em>Testing whether two lists have no common elements</html:em></html:p><html:pre><![CDATA[# let disjoint xs ys =
    all (fun x -> all (fun y -> x<>y) ys) xs
val disjoint : 'a list -> 'a list -> bool = <fun>]]></html:pre><html:p>The Lists lecture presented the function <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link>, which tests whether a
specified value can be found as a list element, and <html:code>inter</html:code>, which returns the
“intersection” of two lists: the list of elements they have in common.</html:p><html:p>But remember: the purpose of list <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functionals</fr:link> is not to replace the
declarations of popular functions, which probably are available already.  It is
to eliminate the need for separate declarations of ad-hoc functions.  When they
are nested, like the calls to <html:code>all</html:code> in <html:code>disjoint</html:code> above, the
inner functions are almost certainly one-offs, not worth declaring separately.</html:p><html:p>Our primitives themselves can be seen as a programming language.  Part of the
task of programming is to extend our programming language with notation for
solving the problem at hand.  The levels of notation that we define should
correspond to natural <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">levels of abstraction</fr:link> in the problem domain.</html:p><html:p>Historical Note:
Alonzo Church’s <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus gave a simple syntax, <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-notation,
for expressing functions.  It is the direct precursor of OCaml’s
<html:code>fun</html:code>-notation.  It was soon shown that his system was equivalent in
computational power to Turing machines, and <html:em>Church’s thesis</html:em> states that
this defines precisely the set of functions that can be computed effectively.</html:p><html:p>The <fr:tex
display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus had a tremendous influence on the design of functional
programming languages.  McCarthy’s Lisp was something of a false start; it
interpreted variable binding incorrectly, an error that stood for some 20
years.  But in 1966, Peter Landin (of Queen Mary College, University of London)
sketched out the main features of functional languages.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/</fr:uri><fr:display-uri>focs-bst</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bst/</fr:route><fr:title
text="Binary Search Trees">Binary Search Trees</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>dictionary</html:em> associates <html:em>values</html:em> (here, numbers) with <html:em>keys</html:em>.</html:p><html:figure><html:img
src="/teaching/2627/FoundsCS/forest/bafkrmifkdrvs6ut5buyf724655gdcinx637uevqiaejsmb2jgu36gaf4wq.svg" /></html:figure><html:p>Binary search trees are an important application of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local">binary trees</fr:link>.  They work
for keys that have a total ordering, such as strings.  Each branch of the tree
carries a <fr:tex
display="inline"><![CDATA[(key, value)]]></fr:tex> pair; its left subtree holds smaller keys; the right
subtree holds greater keys.  If the tree remains reasonably balanced, then
update and lookup both take <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> for a tree of size <fr:tex
display="inline"><![CDATA[n]]></fr:tex>.  These times
hold in the average case; given random data, the tree is likely to remain
balanced.</html:p><html:p>At a given node, all keys in the left subtree are smaller (or equal) while all
trees in the right subtree are greater.</html:p><html:p>An unbalanced tree has a linear access time in the worst case.  Examples
include building a tree by repeated insertions of elements in increasing or
decreasing order; there is a close resemblance to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link>.  Building a binary
search tree, then converting it to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">inorder</fr:link>, yields a sorting algorithm called
<html:em>treesort</html:em>.</html:p><html:p>Self-balancing trees, such as Red-Black trees, attain <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> in the worst
case.  They are complicated to implement.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:uri><fr:display-uri>focs-bfs-append</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-append/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Append">Breadth-First Tree Traversal — Using Append</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec nbreadth = function
  | [] -> []
  | Lf :: ts -> nbreadth ts
  | Br (v, t, u) :: ts ->
      v :: nbreadth (ts @ [t; u])
val nbreadth : 'a tree list -> 'a list = <fun>]]></html:pre><html:p>Keeps an <html:em>enormous queue</html:em> of nodes of search, and is a wasteful use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-append/"
title="Append: List Concatenation"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-append/"
display-uri="focs-append"
type="local"><html:code>append</html:code></fr:link>.</html:p><html:p>Breadth-first search can be inefficient, this naive implementation especially
so.  When the search is at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> of the tree, the list contains all the
remaining trees at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex>, followed by the subtrees (all at depth <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>) of
the trees that have already been visited.  At depth 10, the list could already
contain 1024 elements.  It requires a lot of space, and aggravates this with a
gross misuse of append.  Evaluating <html:code>ts@[t, u]</html:code> copies the long list
<html:code>ts</html:code> just to insert two elements.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:uri><fr:display-uri>focs-bfs-queues</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-queues/</fr:route><fr:title
text="Breadth-First Tree Traversal — Using Queues">Breadth-First Tree Traversal — Using Queues</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec breadth q =
    if qnull q then []
    else
      match qhd q with
      | Lf -> breadth (deq q)
      | Br (v, t, u) -> v :: breadth (enq (enq (deq q) t) u)
val breadth : 'a tree queue -> 'a list = <fun>]]></html:pre><html:p>This function implements the same algorithm as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-append/"
title="Breadth-First Tree Traversal — Using Append"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-append/"
display-uri="focs-bfs-append"
type="local"><html:code>nbreadth</html:code></fr:link> but uses a different
data structure.  It represents queues using type <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functional-queues/"
title="Efficient Functional Queues: Code"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functional-queues/"
display-uri="focs-functional-queues"
type="local"><html:code>queue</html:code></fr:link> instead of type
<html:code>list</html:code>.</html:p><html:p>To compare their efficiency, I applied both functions to the full binary tree
of depth 12, which contains 4095 labels.  The function <html:code>nbreadth</html:code> took 30
seconds while <html:code>breadth</html:code> took only 0.15 seconds: faster by a factor of 200.</html:p><html:p>For larger trees, the speedup would be greater.  Choosing the right data
structure pays handsomely.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/</fr:uri><fr:display-uri>focs-bfs-dfs</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bfs-dfs/</fr:route><fr:title
text="Breadth-First v Depth-First Tree Traversal">Breadth-First v Depth-First Tree Traversal</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>binary trees as <html:em>decision trees</html:em></html:li>
  <html:li>look for <html:em>solution nodes</html:em>
    <html:ul><html:li>Depth-first: search one subtree in full before moving on</html:li>
      <html:li>Breadth-first: search all nodes at level <fr:tex
display="inline"><![CDATA[k]]></fr:tex> before moving to <fr:tex
display="inline"><![CDATA[k+1]]></fr:tex></html:li></html:ul></html:li>
  <html:li>finds <html:em>all</html:em> solutions — nearest first!</html:li></html:ul><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
title="Aside: Traversing Trees (3 Methods)"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-tree-traversal/"
display-uri="focs-tree-traversal"
type="local">Preorder, inorder and postorder tree traversals</fr:link> all have something in common:
they are depth-first.  At each node, the left subtree is entirely
traversed before the right subtree.  Depth-first traversals are easy to code
and can be efficient, but they are ill-suited for some problems.</html:p><html:p>Suppose the tree represents the possible moves in a puzzle, and the purpose
of the traversal is to search for a node containing a solution.  Then a
depth-first traversal may find one solution node deep in the left subtree,
when another solution is at the very top of the right subtree.  Often we
want the shortest path to a solution.</html:p><html:p>Suppose the tree is <html:em>infinite</html:em> or simply extremely large.  Depth-first search
is almost useless with such trees, for if the left subtree is infinite then the
search will never reach the right subtree.  OCaml can represent infinite trees by
the means discussed in the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-sequences/"
title="Sequences, or Lazy Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-sequences/"
display-uri="focs-sequences"
type="local">lecture on laziness</fr:link>. Another tree representation (suitable
for solving solitaire, for example) is by a function <html:code>next : pos -&gt; pos list</html:code>,
which maps a board position to a list of the positions possible after
the next move.  For simplicity, the examples below use the OCaml <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link>
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-binary-trees/"
title="Binary Trees, a Recursive Datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-binary-trees/"
display-uri="focs-binary-trees"
type="local"><html:code>tree</html:code></fr:link>, which has only finite trees.</html:p><html:p>A <html:em>breadth-first</html:em> traversal explores the nodes horizontally rather than
vertically.  When visiting a node, it does not traverse the subtrees until
it has visited all other nodes at the current depth.  This is easily
implemented by keeping a list of trees to visit.  Initially, this list
consists of one element: the entire tree.  Each iteration removes a tree
from the head of the list and adds its subtrees after the end of the
list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/</fr:uri><fr:display-uri>focs-equality</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-equality/</fr:route><fr:title
text="Equality Tests">Equality Tests</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec member x = function
   | [] -> false
   | y::l ->
      if x = y then true
      else member x l
val member : 'a -> 'a list -> bool = <fun>]]></html:pre><html:p>All the list functions we have encountered up to now have been “<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>”,
working for lists of any type.  Function <html:code>member</html:code> uses <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link> to report
whether or not <html:code>x</html:code> occurs in <html:code>l</html:code>.</html:p><html:p>To do this generically, it uses a special feature of OCaml known as
“polymorphic equality”, which manifests itself via the <html:code>=</html:code>, <html:code>&gt;=</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code> and
<html:code>&lt;</html:code> operators.  These operators inspect the <html:em>structure</html:em> of the values using a
consistent order.  Types you can legitimately compare this way include integers,
strings, booleans, and tuples or lists of primitive types.</html:p><html:p>More complex types can be compared this way within careful limits: recursive
structures or function values will not work (we will cover function values in
the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-currying/"
title="Curried Functions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/"
display-uri="focs-currying"
type="local">Currying lecture</fr:link> later).  For now, it is sufficient to use these magic
polymorphic equality operators.  As you get more familiar with OCaml and the
use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functions/"
title="Functions as Values"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/"
display-uri="focs-functions"
type="local">higher order functions</fr:link> (also covered in a later lecture), you will
encounter the use of explicit <html:code>compare</html:code> functions that are used to provide more
complex equality tests.</html:p><html:p>The presence of polymorphic equality is a contentious feature in OCaml.  While
it provides a great ease of use in smaller codebases, it starts to become more
dangerous when building larger OCaml-based systems.  Most large-scale users of
OCaml tend towards not using it in important code, but it is just fine for our
purposes while learning the beginning steps of computer science.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:uri><fr:display-uri>focs-iterative-deepening</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-iterative-deepening/</fr:route><fr:title
text="Iterative deepening: Another Exhaustive Search">Iterative deepening: Another Exhaustive Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Breadth-first search examines <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> nodes:
    <fr:tex
display="block"><![CDATA[1 + b + \cdots  + b^d = {b^{d+1}-1 \over  b-1}
  \qquad  \begin {array}{rl}
            b & {} = \hbox {branching factor}\\
            d & {} = \hbox {depth}
          \end {array}]]></fr:tex></html:li>
  <html:li>Recompute nodes at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> instead of storing them</html:li>
  <html:li>Time factor is <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>; complexity is still <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex></html:li>
  <html:li>Space required at depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> drops from <fr:tex
display="inline"><![CDATA[b^d]]></fr:tex> to <fr:tex
display="inline"><![CDATA[d]]></fr:tex></html:li></html:ul><html:p>Breadth-first search is not practical for infinite trees: it uses too much
space. Large parts of the tree have to be stored.
Consider the slightly more general problem of searching trees whose
branching factor is <fr:tex
display="inline"><![CDATA[b]]></fr:tex> (for binary trees, <fr:tex
display="inline"><![CDATA[b=2]]></fr:tex>).  Then breadth-first search
to depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> examines <fr:tex
display="inline"><![CDATA[(b^{d+1}-1)/(b-1)]]></fr:tex> nodes, which is <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>, ignoring
the constant factor of <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex>.  Since all nodes that are examined are also
stored, the space and time requirements are both <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.</html:p><html:p><html:em>Depth-first iterative deepening</html:em> combines the space efficiency of
depth-first with the “nearest-first” property of breadth-first search.  It
performs repeated depth-first searches with increasing depth bounds, each time
discarding the result of the previous search.  Thus it searches to depth 1,
then to depth 2, and so on until it finds a solution.  We can afford to
discard previous results because the number of nodes is growing exponentially.
There are <fr:tex
display="inline"><![CDATA[b^{d+1}]]></fr:tex> nodes at level <fr:tex
display="inline"><![CDATA[d+1]]></fr:tex>; if <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex>, this number actually
exceeds the total number of nodes of all previous levels put together, namely
<fr:tex
display="inline"><![CDATA[(b^{d+1}-1) / (b-1)]]></fr:tex>.</html:p><html:p><fr:link
href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.91.288"
type="external">Korf shows</fr:link> that the time needed for iterative deepening to reach
depth <fr:tex
display="inline"><![CDATA[d]]></fr:tex> is only <fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> times that for breadth-first search, if <fr:tex
display="inline"><![CDATA[b>1]]></fr:tex>.
This is a constant factor; both algorithms have the same time complexity,
<fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex>.  In typical applications where <fr:tex
display="inline"><![CDATA[b\geq 2]]></fr:tex> the extra factor of
<fr:tex
display="inline"><![CDATA[b/(b-1)]]></fr:tex> is quite tolerable.  The reduction in the space requirement is
exponential, from <fr:tex
display="inline"><![CDATA[O(b^d)]]></fr:tex> for breadth-first to <fr:tex
display="inline"><![CDATA[O(d)]]></fr:tex> for iterative
deepening. Of course, this assumes that the tree itself is not stored in memory.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:uri><fr:display-uri>focs-linear-search</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-linear-search/</fr:route><fr:title
text="Linear Search">Linear Search</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>find <fr:tex
display="inline"><![CDATA[x]]></fr:tex> in list <fr:tex
display="inline"><![CDATA[[x_1,\ldots ,x_n]]]></fr:tex> by comparing with each element</html:li>
  <html:li>obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex> time</html:li>
  <html:li>simple &amp; general</html:li>
  <html:li>ordered searching needs only <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex></html:li>
  <html:li>indexed lookup needs only <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex></html:li></html:ul><html:p><html:em>Linear search</html:em> is the obvious way to find a desired item in a
collection: simply look through all the items, one at a time.  If <fr:tex
display="inline"><![CDATA[x]]></fr:tex> is in
the list, then it will be found in <fr:tex
display="inline"><![CDATA[n/2]]></fr:tex> steps on average, and even the worst
case is obviously <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p><html:p>Large collections of data are usually ordered or indexed so that items can be
found in <fr:tex
display="inline"><![CDATA[O(\log  n)]]></fr:tex> time, which is exponentially better than <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.  Even
<fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> is achievable (using a hash table), though subject to the usual
proviso that machine limits are not exceeded.</html:p><html:p>Efficient indexing methods are of prime importance: consider Web
search engines.  Nevertheless, linear search is often used to search small
collections because it is so simple and general, and it is the starting point
for better algorithms.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:uri><fr:display-uri>focs-predicate-functionals</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-predicate-functionals/</fr:route><fr:title
text="List Functionals for Predicates">List Functionals for Predicates</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec exists p = function
  | [] -> false
  | x::xs -> (p x) || (exists p xs)
val exists : ('a -> bool) -> 'a list -> bool = <fun>
# let rec filter p = function
  | [] -> []
  | x::xs ->
      if p x then
        x :: filter p xs
      else
        filter p xs
val filter : ('a -> bool) -> 'a list -> 'a list = <fun>]]></html:pre><html:p>A <html:em>predicate</html:em> is a <html:em>boolean-valued</html:em> function.</html:p><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
title="Higher-order function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-higher-order-function/"
display-uri="focs-def-higher-order-function"
type="local">functional</fr:link> <html:code>exists</html:code> transforms a predicate into a predicate over
lists.  Given a list, <html:code>exists p</html:code> tests whether or not some list element
satisfies <html:code>p</html:code> (making it return <html:code>true</html:code>).  If it finds one, it stops
searching immediately, thanks to the behaviour of the lazy <html:code>||</html:code> operator.</html:p><html:p>Dually, we have a functional to test whether all list elements satisfy the
predicate.  If it finds a counterexample then it, too, stops searching.</html:p><html:pre><![CDATA[# let rec all p = function
  | [] -> true
  | x::xs -> (p x) && all p xs
val all : ('a -> bool) -> 'a list -> bool = <fun>]]></html:pre><html:p>The <html:code>filter</html:code> functional, like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link>, transforms lists.  It applies a
predicate to all the list elements, but instead of returning the
resulting values (which could only be <html:code>true</html:code> or <html:code>false</html:code>), it returns
the list of elements satisfying the predicate.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:uri><fr:display-uri>focs-change-exceptions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-change-exceptions/</fr:route><fr:title
text="Making Change with Exceptions">Making Change with Exceptions</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception Change
  let rec change till amt =
    match till, amt with
    | _, 0         -> []
    | [], _        -> raise Change
    | c::till, amt -> if amt < 0 then raise Change
                      else try c :: change (c::till) (amt - c)
                           with Change -> change till amt
exception Change
val change : int list -> int -> int list = <fun>]]></html:pre><html:p>In the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-more-lists/"
title="More on Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-more-lists/"
display-uri="focs-more-lists"
type="local">Lists lectures</fr:link>, we considered the problem of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-making-change/"
title="An Application: Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-making-change/"
display-uri="focs-making-change"
type="local">making change</fr:link>.  The greedy
algorithm presented there could not express “6 using 5 and 2” because it always
took the largest coin.  Returning <fr:link
href="/teaching/2627/FoundsCS/forest/focs-change-all/"
title="All Ways of Making Change"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-change-all/"
display-uri="focs-change-all"
type="local">the list of all possible solutions</fr:link> avoids
that problem rather expensively: we only need one solution.</html:p><html:p>Using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exceptions</fr:link>, we can code a <html:em>backtracking</html:em> algorithm: one that can undo
past decisions if it comes to a dead end.  The exception <html:code>Change</html:code> is raised if
we run out of coins (with a non-zero amount) or if the amount goes negative.
We always try the largest coin, but enclose the recursive call in an exception
handler, which undoes the choice if it goes wrong.</html:p><html:p>Carefully observe how exceptions interact with <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.  The exception
handler always undoes the <html:em>most recent</html:em> choice, leaving others possibly to
be undone later.  If making change really is impossible, then eventually
<html:code>exception Change</html:code> will be raised with no handler to catch it, and it
will be reported at top level.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:uri><fr:display-uri>focs-ex-10-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-5/</fr:route><fr:title
text="Exercises › An implicit infinite tree"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › An implicit infinite tree</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the following OCaml function.</html:p><html:pre><![CDATA[let next n = [2 * n; 2 * n + 1]]]></html:pre><html:p>If we regard it as representing a tree, where the subtrees are computed from the current label, what
tree does <html:code>next 1</html:code> represent?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:uri><fr:display-uri>focs-ex-10-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-2/</fr:route><fr:title
text="Exercises › Array-based circular queues"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Array-based circular queues</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The traditional way to implement queues uses a fixed-length array. Two indices into the array
indicate the start and end of the queue, which wraps around from the end of the array to the start.
How appropriate is such a data structure for implementing <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
title="Breadth-First v Depth-First Tree Traversal"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bfs-dfs/"
display-uri="focs-bfs-dfs"
type="local">breadth-first search</fr:link>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:uri><fr:display-uri>focs-ex-10-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-10-4/</fr:route><fr:title
text="Exercises › Search with a branching factor near one"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-10/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-10/"
display-uri="focs-ex-10"
type="local">Exercises</fr:link> › Search with a branching factor near one</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p><fr:link
href="/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
title="Iterative deepening: Another Exhaustive Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-iterative-deepening/"
display-uri="focs-iterative-deepening"
type="local">Iterative deepening</fr:link> is inappropriate if <fr:tex
display="inline"><![CDATA[b\approx 1]]></fr:tex>, where <fr:tex
display="inline"><![CDATA[b]]></fr:tex> is the branching factor. What search
strategy is appropriate in this case?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:uri><fr:display-uri>focs-ex-4-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-1/</fr:route><fr:title
text="Exercises › Set union without repetitions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Set union without repetitions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Sets can be represented in OCaml using lists containing no duplicated items
(i.e. where no item is equal to another using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link> comparison).</html:p><html:p>Using the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local"><html:code>member</html:code></fr:link> function defined above, code a function to implement set
union. It should avoid introducing repetitions, for example the union of the
lists <html:code>[4; 7; 1]</html:code> and <html:code>[6; 4; 7]</html:code> should be <html:code>[1; 6; 4; 7]</html:code> (though the order
does not matter).</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-imperative/</fr:uri><fr:display-uri>focs-topic-imperative</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-imperative/</fr:route><fr:title
text="Imperative">Imperative</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-stacks/</fr:uri><fr:display-uri>focs-stacks</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-stacks/</fr:route><fr:title
text="Another Abstract Data Type: Stacks">Another Abstract Data Type: Stacks</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><html:code>empty</html:code> is the <html:em>empty stack</html:em></html:li>
  <html:li><html:code>null</html:code> tests whether a stack is empty</html:li>
  <html:li><html:code>top</html:code> returns the element at the <html:em>top</html:em> of a stack</html:li>
  <html:li><html:code>pop</html:code> discards the element at the <html:em>top</html:em> of a stack</html:li>
  <html:li><html:code>push</html:code> adds an element at the <html:em>top</html:em> of a stack</html:li></html:ul><html:p>A <html:em>stack</html:em> is a sequence such that items can be added or removed from the head
only.  A stack obeys a Last-In-First-Out (LIFO) discipline: the item next to be
removed is the one that has been on the stack for the <html:em>shortest</html:em> time.  Lists
can easily implement stacks because both <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local"><html:code>cons</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local"><html:code>hd</html:code></fr:link> affect the head.  But
unlike lists, stacks are often regarded as an imperative data structure: the
effect of <html:code>push</html:code> or <html:code>pop</html:code> is to change an existing stack, not return a new one.</html:p><html:p>In conventional programming languages, a stack is often implemented by storing
the elements in an array, using a variable (the “stack pointer”) to count them.
Most language processors keep track of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursive function calls</fr:link> using an
internal stack.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-examples/</fr:uri><fr:display-uri>focs-array-examples</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-array-examples/</fr:route><fr:title
text="Array Examples">Array Examples</fr:title></fr:frontmatter><fr:mainmatter><html:p>In the following session, the identifier <html:code>ar</html:code> is bound to an array of 20 elements, which
are initially set to the squares of their subscripts.  The array’s third
element (which actually has subscript 2) is inspected and found to be four. The
second call to <html:code>Array.get</html:code> supplies a subscript that is out of range, so OCaml
rejects it.</html:p><html:pre><![CDATA[# let ar = Array.init 20 (fun i -> i * i)
val ar : int array =
  [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81; 100; 121; 144; 169; 196; 225; 256;
    289; 324; 361|]
# Array.get ar 2
- : int = 4
# Array.get ar 20
Exception: Invalid_argument "index out of bounds".
# Array.set ar 2 33; ar
- : int array =
[|0; 1; 33; 9; 16; 25; 36; 49; 64; 81; 100; 121; 144; 169; 196; 225; 256;
  289; 324; 361|]]]></html:pre><html:p>By calling <html:code>Array.set</html:code>, we then modify the element with subscript 2. Note
however that we cannot modify the array’s length. If we outgrow the array, we
have to create a new one, copy the data into it, and then forget the old array.
Typically the new array would be double the size of the old one, so that the
cost of copying is insignificant.</html:p><html:p>OCaml provides numerous operators for modifying, computing over and searching in
arrays. Many are analogous to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-lists/"
title="Lists"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lists/"
display-uri="focs-lists"
type="local">functions on lists</fr:link>. For example,
<html:code>Array.exists</html:code> takes a boolean-valued function and returns <html:code>true</html:code> if an
array element satisfies it.</html:p><html:pre><![CDATA[# Array.exists (fun i -> i > 200) ar
- : bool = true
# Array.exists (fun i -> i < 0) ar
- : bool = false]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-arrays/</fr:uri><fr:display-uri>focs-arrays</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-arrays/</fr:route><fr:title
text="Arrays">Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>A conventional array is an indexed storage area.
  <html:ul><html:li>It is updated <html:em>in place</html:em> by the command <html:code>a.(k) &lt;- x</html:code></html:li>
  <html:li>The concept is inherently <html:em>imperative</html:em>.</html:li></html:ul></html:li>
<html:li>A <html:em>functional array</html:em> is a finite map from integers to data.
  <html:ul><html:li>Updating implies <html:em>copying</html:em> to return <html:code>update(A, k, x)</html:code></html:li>
  <html:li>The new array equals <html:code>A</html:code> except that <html:code>A.(k) = x</html:code>.</html:li></html:ul></html:li>
<html:li>Can we do updates efficiently?</html:li></html:ul><html:p>The elements of a list can only be reached by counting from the front.
Elements of a tree are reached by following a path from the root.  An
<html:em>array</html:em> hides such structural matters; its elements are uniformly
designated by number.  Immediate access to arbitrary parts of a data structure
is called <html:em>random access</html:em>.</html:p><html:p>Arrays are the dominant data structure in conventional programming languages.
The ingenious use of arrays is the key to many of the great classical
algorithms, such as Hoare’s original <fr:link
href="/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
title="Quicksort: The Idea"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-quicksort-idea/"
display-uri="focs-quicksort-idea"
type="local">quicksort</fr:link> (the partition step) and
Warshall’s transitive-closure algorithm.</html:p><html:p>The drawback is that subscripting is a chief cause of programmer error.  That
is why arrays play little role in this introductory course.</html:p><html:p>Functional arrays are described below in order to illustrate another way of
using trees to organise data.  Here is a summary of basic dictionary data
structures in order of decreasing generality and increasing efficiency:</html:p><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">Linear search</fr:link>: Most general, needing only equality on keys, but inefficient: linear time.</html:li>
<html:li>Binary search: Needs an ordering on keys.  Logarithmic access time in the average case, but our <fr:link
href="/teaching/2627/FoundsCS/forest/focs-bst/"
title="Binary Search Trees"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bst/"
display-uri="focs-bst"
type="local">binary search trees</fr:link> are linear in the worst case.</html:li>
<html:li>Array subscripting: Least general, requiring keys to be integers, but even worst-case time is logarithmic.</html:li></html:ul></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-commands/</fr:uri><fr:display-uri>focs-commands</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-commands/</fr:route><fr:title
text="Commands: Expressions with Effects">Commands: Expressions with Effects</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Basic commands update <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link>, write to files, etc.</html:li>
  <html:li><fr:tex
display="inline"><![CDATA[C_1 ; \ldots  ; C_n]]></fr:tex> causes a series of expressions to be evaluated and returns the value of <fr:tex
display="inline"><![CDATA[C_n]]></fr:tex>.</html:li>
  <html:li>A typical command returns the empty tuple: <html:code>()</html:code></html:li>
  <html:li><html:code>if</html:code> <fr:tex
display="inline"><![CDATA[B]]></fr:tex> <html:code>then</html:code> <fr:tex
display="inline"><![CDATA[C_1]]></fr:tex> <html:code>else</html:code> <fr:tex
display="inline"><![CDATA[C_2]]></fr:tex> behaves like the traditional control structure if <fr:tex
display="inline"><![CDATA[C_1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[C_2]]></fr:tex> have effects.</html:li>
  <html:li>Other OCaml constructs behave naturally with commands, including <html:code>match</html:code> expressions and recursive functions.</html:li></html:ul><html:p>We use the term <html:em>command</html:em> informally to refer to an expression that has an
effect on the state. All expressions denote some value, but they can return
<html:code>()</html:code>, which conveys no actual information.</html:p><html:p>We need a way to execute one command after another.
The construct <fr:tex
display="inline"><![CDATA[C_1 ; \ldots  ; C_n]]></fr:tex> evaluates the expressions <fr:tex
display="inline"><![CDATA[C_1]]></fr:tex>
to <fr:tex
display="inline"><![CDATA[C_n]]></fr:tex> in the order given and returns the value of <fr:tex
display="inline"><![CDATA[C_n]]></fr:tex>.  The values
of the other expressions are discarded; their only purpose is to change the
state.</html:p><html:p>Commands may be used with <html:code>if</html:code> and <html:code>match</html:code> much as in conventional languages.
OCaml functions play the role of procedures.</html:p><html:p>Other languages that combine the functional and imperative programming
paradigms include Lisp (and its dialect Scheme), F#, Scala, Swift and Kotlin.
Rust is a notable modern example: a systems programming language whose type
system and pattern matching draw heavily on the ML family (its first compiler
was written in OCaml), yet which gives the programmer precise control over
mutable state.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-goals-of-programming/</fr:uri><fr:display-uri>focs-goals-of-programming</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-goals-of-programming/</fr:route><fr:title
text="Goals of Programming">Goals of Programming</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>to describe a computation so that it can be done <html:strong>mechanically</html:strong>:
    <html:ul><html:li>Expressions compute values.</html:li>
      <html:li>Commands cause effects.</html:li></html:ul></html:li>
  <html:li>to do so efficiently and <html:strong>correctly</html:strong>, giving the right answers quickly</html:li>
  <html:li>to allow easy modification as needs change
    <html:ul><html:li>Through an orderly <html:strong>structure</html:strong> based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstraction principles</fr:link></html:li>
      <html:li>Such as modules or classes</html:li></html:ul></html:li></html:ul><html:p>Programming <html:em>in-the-small</html:em> concerns the writing of code to do simple, clearly
defined tasks. Programs provide expressions for describing mathematical
formulae and so forth. This was the original contribution of FORTRAN, the
FORmula TRANslator. Commands describe how control should flow from one part of
the program to the next.</html:p><html:p>As we code layer upon layer, we eventually find ourselves programming
<html:em>in the large</html:em> : joining large modules to solve some messy task. Programming
languages have used various mechanisms to allow one part of the program to
provide interfaces to other parts. Modules encapsulate a body of code, allowing
outside access only through a programmer-defined interface. <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queue-adt/"
title="An Abstract Data Type: Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/"
display-uri="focs-queue-adt"
type="local"><html:em>Abstract Data
Types</html:em></fr:link> are a simpler version of this concept, which implement a single concept
such as dates or floating-point numbers.</html:p><html:p><html:em>Object-oriented programming</html:em> is the most complicated approach to modularity.
<html:em>Classes</html:em> define concepts, and they can be built upon other classes. Operations
can be defined that work in appropriately specialised ways on a family of
related classes. <html:em>Objects</html:em> are instances of classes and hold the data that is
being manipulated.</html:p><html:p>This course does not cover OCaml’s sophisticated module system, which can do
many of the same things as classes. You will learn all about objects when you
study Java. OCaml includes a powerful object system, although this is not used
as much as its module system.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/</fr:uri><fr:display-uri>focs-while</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-while/</fr:route><fr:title
text="Iteration: the while command">Iteration: the while command</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let tlopt = function
  | [] -> None
  | _::xs -> Some xs
val tlopt : 'a list -> 'a list option = <fun>
# let length xs =
    let lp  = ref xs in (* list of uncounted elements *)
    let np  = ref 0  in (* accumulated count *)
    let fin = ref false in
    while not !fin do
      match tlopt !lp with
      | None -> fin := true
      | Some xs ->
          lp := xs;
          np := 1 + !np
    done;
    !np (* the final count is returned *)
val length : 'a list -> int = <fun>]]></html:pre><html:p>Once we can change the state, we need to do so repeatedly.  <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">Recursion</fr:link> can
serve this purpose, but having to declare a procedure for every loop is
clumsy, and compilers for conventional languages seldom exploit
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
title="Recursion vs Iteration"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/"
display-uri="focs-recursion-vs-iteration"
type="local">tail-recursion</fr:link>.</html:p><html:p>Early programming languages provided little support for repetition.  The
programmer had to set up loops using goto commands, exiting the loop using
another goto controlled by an <html:code>if</html:code>.  Modern languages provide a
confusing jumble of looping constructs, the most fundamental of which is
<html:code>while B do C</html:code>.  The boolean expression <fr:tex
display="inline"><![CDATA[B]]></fr:tex> is evaluated,
and if true, command <fr:tex
display="inline"><![CDATA[C]]></fr:tex> is executed and the command repeats.  If <fr:tex
display="inline"><![CDATA[B]]></fr:tex>
evaluates to false then the <html:code>while</html:code> command terminates, perhaps without
executing <fr:tex
display="inline"><![CDATA[C]]></fr:tex> even once.</html:p><html:p>OCaml’s main looping construct is <html:code>while</html:code>, which returns the value <html:code>()</html:code>.  The
function <html:code>length</html:code> declares <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> to hold the list under
examination (<html:code>lp</html:code>) and number of elements counted so far (<html:code>np</html:code>) as well
as whether the end of the list has been reached (the boolean reference <html:code>fin</html:code>).
While the list is non-empty, we skip over one more element (by setting it to
its tail) and count that element.</html:p><html:p>The body of the <html:code>while</html:code> loop first checks to see if the end of the list has
been reached, in which case it sets the <html:code>fin</html:code> variable to true.  If there is a
tail value, then two assignments are executed in sequence.  The <html:code>lp</html:code> reference
is set to the tail of the list, and the <html:code>np</html:code> reference integer is incremented
by one.  When the while loop terminates due to the <html:code>fin</html:code> variable being set to
true, the expression <html:code>!np</html:code> returns the computed length as the function’s
result.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/</fr:uri><fr:display-uri>focs-def-mutable-reference</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/</fr:route><fr:title
text="Mutable reference">Mutable reference</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A reference is a cell in the store, also called a “location”: <html:code>ref E</html:code>
creates a reference with initial contents the value of <html:code>E</html:code>, <html:code>!P</html:code>
returns the current contents of reference <html:code>P</html:code> (an operation called
<html:em>dereferencing</html:em>), and <html:code>P := E</html:code> updates the contents of <html:code>P</html:code> to the
value of <html:code>E</html:code>. If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is some OCaml type, then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>ref</html:code> is the
type of references to cells that can hold values of <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local">OCaml Primitives for References</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/</fr:uri><fr:display-uri>focs-array-primitives</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-array-primitives/</fr:route><fr:title
text="OCaml Primitives for Arrays">OCaml Primitives for Arrays</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# [|"a"; "b"; "c"|] (* allocate a fresh string array *)
- : string array = [|"a"; "b"; "c"|]
# Array.make 3 'a'   (* array[3] with cell containing 'a' *)
- : char array = [|'a'; 'a'; 'a'|]
# let aa = Array.init 5 (fun i -> i * 10) (* array[5] initialised to (fun i) *)
val aa : int array = [|0; 10; 20; 30; 40|]
# Array.get aa 3  (* retrieve the 4th cell in the array *)
- : int = 30
# Array.set aa 3 42 (* set the 4th cell's value to 42 *)
- : unit = ()]]></html:pre><html:p>There are many other array operations in the <html:code>Array</html:code> module in the OCaml standard
library.</html:p><html:pre><![CDATA[# Array.make
- : int -> 'a -> 'a array = <fun>
# Array.init
- : int -> (int -> 'a) -> 'a array = <fun>
# Array.get
- : 'a array -> int -> 'a = <fun>
# Array.set
- : 'a array -> int -> 'a -> unit = <fun>]]></html:pre><html:p>OCaml arrays are like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> that hold several elements instead of one.  The
elements of an <fr:tex
display="inline"><![CDATA[n]]></fr:tex>-element array are designated by the integers from 0
to <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex>.  The <fr:tex
display="inline"><![CDATA[i]]></fr:tex>th array element is usually written <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex>.
If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is a type then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>array</html:code> is the
type of arrays (of any size) with elements from <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.</html:p><html:p>Calling <html:code>Array.init n f</html:code> creates an array of the size specified in <fr:tex
display="inline"><![CDATA[n]]></fr:tex>
by function <fr:tex
display="inline"><![CDATA[f]]></fr:tex>.  Initially, element <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex> holds the value of <fr:tex
display="inline"><![CDATA[f(i)]]></fr:tex> for <fr:tex
display="inline"><![CDATA[i=0]]></fr:tex>, …, <fr:tex
display="inline"><![CDATA[n-1]]></fr:tex>.
Like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local"><html:code>ref</html:code></fr:link>, it allocates mutable storage to hold the specified values.</html:p><html:p>Calling <html:code>Array.get A i</html:code> returns the contents of <fr:tex
display="inline"><![CDATA[A.(i)]]></fr:tex>.</html:p><html:p>Calling <html:code>Array.set A i E</html:code> modifies the array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by storing the
value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as the new contents of <fr:tex
display="inline"><![CDATA[A[i]]]></fr:tex>; it returns <html:code>()</html:code> as its value.</html:p><html:p>OCaml’s arrays are much safer than C’s. In C, an array is nothing more than an
address indicating the start of a storage area. Nothing indicates the size of
the area.  Therefore C programs are vulnerable to <html:em>buffer overrun attacks:</html:em> an
attacker sends more data than the receiving program expects, overrunning the
area of storage set aside to hold it. The attack eventually overwrites the
program itself, replacing it with code controlled by the attacker.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/</fr:uri><fr:display-uri>focs-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references/</fr:route><fr:title
text="OCaml Primitives for References">OCaml Primitives for References</fr:title></fr:frontmatter><fr:mainmatter><html:table>
  <html:tr><html:th>Syntax</html:th><html:th>Effect</html:th></html:tr>
  <html:tr><html:td><html:code>ref E</html:code></html:td><html:td><html:em>create</html:em> a reference with <html:em>initial contents</html:em> = value of <html:code>E</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>!P</html:code></html:td><html:td>return <html:em>current contents</html:em> of reference <html:code>P</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>P := E</html:code></html:td><html:td><html:em>update</html:em> contents of <html:code>P</html:code> to value of <html:code>E</html:code></html:td></html:tr>
</html:table><html:p>The above text presents the OCaml primitives, but most languages have analogues of
them, often heavily disguised.  We need a means of creating references (or
allocating storage), getting at the current contents of a reference cell, and
updating that cell.</html:p><html:p>The function <html:code>ref</html:code> creates references (also called
“locations”).  Calling <html:code>ref</html:code> allocates a new location in memory.
Initially, this location holds the value given by
expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p><html:p>The function <html:code>!</html:code>, when applied to a reference, returns its contents.
This operation is called <html:em>dereferencing</html:em>.  Clearly <html:code>!</html:code> is not a
mathematical function; its result depends upon the store.</html:p><html:p>The assignment <html:code>P:=E</html:code> evaluates expression <fr:tex
display="inline"><![CDATA[P]]></fr:tex>, which must return a
reference <fr:tex
display="inline"><![CDATA[p]]></fr:tex>, and <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.  It stores at address <fr:tex
display="inline"><![CDATA[p]]></fr:tex> the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.
Syntactically, <html:code>:=</html:code> is a function and <html:code>P:=E</html:code> is an
expression, even though it updates the store.  Like many functions that change
the state, it returns the value <html:code>()</html:code> of type <html:code>unit</html:code>.</html:p><html:p>If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is some OCaml type, then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>ref</html:code> is the type of references
to cells that can hold values of <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.  Please do not confuse the type
<html:code>ref</html:code> with the function <html:code>ref</html:code>.  This table of the primitive
functions and their types might be useful:</html:p><html:table>
  <html:tr><html:th>Syntax</html:th><html:th>OCaml Type</html:th></html:tr>
  <html:tr><html:td><html:code>ref</html:code></html:td><html:td><html:code>'a -&gt; 'a ref</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>!</html:code></html:td><html:td><html:code>'a ref -&gt; 'a</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>:=</html:code></html:td><html:td><html:code>'a ref -&gt; 'a -&gt; unit</html:code></html:td></html:tr>
</html:table></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/</fr:uri><fr:display-uri>focs-private-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-private-references/</fr:route><fr:title
text="Private, Persistent References">Private, Persistent References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# exception TooMuch of int
exception TooMuch of int
# let makeAccount initBalance =
    let balance = ref initBalance in
    let withdraw amt =
       if amt > !balance then
         raise (TooMuch (amt - !balance))
       else begin
         balance := !balance - amt;
         !balance
       end
    in
    withdraw
val makeAccount : int -> int -> int = <fun>]]></html:pre><html:p>As you may have noticed, OCaml’s programming style looks clumsy compared with
that of languages like C.  OCaml omits the defaults and abbreviations they
provide to shorten programs.  However, OCaml’s explicitness makes it ideal for
teaching the fine points of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link> and arrays.  OCaml’s references are more
flexible than those found in other languages.</html:p><html:p>The function <html:code>makeAccount</html:code> models a bank.  Calling the function with a
specified initial balance creates a new reference (<html:code>balance</html:code>) to
maintain the account balance and returns a function (<html:code>withdraw</html:code>) having
sole access to that reference.  Calling <html:code>withdraw</html:code> reduces the balance
by the specified amount and returns the new balance.  You can pay money in by
withdrawing a negative amount.  The <html:code>if</html:code>-construct prevents the account
from going overdrawn, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
title="Exceptions in OCaml"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ocaml-exceptions/"
display-uri="focs-ocaml-exceptions"
type="local">raising an exception</fr:link>.</html:p><html:p>Look at the <fr:tex
display="inline"><![CDATA[E_1; E_2]]></fr:tex> sequence inside <html:code>begin</html:code> … <html:code>end</html:code> in the <html:em>else</html:em> part above.
The first expression updates the account balance and returns the trivial
value ().  The second expression, <html:code>!balance</html:code>, returns the current
balance but does not return the reference itself: that would allow
unauthorised updates.</html:p><html:p>This example is based on one by Dr A C Norman.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural-programming/</fr:uri><fr:display-uri>focs-procedural-programming</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-procedural-programming/</fr:route><fr:title
text="Procedural Programming">Procedural Programming</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Procedural programs can change the machine state.</html:li>
  <html:li>They can interact with its environment</html:li>
  <html:li>They use control structures like branching, iteration and procedures.</html:li></html:ul><html:p>They use data abstractions of the computer’s memory:</html:p><html:ul><html:li><html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link></html:em> to memory cells</html:li>
  <html:li><html:em>arrays</html:em> that are blocks of memory cells</html:li>
  <html:li><html:em>linked structures</html:em> such as <html:em>linked lists</html:em></html:li></html:ul><html:p>Procedural programming is programming in the traditional sense of the word.  A
program <html:em>state</html:em> is repeatedly transformed by the execution of
<html:em>commands</html:em> or <html:em>statements</html:em>.  A state change might be local to the
machine and consist of updating a variable or array.  A state change might
consist of sending data to the outside world.  Even reading data counts as a
state change, since this act normally removes the data from the environment.</html:p><html:p>Procedural programming languages provide primitive commands and control
structures for combining them.  The primitive commands include
<html:em>assignment</html:em> for updating variables, and various <html:em>input/output</html:em>
commands for communication.  Control structures include <html:code>if</html:code> and
<html:code>match</html:code> constructs for conditional execution, and repetitive constructs
such as <html:code>while</html:code>.  Programmers can package up their own commands as
<html:em>procedures</html:em> taking arguments.  The need for such “subroutines” was
evident from the earliest days; they represent one of the first
examples of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstraction</fr:link> in programming languages.</html:p><html:p>OCaml makes no distinction between commands and expressions. OCaml provides built-in
‘functions’ to perform assignment and communication, and these can be used
in the traditional (procedural) style. OCaml programmers often follow a
functional style for most internal computations and use imperative features
mainly for communication with the outside world.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/</fr:uri><fr:display-uri>focs-recursion-vs-iteration</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-recursion-vs-iteration/</fr:route><fr:title
text="Recursion vs Iteration">Recursion vs Iteration</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>“Iterative” normally refers to a loop, coded using <html:code>while</html:code> for example (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural/"
title="Elements of Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural/"
display-uri="focs-procedural"
type="local">final lecture</fr:link>)</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
title="Tail recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-tail-recursion/"
display-uri="focs-def-tail-recursion"
type="local">Tail-recursion</fr:link> is only efficient if the compiler detects it</html:li>
  <html:li>Mainly it saves space (memory), though iterative code can also run faster</html:li>
  <html:li>Do not make programs iterative unless the gain is worth it</html:li></html:ul><html:p>A <fr:link
href="https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs"
type="external">classic book</fr:link>
by Abelson and Sussman, which describes the Lisp dialect known as Scheme,
used <html:em>iterative</html:em> to mean <html:em>tail-recursive</html:em>. Iterative functions produce computations
resembling those that can be done using while-loops in conventional languages.</html:p><html:p>Many algorithms can be expressed naturally using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>, but only awkwardly
using iteration. There is a story that Dijkstra sneaked recursion into Algol-60
by inserting the words “any other occurrence of the procedure name denotes
execution of the procedure.” By not using the word “recursion”, he managed to
slip this amendment past sceptical colleagues.</html:p><html:p>Obsession with tail recursion leads to a coding style in which functions
have many more arguments than necessary.  Write straightforward code first,
avoiding only gross inefficiency.  If the program turns out to be too slow,
tools are available for pinpointing the cause.  Always remember KISS (Keep
It Simple, Stupid).</html:p><html:p>I hope you have all noticed by now that the summation can be done even more
efficiently using the arithmetic progression formula:</html:p><fr:tex
display="block"><![CDATA[1+\cdots +n = n(n+1)/2]]></fr:tex></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:uri><fr:display-uri>focs-references-comparison</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-comparison/</fr:route><fr:title
text="References: OCaml vs conventional languages">References: OCaml vs conventional languages</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>We must write <html:code>!p</html:code> to get the <html:em>contents</html:em> of <html:code>p</html:code></html:li>
  <html:li>We write just <html:code>p</html:code> for the <html:em>address</html:em> of <html:code>p</html:code></html:li>
  <html:li>We can store private <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference cells</fr:link> (like <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>balance</html:code></fr:link>) in functions—analogous to elements of <html:em>object-oriented programming</html:em></html:li>
  <html:li>OCaml’s assignment syntax is <fr:tex
display="inline"><![CDATA[\tt  V \, := \, E]]></fr:tex> instead of <fr:tex
display="inline"><![CDATA[V]]></fr:tex> = <fr:tex
display="inline"><![CDATA[E]]></fr:tex></html:li>
  <html:li>OCaml has few control structures: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-while/"
title="Iteration: the while command"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-while/"
display-uri="focs-while"
type="local"><html:code>while</html:code></fr:link>, <html:code>match</html:code>, <html:code>if</html:code> and <html:code>for</html:code> (the latter is not covered in this course)</html:li>
  <html:li>OCaml has syntax for updating an array via the <html:code>a.(i) &lt;- v</html:code> syntax which is the same as <fr:link
href="/teaching/2627/FoundsCS/forest/focs-array-primitives/"
title="OCaml Primitives for Arrays"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-array-primitives/"
display-uri="focs-array-primitives"
type="local"><html:code>Array.set a i v</html:code></fr:link>.</html:li></html:ul><html:p>Conventional syntax for variables and assignments has hardly changed since
Fortran, the first high-level language. In conventional languages,
virtually all variables can be updated.  We declare something like
<html:code>p: int</html:code>, mentioning no reference type even if the language provides
them.  If we do not specify an initial value, we may get whatever bits were
previously at that address.  Illegal values arising from uninitialised
variables can cause errors that are almost impossible to diagnose.</html:p><html:p>Dereferencing operators (like OCaml’s <html:code>!</html:code>) are especially unpopular, because
they clutter the program text. Virtually all programming languages make dereferencing
implicit (that is, automatic).</html:p><html:p>It is generally accepted these days that a two-dimensional array <fr:tex
display="inline"><![CDATA[A]]></fr:tex> is nothing
but an array of arrays.  An assignment to such an array is typically written
something like <fr:tex
display="inline"><![CDATA[A[i,j] {:=} x]]></fr:tex>; in C, the syntax is <html:code>A[i][j] = x</html:code>. Higher
dimensions are treated analogously.  The corresponding OCaml code can either
declare an array of arrays, or use the <html:code>A.(i)</html:code> syntax to calculate the linear
offset into a single array.</html:p><html:p>You can use the constructs we have learnt to easily create linked (mutable) lists as
an alternative to arrays.</html:p><html:pre><![CDATA[# type 'a mlist =
  | Nil
  | Cons of 'a * 'a mlist ref
type 'a mlist = Nil | Cons of 'a * 'a mlist ref]]></html:pre><html:p>It is worth mentioning that OCaml’s references fully suffice for coding the sort of linked data structures
taught in algorithms courses, as the <html:code>mlist</html:code> type above illustrates. The
programming style is a little different from the usual, but the principles are
the same.  OCaml also provides comprehensive input/output primitives for various
types of file and operating system.</html:p><html:p>OCaml’s system of modules include <html:em>structures,</html:em> which can be seen as encapsulated
groups of declarations, and <html:em>signatures,</html:em> which are specifications of
structures listing the name and type of each component.  Finally, there are
<html:em>functors,</html:em> which are analogous to functions that combine a number of argument
structures, and which can be used to plug program components together. These
primitives are useful for managing large programming projects.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-examples/</fr:uri><fr:display-uri>focs-references-examples</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-examples/</fr:route><fr:title
text="Trying Out References">Trying Out References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let p = ref 5 (* create a reference *)
val p : int ref = {contents = 5}
# p := !p + 1   (* p now holds value 6 *)
- : unit = ()
# let ps = [ ref 77; p ]
val ps : int ref list = [{contents = 77}; {contents = 6}]
# List.hd ps := 3
- : unit = ()
# ps
- : int ref list = [{contents = 3}; {contents = 6}]]]></html:pre><html:p>The first line declares <html:code>p</html:code> to hold a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference</fr:link> to an integer,
initially 5.  Its type is <html:code>int ref</html:code>, not just <html:code>int</html:code>, so it
admits assignment.  Assignment never changes <html:code>let</html:code> bindings: they are
<html:em>immutable</html:em>.  The identifier <html:code>p</html:code> will always denote the reference
mentioned in its declaration unless superseded by a new usage of <html:code>p</html:code>.
Only the <html:em>contents</html:em> of the reference is mutable.</html:p><html:p>OCaml displays a reference value as <html:code><![CDATA[{contents=v}]]></html:code>, where value <fr:tex
display="inline"><![CDATA[v]]></fr:tex> is the
contents.  This notation is readable but gives us no way of telling whether
two references holding the same value are actually the same reference.  To
display a reference as a machine address has obvious drawbacks!</html:p><html:p>In the first assignment, the expression <html:code>!p</html:code> yields the reference’s
current contents, namely 5.  The assignment changes the contents of <html:code>p</html:code>
to 6.  Most languages do not have an explicit dereferencing operator
(like <html:code>!</html:code>) because of its inconvenience.  Instead, by convention,
occurrences of the reference on the <html:em>left-hand</html:em> side of the <html:code>:=</html:code>
denote locations and those on the <html:em>right-hand</html:em> side denote the contents.
A special ‘address of’ operator may be available to override the convention
and make a reference on the right-hand side to denote a location.  Logically
this is a mess, but it makes programs shorter.</html:p><html:p>The list <html:code>ps</html:code> is declared to hold a new reference (initially
containing 77) as well as <html:code>p</html:code>.  Then the new reference is
updated to hold 3.  The assignment to <html:code>hd ps</html:code> does <html:em>not</html:em>
update <html:code>ps</html:code>, only the contents of a reference in that list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-bank-accounts/</fr:uri><fr:display-uri>focs-bank-accounts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-bank-accounts/</fr:route><fr:title
text="Two Bank Accounts">Two Bank Accounts</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let student = makeAccount 500
val student : int -> int = <fun>
# let director = makeAccount 4000000
val director : int -> int = <fun>
# student 5        (* coach fare *)
- : int = 495
# director 150000  (* Tesla *)
- : int = 3850000
# student 500      (* oh oh *)
Exception: TooMuch 5.]]></html:pre><html:p>Each call to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-private-references/"
title="Private, Persistent References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-private-references/"
display-uri="focs-private-references"
type="local"><html:code>makeAccount</html:code></fr:link> returns a copy of <html:code>withdraw</html:code> holding
a <html:em>fresh</html:em> instance of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference</fr:link> <html:code>balance</html:code>.  As with a real bank
pass-book, there is no access to the account balance except via the
corresponding <html:code>withdraw</html:code> function.  If that function is discarded, the
reference cell becomes unreachable; the computer will eventually reclaim it,
just as banks close down dormant accounts.</html:p><html:p>Here we see two people managing their accounts.  For better or worse, neither
can take money from the other.</html:p><html:p>We could generalise <html:code>makeAccount</html:code> to return several functions that
jointly manage information held in shared references.  The functions might be
packaged using OCaml records, which are not discussed in this course.
Most procedural languages do not properly support the concept of private
references, although <html:em>object-oriented</html:em> languages take them as a basic theme.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-3/</fr:uri><fr:display-uri>focs-ex-11-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-3/</fr:route><fr:title
text="Exercises › Effects in a while condition"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Effects in a while condition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>What is the effect of <fr:tex
display="inline"><![CDATA[\tt  while \, C_1; \; B \, do \, C_2 \, done]]></fr:tex> ?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-4/</fr:uri><fr:display-uri>focs-ex-11-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-4/</fr:route><fr:title
text="Exercises › Exchanging two references"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Exchanging two references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a function to exchange the values of two <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">references</fr:link>, <html:code>xr</html:code> and <html:code>yr</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:uri><fr:display-uri>focs-ex-11-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-2/</fr:route><fr:title
text="Exercises › Iterative power with while"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Iterative power with while</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Write a version of function <html:code>power</html:code> (<fr:link
href="/teaching/2627/FoundsCS/forest/focs-intro/"
title="Introduction to Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro"
type="local">Lecture <fr:contextual-number
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-intro/"
display-uri="focs-intro" /></fr:link>) using <html:code>while</html:code> instead of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-recursion/"
title="Recursion"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-recursion/"
display-uri="focs-def-recursion"
type="local">recursion</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:uri><fr:display-uri>focs-ex-11-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:route><fr:title
text="Exercises › Lists of references"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Lists of references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Comment, with examples, on the differences between an <html:code>int ref list</html:code> and an <html:code>int list ref</html:code>.</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-types/</fr:uri><fr:display-uri>focs-topic-types</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-types/</fr:route><fr:title
text="Types">Types</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-constructors-args/</fr:uri><fr:display-uri>focs-constructors-args</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-constructors-args/</fr:route><fr:title
text="A Datatype whose Constructors have Arguments">A Datatype whose Constructors have Arguments</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike of int
               | Car       of bool
               | Lorry     of int
type vehicle = Bike | Motorbike of int | Car of bool | Lorry of int]]></html:pre><html:ul><html:li>Constructors with arguments (like <html:code>Lorry</html:code>) are <html:em>distinct values</html:em>. (So <html:code>Car true</html:code> is distinct from <html:code>Car false</html:code>).</html:li>
  <html:li>Different kinds of <html:code>vehicle</html:code> can belong to one list: <html:code>[Bike; Car true; Motorbike 450]</html:code></html:li></html:ul><html:p>OCaml generalises the notion of enumeration type to allow data to be associated
with each constructor.  The constructor <html:code>Bike</html:code> is a vehicle all by itself, but
the other three constructors create vehicles from arguments.</html:p><html:p>Since we might find it hard to remember what the various <html:code>int</html:code> and
<html:code>bool</html:code> components are for, it is wise to include <html:em>comments</html:em> in
complex declarations.  In OCaml, comments are enclosed in the brackets
<html:code><![CDATA[(*]]></html:code> and <html:code><![CDATA[*)]]></html:code>. Programmers should comment their code to explain
design decisions and key features of the algorithms (sometimes by citing a
reference work).</html:p><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike of int  (* engine size in CCs *)
               | Car       of bool (* true if a Reliant Robin *)
               | Lorry     of int  (* number of wheels *)
type vehicle = Bike | Motorbike of int | Car of bool | Lorry of int]]></html:pre><html:p>The list <html:code>[Bike; Car true; Motorbike 450]</html:code> represents a bicycle, a Reliant Robin and a large
motorbike.  It can be almost seen as a mixed-type list containing integers and
booleans.  It is actually a list of vehicles; datatypes lessen the impact of
the restriction that all list elements must have the same type.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-first-session/</fr:uri><fr:display-uri>focs-first-session</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-first-session/</fr:route><fr:title
text="A first session with OCaml">A first session with OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let pi = 3.14159265358979
val pi : float = 3.14159265358979]]></html:pre><html:p>The first line of this simple session is a <html:em>value declaration</html:em>. It makes the
name <html:code>pi</html:code> stand for the floating point number <html:code>3.14159</html:code>. (Such names are called
<html:em>identifiers</html:em>.)  OCaml echoes the name (<html:code>pi</html:code>) and type (<html:code>float</html:code>) of the
declared identifier.</html:p><html:pre><![CDATA[# pi *. 1.5 *. 1.5
- : float = 7.06858347057702829]]></html:pre><html:p>The second line computes the area of the circle with radius <html:code>1.5</html:code> using the
formula <fr:tex
display="inline"><![CDATA[A = \pi  r^2]]></fr:tex>. We use <html:code>pi</html:code> as an abbreviation for <html:code>3.14159</html:code>.
Multiplication is expressed using <html:code>*.</html:code>, which is called an <html:em>infix operator</html:em>
because it is written between its two operands.</html:p><html:p>OCaml replies with the computed value (about <html:code>7.07</html:code>) and its type (again <html:code>float</html:code>).</html:p><html:pre><![CDATA[# let area r = pi *. r *. r
val area : float -> float = <fun>]]></html:pre><html:p>To work <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstractly</fr:link>, we should provide the service “compute the area of a
circle,” so that we no longer need to remember the formula. This sort of
encapsulated computation is called a <html:em>function</html:em>. The third line declares the
function <html:code>area</html:code>. Given any floating point number <html:code>r</html:code>, it returns another
floating point number computed using the <html:code>area</html:code> formula; note that the function
has type <html:code>float -&gt; float</html:code>.</html:p><html:pre><![CDATA[# area 2.0
- : float = 12.56637061435916]]></html:pre><html:p>The fourth line calls the function <html:code>area</html:code> supplying <html:code>2.0</html:code> as the argument. A
circle of radius <html:code>2</html:code> has an area of about <html:code>12.6</html:code>. Note that brackets around a
function argument are not necessary.</html:p><html:p>The function uses <html:code>pi</html:code> to stand for <html:code>3.14159</html:code>. Unlike what you may have seen in
other programming languages, <html:code>pi</html:code> cannot be "assigned to" or otherwise updated.
Its meaning within <html:code>area</html:code> will persist even if we issue a new <html:code>let</html:code> declaration
for <html:code>pi</html:code> afterwards.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/</fr:uri><fr:display-uri>focs-def-abstraction-barrier</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/</fr:route><fr:title
text="Abstraction barrier">Abstraction barrier</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Large systems can only be understood in levels: the interface to the higher
level should supply the advertised services and, just as important, block access
to the means by which those services are implemented. This abstraction barrier
allows one level to be changed without affecting levels above.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-basic-concepts/"
title="Basic Concepts in Computer Science"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-basic-concepts/"
display-uri="focs-basic-concepts"
type="local">Basic Concepts in Computer Science</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/</fr:uri><fr:display-uri>focs-def-algebraic-datatype</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/</fr:route><fr:title
text="Algebraic datatype">Algebraic datatype</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>OCaml generalises the notion of enumeration type to allow data to be
associated with each constructor: some constructors are values all by themselves,
while others create values from arguments. Constructors with arguments are
<html:em>distinct values</html:em>, and values built from different constructors of one
datatype can belong to a single list.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-constructors-args/"
title="A Datatype whose Constructors have Arguments"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-constructors-args/"
display-uri="focs-constructors-args"
type="local">A Datatype whose Constructors have Arguments</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-enumeration/</fr:uri><fr:display-uri>focs-enumeration</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-enumeration/</fr:route><fr:title
text="An Enumeration Type">An Enumeration Type</fr:title></fr:frontmatter><fr:mainmatter><html:p>We will now learn how to define more expressive types than the
basic ones supplied with the core OCaml language.</html:p><html:pre><![CDATA[# type vehicle = Bike
               | Motorbike
               | Car
               | Lorry
type vehicle = Bike | Motorbike | Car | Lorry]]></html:pre><html:ul><html:li>We have declared a <html:em>new type</html:em> named <html:code>vehicle</html:code>.</html:li>
  <html:li><fr:tex
display="inline"><![CDATA[\ldots ]]></fr:tex> along with four new constants.</html:li>
  <html:li>They are the <html:em>constructors</html:em> of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">datatype</fr:link>.</html:li></html:ul><html:p>The <html:code>type</html:code> declaration adds a new type to our OCaml session.  Type
<html:code>vehicle</html:code> is as good as any built-in type and even admits
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link> (as we used with the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-list-primitives/"
title="The List Primitives"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-list-primitives/"
display-uri="focs-list-primitives"
type="local">built-in list types</fr:link> earlier).
The four new identifiers of type <html:code>vehicle</html:code> are called <html:em>constructors</html:em>.</html:p><html:p>We could represent the various vehicles by the numbers 0–3.  However, the code would be
hard to read and even harder to maintain.  Consider adding <html:code>Tricycle</html:code>
as a new vehicle. If we wanted to add it before <html:code>Bike</html:code>, then all the
numbers would have to be changed.  Using <html:code>type</html:code>, such additions are
trivial and the compiler can (at least sometimes) warn us when it encounters a
function declaration that doesn’t yet have a case for <html:code>Tricycle</html:code>.</html:p><html:p>Representing vehicles by strings like <html:code>"Bike"</html:code>, <html:code>"Car"</html:code>, etc.,
is also bad.  Comparing string values is slow and the compiler
can’t warn us of misspellings like <html:code>"MOtorbike"</html:code>: they will make our
code fail.</html:p><html:p>Most programming languages allow the declaration of types like
<html:code>vehicle</html:code>.  Because they consist of a series of identifiers, they are
called <html:em>enumeration types</html:em>.  Other common examples are days of the week
or colours.  The compiler chooses the integers for us; type-checking prevents
us from confusing <html:code>Bike</html:code> with <html:code>Red</html:code> or <html:code>Sunday</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-basic-concepts/</fr:uri><fr:display-uri>focs-basic-concepts</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-basic-concepts/</fr:route><fr:title
text="Basic Concepts in Computer Science">Basic Concepts in Computer Science</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>Computers: a child can use them; <html:strong>nobody</html:strong> can fully understand them!</html:li>
  <html:li>We can master complexity through levels of abstraction.</html:li>
  <html:li>Focus on 2 or 3 levels at most!</html:li></html:ul><html:p><html:strong>Recurring issues:</html:strong></html:p><html:ul><html:li><html:em>what services</html:em> to provide at each level</html:li>
  <html:li><html:em>how to implement</html:em> them using lower-level services</html:li>
  <html:li><html:em>the interface</html:em> that defines how the two levels should communicate</html:li></html:ul><html:p>A basic concept in computer science is that large systems can only be
understood in levels, with each level further subdivided into functions or
services of some sort. The interface to the higher level should supply the
advertised services. Just as important, it should block access to the means by
which those services are implemented. This <html:em>abstraction barrier</html:em> allows one
level to be changed without affecting levels above. For example, when a
manufacturer designs a faster version of a processor, it is essential that
existing programs continue to run on it. Any differences between the old and
new processors should be invisible to the program.</html:p><html:p>Modern processors have elaborate specifications, which still sometimes leave
out important details. In the old days, you then had to consult the circuit
diagrams.</html:p>

<fr:tree
show-metadata="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/</fr:uri><fr:display-uri>focs-dates</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dates/</fr:route><fr:title
text="Example 1: Dates">Example 1: Dates</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">Abstract level</fr:link>: dates over a certain interval</html:li>
  <html:li>Concrete level: could be 6 characters: <html:code>YYMMDD</html:code> (where each character is represented by 8 bits)</html:li>
  <html:li>Date crises caused by <html:strong>inadequate</html:strong> internal formats:
    <html:ul><html:li>Digital’s PDP-10: using 12-bit dates (good for at most 11 years)</html:li>
      <html:li>2000 crisis: 48 bits could be good for lifetime of universe!</html:li></html:ul></html:li></html:ul><html:p>Digital Equipment Corporation’s date crisis occurred in 1975.  The
PDP-10 was a 36-bit mainframe computer. It represented dates using a 12-bit
format designed for the tiny PDP-8. With 12 bits, one can distinguish
<fr:tex
display="inline"><![CDATA[2^{12} = 4096]]></fr:tex> days or 11 years.</html:p><html:p>Last century, the most common industry format for dates used six characters: two for the
year, two for the month and two for the day. The most common “solution” to the
year 2000 crisis is to add two further characters, thereby altering file sizes.
Others have noticed that the existing six characters consist of 48 bits,
already sufficient to represent all dates over the projected lifetime of the
universe: <fr:tex
display="inline"><![CDATA[2^{48}]]></fr:tex> = <fr:tex
display="inline"><![CDATA[2.8\times  10^{14}]]></fr:tex> days = <fr:tex
display="inline"><![CDATA[7.7\times  10^{11}]]></fr:tex> years!</html:p><html:p>Mathematicians think in terms of unbounded ranges, but the representation we
choose for the computer usually imposes hard limits. A good programming
language like OCaml lets one easily change the representation used in the
program.  But if files in the old representation exist all over the place,
there will still be conversion problems. The need for compatibility with older
systems causes problems across the computer industry.</html:p></fr:mainmatter></fr:tree>
<fr:tree
show-metadata="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/</fr:uri><fr:display-uri>focs-floating-point</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-floating-point/</fr:route><fr:title
text="Example 2: Floating Point Numbers">Example 2: Floating Point Numbers</fr:title></fr:frontmatter><fr:mainmatter><html:p>Computers have integers like <html:code>1066</html:code> and floats like <fr:tex
display="inline"><![CDATA[1.066\times  10^3]]></fr:tex>.
A floating-point number is represented by two integers.
The concept of <html:em>data type</html:em> involves:</html:p><html:ul><html:li>how a value is represented inside the computer</html:li>
  <html:li>the suite of operations given to programmers</html:li>
  <html:li>valid and invalid (or exceptional) results, such as “infinity”</html:li></html:ul><html:p>Computer arithmetic can yield <html:em>incorrect answers!</html:em></html:p><html:p>In science, numbers written with finite precision and a decimal exponent are
said to be in <html:em>standard form</html:em>. The computational equivalent is the <html:em>floating
point number</html:em>. These are familiar to anybody who has used a scientific
calculator.  Internally, a float consists of two integers.</html:p><html:p>Because of its finite precision, floating-point computations are potentially
inaccurate. To see an example, use your nearest electronic calculator to
compute <fr:tex
display="inline"><![CDATA[(2^{1/10000})^{10000}]]></fr:tex>. I get <fr:tex
display="inline"><![CDATA[1.99999959]]></fr:tex>! With certain computations,
the errors spiral out of control. Many programming languages fail to check
whether even integer computations fall within the allowed range: you can add
two positive integers and get a negative one!</html:p><html:p>Most computers give us a choice of precisions. In 32-bit precision, integers
typically range from <fr:tex
display="inline"><![CDATA[2^{31}-1]]></fr:tex> (namely 2 147 483 647) to <fr:tex
display="inline"><![CDATA[-2^{31}]]></fr:tex>; floats
are accurate to about six decimal places and can get as large as <fr:tex
display="inline"><![CDATA[10^{35}]]></fr:tex> or so.
For floats, 64-bit precision is often preferred. Early languages like Fortran
required variables to be declared as <html:code>INTEGER</html:code>, <html:code>REAL</html:code> or <html:code>COMPLEX</html:code> and barred
programmers from mixing numbers in a computation. Nowadays, programs handle
many different kinds of data, including text and symbols. The concept of a
<html:em>data type</html:em> can ensure that different types of data are not combined in a
senseless way.</html:p><html:p>Inside the computer, all data are stored as bits. In most programming
languages, the compiler uses types to generate correct machine code, and types
are not stored during program execution. In this course, we focus almost
entirely on programming in a high-level language: OCaml.</html:p></fr:mainmatter></fr:tree>
</fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-vehicles/</fr:uri><fr:display-uri>focs-vehicles</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-vehicles/</fr:route><fr:title
text="Declaring a Function on Vehicles">Declaring a Function on Vehicles</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let wheels = function
  | Bike -> 2
  | Motorbike -> 2
  | Car -> 4
  | Lorry -> 18
val wheels : vehicle -> int = <fun>]]></html:pre><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
title="Algebraic datatype"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-algebraic-datatype/"
display-uri="focs-def-algebraic-datatype"
type="local">Datatype constructors</fr:link> can be used in patterns.</html:li>
  <html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">Pattern-matching</fr:link> is fast, even complicated nested patterns.</html:li>
  <html:li>Notice the type of the argument is <html:code>vehicle</html:code>, which we defined earlier.</html:li></html:ul><html:p>The beauty of datatype declarations is that the new types behave as if they
were built into OCaml. Type-checking catches common errors, such as mixing up
different datatypes in a function like <html:code>wheels</html:code>, as well as missing
and redundant patterns.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:uri><fr:display-uri>focs-dictionary-adt</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dictionary-adt/</fr:route><fr:title
text="Dictionaries">Dictionaries</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>lookup: find an item in the dictionary</html:li>
<html:li>update (insert): replace (store) an item in the dictionary</html:li>
<html:li>delete: remove an item from the dictionary</html:li>
<html:li>empty: the null dictionary</html:li>
<html:li>Missing: <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> for errors in <html:code>lookup</html:code> and <html:code>delete</html:code></html:li></html:ul><html:p>Ideally, an <html:em>abstract type</html:em> should provide these operations and hide the internal data structures.</html:p><html:p>A dictionary attaches values to identifiers, called “keys”.  Before choosing
the internal representation for a data structure, you need to specify the full
set of operations. In fact, here we only consider <html:code>update</html:code> (associating a
value with an identifier) and <html:code>lookup</html:code> (retrieving such a value). Deletion
is more difficult and would limit our choices. Some applications may need
additional operations, such as <html:code>merge</html:code> (combining two dictionaries). We
shall see that update can be done efficiently in a functional style, without
excessive copying.</html:p><html:p>An <html:em>abstract type</html:em> provides specified operations while hiding low-level
details, such as the data structure used to represent dictionaries. Abstract
types can be declared in any modern programming language. Java’s <html:em>objects</html:em>
serve this role, as do OCaml’s modules. This course does not cover modules, and we
simply declare the dictionary operations individually.</html:p><html:p>An <html:em>association list</html:em> (a list of pairs) is the simplest dictionary representation.
Lookup is by <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link>, and therefore slow: <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>. Association lists are
only usable if there are few keys in use. However, they are general in that the
keys do not need a concept of ordering, only equality.</html:p><html:pre><![CDATA[# exception Missing
exception Missing
# let rec lookup a = function
  | [] -> raise Missing
  | (x, y) :: pairs ->
      if a = x then y
      else lookup a pairs
val lookup : 'a -> ('a * 'b) list -> 'b = <fun>
# let update (l, b, y) = (b, y) :: l
val update : ('a * 'b) list * 'a * 'b -> ('a * 'b) list = <fun>]]></html:pre><html:p>To enter a new <html:code>(key, value)</html:code> pair, simply “cons” it to the list with <html:code>update</html:code>.
This takes constant time, which is the best we could hope for.  But the space
requirement is huge: linear in the number of updates, not in the number of
distinct keys. Obsolete entries are never deleted: that would require first
finding them, increasing the update time from <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex> to <fr:tex
display="inline"><![CDATA[O(n)]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/</fr:uri><fr:display-uri>focs-equality</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-equality/</fr:route><fr:title
text="Equality Tests">Equality Tests</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec member x = function
   | [] -> false
   | y::l ->
      if x = y then true
      else member x l
val member : 'a -> 'a list -> bool = <fun>]]></html:pre><html:p>All the list functions we have encountered up to now have been “<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic</fr:link>”,
working for lists of any type.  Function <html:code>member</html:code> uses <fr:link
href="/teaching/2627/FoundsCS/forest/focs-linear-search/"
title="Linear Search"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-linear-search/"
display-uri="focs-linear-search"
type="local">linear search</fr:link> to report
whether or not <html:code>x</html:code> occurs in <html:code>l</html:code>.</html:p><html:p>To do this generically, it uses a special feature of OCaml known as
“polymorphic equality”, which manifests itself via the <html:code>=</html:code>, <html:code>&gt;=</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code> and
<html:code>&lt;</html:code> operators.  These operators inspect the <html:em>structure</html:em> of the values using a
consistent order.  Types you can legitimately compare this way include integers,
strings, booleans, and tuples or lists of primitive types.</html:p><html:p>More complex types can be compared this way within careful limits: recursive
structures or function values will not work (we will cover function values in
the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-currying/"
title="Curried Functions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/"
display-uri="focs-currying"
type="local">Currying lecture</fr:link> later).  For now, it is sufficient to use these magic
polymorphic equality operators.  As you get more familiar with OCaml and the
use of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-functions/"
title="Functions as Values"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-functions/"
display-uri="focs-functions"
type="local">higher order functions</fr:link> (also covered in a later lecture), you will
encounter the use of explicit <html:code>compare</html:code> functions that are used to provide more
complex equality tests.</html:p><html:p>The presence of polymorphic equality is a contentious feature in OCaml.  While
it provides a great ease of use in smaller codebases, it starts to become more
dangerous when building larger OCaml-based systems.  Most large-scale users of
OCaml tend towards not using it in important code, but it is just fine for our
purposes while learning the beginning steps of computer science.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/</fr:uri><fr:display-uri>focs-dates</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-dates/</fr:route><fr:title
text="Example 1: Dates">Example 1: Dates</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">Abstract level</fr:link>: dates over a certain interval</html:li>
  <html:li>Concrete level: could be 6 characters: <html:code>YYMMDD</html:code> (where each character is represented by 8 bits)</html:li>
  <html:li>Date crises caused by <html:strong>inadequate</html:strong> internal formats:
    <html:ul><html:li>Digital’s PDP-10: using 12-bit dates (good for at most 11 years)</html:li>
      <html:li>2000 crisis: 48 bits could be good for lifetime of universe!</html:li></html:ul></html:li></html:ul><html:p>Digital Equipment Corporation’s date crisis occurred in 1975.  The
PDP-10 was a 36-bit mainframe computer. It represented dates using a 12-bit
format designed for the tiny PDP-8. With 12 bits, one can distinguish
<fr:tex
display="inline"><![CDATA[2^{12} = 4096]]></fr:tex> days or 11 years.</html:p><html:p>Last century, the most common industry format for dates used six characters: two for the
year, two for the month and two for the day. The most common “solution” to the
year 2000 crisis is to add two further characters, thereby altering file sizes.
Others have noticed that the existing six characters consist of 48 bits,
already sufficient to represent all dates over the projected lifetime of the
universe: <fr:tex
display="inline"><![CDATA[2^{48}]]></fr:tex> = <fr:tex
display="inline"><![CDATA[2.8\times  10^{14}]]></fr:tex> days = <fr:tex
display="inline"><![CDATA[7.7\times  10^{11}]]></fr:tex> years!</html:p><html:p>Mathematicians think in terms of unbounded ranges, but the representation we
choose for the computer usually imposes hard limits. A good programming
language like OCaml lets one easily change the representation used in the
program.  But if files in the old representation exist all over the place,
there will still be conversion problems. The need for compatibility with older
systems causes problems across the computer industry.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/</fr:uri><fr:display-uri>focs-floating-point</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-floating-point/</fr:route><fr:title
text="Example 2: Floating Point Numbers">Example 2: Floating Point Numbers</fr:title></fr:frontmatter><fr:mainmatter><html:p>Computers have integers like <html:code>1066</html:code> and floats like <fr:tex
display="inline"><![CDATA[1.066\times  10^3]]></fr:tex>.
A floating-point number is represented by two integers.
The concept of <html:em>data type</html:em> involves:</html:p><html:ul><html:li>how a value is represented inside the computer</html:li>
  <html:li>the suite of operations given to programmers</html:li>
  <html:li>valid and invalid (or exceptional) results, such as “infinity”</html:li></html:ul><html:p>Computer arithmetic can yield <html:em>incorrect answers!</html:em></html:p><html:p>In science, numbers written with finite precision and a decimal exponent are
said to be in <html:em>standard form</html:em>. The computational equivalent is the <html:em>floating
point number</html:em>. These are familiar to anybody who has used a scientific
calculator.  Internally, a float consists of two integers.</html:p><html:p>Because of its finite precision, floating-point computations are potentially
inaccurate. To see an example, use your nearest electronic calculator to
compute <fr:tex
display="inline"><![CDATA[(2^{1/10000})^{10000}]]></fr:tex>. I get <fr:tex
display="inline"><![CDATA[1.99999959]]></fr:tex>! With certain computations,
the errors spiral out of control. Many programming languages fail to check
whether even integer computations fall within the allowed range: you can add
two positive integers and get a negative one!</html:p><html:p>Most computers give us a choice of precisions. In 32-bit precision, integers
typically range from <fr:tex
display="inline"><![CDATA[2^{31}-1]]></fr:tex> (namely 2 147 483 647) to <fr:tex
display="inline"><![CDATA[-2^{31}]]></fr:tex>; floats
are accurate to about six decimal places and can get as large as <fr:tex
display="inline"><![CDATA[10^{35}]]></fr:tex> or so.
For floats, 64-bit precision is often preferred. Early languages like Fortran
required variables to be declared as <html:code>INTEGER</html:code>, <html:code>REAL</html:code> or <html:code>COMPLEX</html:code> and barred
programmers from mixing numbers in a computation. Nowadays, programs handle
many different kinds of data, including text and symbols. The concept of a
<html:em>data type</html:em> can ensure that different types of data are not combined in a
senseless way.</html:p><html:p>Inside the computer, all data are stored as bits. In most programming
languages, the compiler uses types to generate correct machine code, and types
are not stored during program execution. In this course, we focus almost
entirely on programming in a high-level language: OCaml.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-anonymous-functions/</fr:uri><fr:display-uri>focs-anonymous-functions</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-anonymous-functions/</fr:route><fr:title
text="Functions Without Names">Functions Without Names</fr:title></fr:frontmatter><fr:mainmatter><html:p>If functions are to be regarded as computational values, then we need a
notation for them.  The <html:code>fun</html:code> notation expresses a non-recursive function
value without giving the function a name.</html:p><html:p><fr:tex
display="inline"><![CDATA[\tt  fun\;x\;\rightarrow  E]]></fr:tex> is the function <fr:tex
display="inline"><![CDATA[f]]></fr:tex> such that <fr:tex
display="inline"><![CDATA[f(x)=E]]></fr:tex>.
The function <html:code>fun n -&gt; n*2</html:code> is a <html:em>doubling function</html:em>.</html:p><html:pre><![CDATA[# fun n -> n * 2
- : int -> int = <fun>
# (fun n -> n * 2) 17
- : int = 34]]></html:pre><html:p>The main purpose of <html:code>fun</html:code>-notation is to package up small expressions that are to be
applied repeatedly using some other function.
The expression <html:code>fun n -&gt; n*2</html:code> has the same value as the identifier
<html:code>double</html:code>, declared as follows:</html:p><html:pre><![CDATA[# let double n = n * 2
val double : int -> int = <fun>]]></html:pre><html:p>The <html:code>fun</html:code> notation can also do <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern matching</fr:link>, and the <html:code>function</html:code> keyword
adds an anonymous variable name to pattern match against.  The following functions
are all equivalent, with the latter definitions bound to the <html:code>is_zero</html:code> value and the earlier ones anonymous:</html:p><html:pre><![CDATA[# fun x -> match x with 0 -> true | _ -> false
- : int -> bool = <fun>
# function 0 -> true | _ -> false
- : int -> bool = <fun>
# let is_zero = fun x -> match x with 0 -> true | _ -> false
val is_zero : int -> bool = <fun>
# let is_zero = function 0 -> true | _ -> false
val is_zero : int -> bool = <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/</fr:uri><fr:display-uri>focs-head-tail</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-head-tail/</fr:route><fr:title
text="Getting at the Head and Tail">Getting at the Head and Tail</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let null = function
    | [] -> true
    | x :: l -> false
val null : 'a list -> bool = <fun>
# null []
- : bool = true
# null [1; 2; 3]
- : bool = false
# let hd (x::l) = x
Line 1, characters 8-14:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val hd : 'a list -> 'a = <fun>
# hd [1; 2; 3]
- : int = 1
# let tl (x::l) = l
Line 1, characters 8-14:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]

val tl : 'a list -> 'a list = <fun>
# tl [7; 6; 5]
- : int list = [6; 5]]]></html:pre><html:p>The empty list has neither head nor tail.  Applying <html:code>hd</html:code> or <html:code>tl</html:code> to <html:code>[]</html:code>
is an error—strictly speaking, an <fr:link
href="/teaching/2627/FoundsCS/forest/focs-exceptions/"
title="Error Handling: Exceptions"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-exceptions/"
display-uri="focs-exceptions"
type="local">“exception”</fr:link>.  The function <html:code>null</html:code> can
be used to check for the empty list beforehand.  Taking a list apart using
combinations of <html:code>hd</html:code> and <html:code>tl</html:code> is hard to get right.  Fortunately, it is seldom
necessary because of <html:em>pattern-matching</html:em>.</html:p><html:p>The declaration of <html:code>null</html:code> introduces a new concept known as "pattern matching",
which we will explore more in subsequent lectures. For now, it is sufficient
to observe that <html:code>let null = function</html:code> allows for matching on the two possible values
that might be passed in as argument to <html:code>null</html:code> here: one for the empty list (for which it returns <html:code>true</html:code>)
and one for non-empty lists (for which it returns <html:code>false</html:code>).</html:p><html:p>The declaration of <html:code>hd</html:code> above has only one clause, for non-empty lists.  They
have the form <html:code>x::l</html:code> and the function returns <html:code>x</html:code>, which is the head.  If you
compile this program, OCaml also prints a warning to tell us that calling
the function could raise an exception because not all possible inputs are handled,
including a counter-example (in this case, the empty list <html:code>[]</html:code>). The declaration of <html:code>tl</html:code> is similar to <html:code>hd</html:code>.</html:p><html:p>These three primitive functions are <html:em>polymorphic</html:em> and allow flexibility in the
types of their arguments and results. Note their types!</html:p><html:pre><![CDATA[# null
- : 'a list -> bool = <fun>
# hd
- : 'a list -> 'a = <fun>
# tl
- : 'a list -> 'a list = <fun>]]></html:pre><html:p>Symbols <html:code>'a</html:code> and <html:code>'b</html:code> are called <html:em>type variables</html:em> and stand for any types. Code
written using these functions is checked for type correctness at compile time.
And this guarantees strong properties at run time, for example that the
elements of any list all have the same type.  They are usually read as their
corresponding greek characters; <html:code>'a</html:code> is "alpha", <html:code>'b</html:code> is "beta", and so on.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-goals-of-programming/</fr:uri><fr:display-uri>focs-goals-of-programming</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-goals-of-programming/</fr:route><fr:title
text="Goals of Programming">Goals of Programming</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>to describe a computation so that it can be done <html:strong>mechanically</html:strong>:
    <html:ul><html:li>Expressions compute values.</html:li>
      <html:li>Commands cause effects.</html:li></html:ul></html:li>
  <html:li>to do so efficiently and <html:strong>correctly</html:strong>, giving the right answers quickly</html:li>
  <html:li>to allow easy modification as needs change
    <html:ul><html:li>Through an orderly <html:strong>structure</html:strong> based on <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
title="Abstraction barrier"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-abstraction-barrier/"
display-uri="focs-def-abstraction-barrier"
type="local">abstraction principles</fr:link></html:li>
      <html:li>Such as modules or classes</html:li></html:ul></html:li></html:ul><html:p>Programming <html:em>in-the-small</html:em> concerns the writing of code to do simple, clearly
defined tasks. Programs provide expressions for describing mathematical
formulae and so forth. This was the original contribution of FORTRAN, the
FORmula TRANslator. Commands describe how control should flow from one part of
the program to the next.</html:p><html:p>As we code layer upon layer, we eventually find ourselves programming
<html:em>in the large</html:em> : joining large modules to solve some messy task. Programming
languages have used various mechanisms to allow one part of the program to
provide interfaces to other parts. Modules encapsulate a body of code, allowing
outside access only through a programmer-defined interface. <fr:link
href="/teaching/2627/FoundsCS/forest/focs-queue-adt/"
title="An Abstract Data Type: Queues"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-queue-adt/"
display-uri="focs-queue-adt"
type="local"><html:em>Abstract Data
Types</html:em></fr:link> are a simpler version of this concept, which implement a single concept
such as dates or floating-point numbers.</html:p><html:p><html:em>Object-oriented programming</html:em> is the most complicated approach to modularity.
<html:em>Classes</html:em> define concepts, and they can be built upon other classes. Operations
can be defined that work in appropriately specialised ways on a family of
related classes. <html:em>Objects</html:em> are instances of classes and hold the data that is
being manipulated.</html:p><html:p>This course does not cover OCaml’s sophisticated module system, which can do
many of the same things as classes. You will learn all about objects when you
study Java. OCaml includes a powerful object system, although this is not used
as much as its module system.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:uri><fr:display-uri>focs-lazy-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-lazy-ocaml/</fr:route><fr:title
text="Lazy Lists in OCaml">Lazy Lists in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:ul><html:li>The empty tuple <html:code>()</html:code> and its <html:em>type</html:em> <html:code>unit</html:code></html:li>
  <html:li>Delayed version of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> is <html:code>fun () -&gt; E</html:code></html:li></html:ul><html:pre><![CDATA[# type 'a seq =
  | Nil
  | Cons of 'a * (unit -> 'a seq)
type 'a seq = Nil | Cons of 'a * (unit -> 'a seq)
# let head (Cons (x, _)) = x
Line 1, characters 10-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val head : 'a seq -> 'a = <fun>
# let tail (Cons (_, xf)) = xf ()
Line 1, characters 10-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Nil

val tail : 'a seq -> 'a seq = <fun>]]></html:pre><html:p><fr:tex
display="inline"><![CDATA[\tt  Cons(x, xf)]]></fr:tex> has <html:em>head</html:em> <fr:tex
display="inline"><![CDATA[x]]></fr:tex> and <html:em>tail function</html:em> <fr:tex
display="inline"><![CDATA[xf]]></fr:tex></html:p><html:p>The primitive OCaml type <html:code>unit</html:code> has one element, which is
written <html:code>()</html:code>.  This element may be regarded as a 0-tuple, and
<html:code>unit</html:code> as the nullary Cartesian product.  (Think of the connection
between multiplication and the number 1.)</html:p><html:p>The empty tuple serves as a placeholder in situations where no information is
required.  It may:</html:p><html:ul><html:li>appear in a data structure.  For example, a <html:code>unit</html:code>-valued <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
title="Dictionaries"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dictionary-adt/"
display-uri="focs-dictionary-adt"
type="local">dictionary</fr:link> represents a set of keys.</html:li>
  <html:li>be the argument of a function, where its effect is to <html:em>delay evaluation</html:em>.</html:li>
  <html:li>be the argument or result of a procedure. (see the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
title="Procedural Programming"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-procedural-programming/"
display-uri="focs-procedural-programming"
type="local">Procedural Programming section</fr:link>)</html:li></html:ul><html:p>The empty tuple, like all tuples, is a constructor and is allowed in patterns;
for example: <html:code>let f () = ...</html:code></html:p><html:p>In particular <fr:tex
display="inline"><![CDATA[\tt  fun \, () \rightarrow  E]]></fr:tex> is the function that takes an argument of
type <html:code>unit</html:code> and returns the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex> as its result.  Expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>
is not evaluated until the function is called, even though the only possible
argument is <html:code>()</html:code>.  The function simply delays the evaluation of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/</fr:uri><fr:display-uri>focs-def-mutable-reference</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/</fr:route><fr:title
text="Mutable reference">Mutable reference</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A reference is a cell in the store, also called a “location”: <html:code>ref E</html:code>
creates a reference with initial contents the value of <html:code>E</html:code>, <html:code>!P</html:code>
returns the current contents of reference <html:code>P</html:code> (an operation called
<html:em>dereferencing</html:em>), and <html:code>P := E</html:code> updates the contents of <html:code>P</html:code> to the
value of <html:code>E</html:code>. If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is some OCaml type, then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>ref</html:code> is the
type of references to cells that can hold values of <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-references/"
title="OCaml Primitives for References"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/"
display-uri="focs-references"
type="local">OCaml Primitives for References</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references/</fr:uri><fr:display-uri>focs-references</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references/</fr:route><fr:title
text="OCaml Primitives for References">OCaml Primitives for References</fr:title></fr:frontmatter><fr:mainmatter><html:table>
  <html:tr><html:th>Syntax</html:th><html:th>Effect</html:th></html:tr>
  <html:tr><html:td><html:code>ref E</html:code></html:td><html:td><html:em>create</html:em> a reference with <html:em>initial contents</html:em> = value of <html:code>E</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>!P</html:code></html:td><html:td>return <html:em>current contents</html:em> of reference <html:code>P</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>P := E</html:code></html:td><html:td><html:em>update</html:em> contents of <html:code>P</html:code> to value of <html:code>E</html:code></html:td></html:tr>
</html:table><html:p>The above text presents the OCaml primitives, but most languages have analogues of
them, often heavily disguised.  We need a means of creating references (or
allocating storage), getting at the current contents of a reference cell, and
updating that cell.</html:p><html:p>The function <html:code>ref</html:code> creates references (also called
“locations”).  Calling <html:code>ref</html:code> allocates a new location in memory.
Initially, this location holds the value given by
expression <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.</html:p><html:p>The function <html:code>!</html:code>, when applied to a reference, returns its contents.
This operation is called <html:em>dereferencing</html:em>.  Clearly <html:code>!</html:code> is not a
mathematical function; its result depends upon the store.</html:p><html:p>The assignment <html:code>P:=E</html:code> evaluates expression <fr:tex
display="inline"><![CDATA[P]]></fr:tex>, which must return a
reference <fr:tex
display="inline"><![CDATA[p]]></fr:tex>, and <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.  It stores at address <fr:tex
display="inline"><![CDATA[p]]></fr:tex> the value of <fr:tex
display="inline"><![CDATA[E]]></fr:tex>.
Syntactically, <html:code>:=</html:code> is a function and <html:code>P:=E</html:code> is an
expression, even though it updates the store.  Like many functions that change
the state, it returns the value <html:code>()</html:code> of type <html:code>unit</html:code>.</html:p><html:p>If <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> is some OCaml type, then <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex> <html:code>ref</html:code> is the type of references
to cells that can hold values of <fr:tex
display="inline"><![CDATA[\tau ]]></fr:tex>.  Please do not confuse the type
<html:code>ref</html:code> with the function <html:code>ref</html:code>.  This table of the primitive
functions and their types might be useful:</html:p><html:table>
  <html:tr><html:th>Syntax</html:th><html:th>OCaml Type</html:th></html:tr>
  <html:tr><html:td><html:code>ref</html:code></html:td><html:td><html:code>'a -&gt; 'a ref</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>!</html:code></html:td><html:td><html:code>'a ref -&gt; 'a</html:code></html:td></html:tr>
  <html:tr><html:td><html:code>:=</html:code></html:td><html:td><html:code>'a ref -&gt; 'a -&gt; unit</html:code></html:td></html:tr>
</html:table></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/</fr:uri><fr:display-uri>focs-def-pattern-matching</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/</fr:route><fr:title
text="Pattern matching">Pattern matching</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Pattern matching takes a value apart by matching it against the forms that
value can have, letting <html:em>one</html:em> function declaration handle several cases,
separated by a vertical bar <html:code>|</html:code>. Taking a list apart using combinations of
<html:code>hd</html:code> and <html:code>tl</html:code> is hard to get right; fortunately, it is seldom necessary
because of pattern-matching.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">Getting at the Head and Tail</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/</fr:uri><fr:display-uri>focs-def-polymorphism</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-def-polymorphism/</fr:route><fr:title
text="Polymorphism">Polymorphism</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>A polymorphic function allows flexibility in the types of its arguments and
results: the list primitives <html:code>null</html:code>, <html:code>hd</html:code> and <html:code>tl</html:code> work whatever
the element type is. Symbols <html:code>'a</html:code> and <html:code>'b</html:code> are called <html:em>type
variables</html:em> and stand for any types, and code written using them is still checked
for type correctness at compile time.
Introduced in <fr:link
href="/teaching/2627/FoundsCS/forest/focs-head-tail/"
title="Getting at the Head and Tail"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-head-tail/"
display-uri="focs-head-tail"
type="local">Getting at the Head and Tail</fr:link>.</html:p><html:p>Part of the course <fr:link
href="/teaching/2627/FoundsCS/forest/focs-glossary/"
title="Glossary"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-glossary/"
display-uri="focs-glossary"
type="local">glossary</fr:link>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/</fr:uri><fr:display-uri>focs-npower</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-npower/</fr:route><fr:title
text="Raising a Number to a Power">Raising a Number to a Power</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let rec npower x n =
    if n = 0 then 1.0
    else x *. npower x (n - 1)
val npower : float -> int -> float = <fun>]]></html:pre><html:p>Our new <html:code>npower</html:code> definition can now take additional arguments, reflected in the arrows
present in the type of <html:code>npower</html:code>; these represent <html:em>parameters</html:em> that can be passed to the
new value being defined, with the final segment being the resulting type. Thus our <html:code>npower</html:code>
type can be read as "pass in a float and integer to return a float".</html:p><html:p><html:em>Mathematical Justification</html:em> (for <fr:tex
display="inline"><![CDATA[x\not =0]]></fr:tex>):</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
           x^0 & = 1 \\
           x^{n+1} & = x\times  x^n.
\end {aligned}
]]></fr:tex><html:p>The function <html:code>npower</html:code> raises its float argument <html:code>x</html:code> to the power <html:code>n</html:code>, a
non-negative integer. The function is <html:strong>recursive</html:strong>: it calls itself.  You
can spot a recursive function due to the <html:code>rec</html:code> keyword in the definition:
this indicates that any invocation of the function name within the function body should call itself.
This concept should be familiar from mathematics, since exponentiation is defined by the
rules shown above. You may also have seen recursion in the product rule for
differentiation: <fr:tex
display="inline"><![CDATA[(u\cdot  v)' = u\cdot  v' + u'\cdot  v]]></fr:tex>. In finding the derivative of <fr:tex
display="inline"><![CDATA[u\cdot  v]]></fr:tex>,
we recursively find the derivatives of <fr:tex
display="inline"><![CDATA[u]]></fr:tex> and <fr:tex
display="inline"><![CDATA[v]]></fr:tex>, combining them to obtain the desired result.
The recursion is meaningful because it terminates: we reduce the problem to two smaller
problems, and this cannot go on forever. The OCaml programmer uses recursion
heavily.  For <fr:tex
display="inline"><![CDATA[n\geq 0]]></fr:tex>, the equation <fr:tex
display="inline"><![CDATA[x^{n+1} = x\times  x^n]]></fr:tex> yields an obvious
computation:</html:p><fr:tex
display="block"><![CDATA[ x^3 = x\times  x^2 = x\times  x\times  x^1 = x\times  x\times  x\times  x^0 = x\times  x\times  x ]]></fr:tex><html:p>The equation clearly holds even for negative <fr:tex
display="inline"><![CDATA[n]]></fr:tex>. However, the corresponding
computation runs forever:</html:p><fr:tex
display="block"><![CDATA[ x^{-1} = x\times  x^{-2} = x\times  x\times  x^{-3}=\cdots  ]]></fr:tex><html:p>Note that the function <html:code>npower</html:code> contains both an integer constant (<html:code>0</html:code>) and a
floating point constant (<html:code>1.0</html:code>). The decimal point makes all the difference.
OCaml will notice and ascribe different meaning to each type of constant.</html:p><html:pre><![CDATA[# let square x = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>Now for a tiresome but necessary aside. In most languages, the types of
arguments and results must always be specified. OCaml is unusual that it normally
infers the types itself. However, sometimes it is useful to supply a hint to
help you debug and develop your program. OCaml will still infer the types even if you don’t specify them, but in some cases
it will use a more inefficient function than a specialised one. Some languages
have just one type of number, converting automatically between different
formats; this is slow and could lead to unexpected rounding errors.  Type
constraints are allowed almost anywhere. We can put one on any occurrence of x
in the function.</html:p><html:pre><![CDATA[# let square (x : float) = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>Or we can constrain the type of the function’s result:</html:p><html:pre><![CDATA[# let square x : float = x *. x
val square : float -> float = <fun>]]></html:pre><html:p>OCaml treats the equality and comparison test specially. Expressions like <html:code>if x = y then</html:code> …
are allowed provided <html:code>x</html:code> and <html:code>y</html:code> have the same type and equality testing is
possible for that type. (We discuss <fr:link
href="/teaching/2627/FoundsCS/forest/focs-equality/"
title="Equality Tests"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-equality/"
display-uri="focs-equality"
type="local">equality</fr:link> further in a later lecture.)
Note that <html:code>x &lt;&gt; y</html:code> is OCaml for <fr:tex
display="inline"><![CDATA[x\not =y]]></fr:tex>.</html:p><html:p>A characteristic feature of the computer is its ability to test for conditions
and act accordingly.  In the early days, a program might jump to a given
address depending on the sign of some number.  Later, John McCarthy defined
the <html:em>conditional expression</html:em> to satisfy <html:code>if true then x else y = x</html:code> and
<html:code>if false then x else y = y</html:code>.</html:p><html:p>OCaml evaluates the expression <html:code>if</html:code> <fr:tex
display="inline"><![CDATA[B]]></fr:tex> <html:code>then</html:code> <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> <html:code>else</html:code> <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex> by first evaluating <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.
If the result is <html:code>true</html:code> then OCaml evaluates <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> and otherwise <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex>.  Only one
of the two expressions <fr:tex
display="inline"><![CDATA[E_1]]></fr:tex> and <fr:tex
display="inline"><![CDATA[E_2]]></fr:tex> is evaluated!  If both were evaluated,
then recursive functions like <html:code>npower</html:code> above would run forever.</html:p><html:p>The <html:code>if</html:code>-expression is governed by an expression of type <html:code>bool</html:code>, whose two
values are <html:code>true</html:code> and <html:code>false</html:code>.  In modern programming languages, tests are not
built into “conditional branch” constructs but can just be part of normal expressions.
Tests, or <html:em>Boolean expressions,</html:em> can be expressed using relational operators
such as <html:code>&lt;</html:code> and <html:code>=</html:code>. They can be combined using the Boolean operators for
negation (<html:code>not</html:code>), conjunction (written as <html:code>&amp;&amp;</html:code>) and disjunction (written as <html:code>||</html:code>).  New
properties can be declared as functions: here, to test whether an integer is
even, for example:</html:p><html:pre><![CDATA[# let even n = n mod 2 = 0
val even : int -> bool = <fun>]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-references-examples/</fr:uri><fr:display-uri>focs-references-examples</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-references-examples/</fr:route><fr:title
text="Trying Out References">Trying Out References</fr:title></fr:frontmatter><fr:mainmatter><html:pre><![CDATA[# let p = ref 5 (* create a reference *)
val p : int ref = {contents = 5}
# p := !p + 1   (* p now holds value 6 *)
- : unit = ()
# let ps = [ ref 77; p ]
val ps : int ref list = [{contents = 77}; {contents = 6}]
# List.hd ps := 3
- : unit = ()
# ps
- : int ref list = [{contents = 3}; {contents = 6}]]]></html:pre><html:p>The first line declares <html:code>p</html:code> to hold a <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
title="Mutable reference"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-mutable-reference/"
display-uri="focs-def-mutable-reference"
type="local">reference</fr:link> to an integer,
initially 5.  Its type is <html:code>int ref</html:code>, not just <html:code>int</html:code>, so it
admits assignment.  Assignment never changes <html:code>let</html:code> bindings: they are
<html:em>immutable</html:em>.  The identifier <html:code>p</html:code> will always denote the reference
mentioned in its declaration unless superseded by a new usage of <html:code>p</html:code>.
Only the <html:em>contents</html:em> of the reference is mutable.</html:p><html:p>OCaml displays a reference value as <html:code><![CDATA[{contents=v}]]></html:code>, where value <fr:tex
display="inline"><![CDATA[v]]></fr:tex> is the
contents.  This notation is readable but gives us no way of telling whether
two references holding the same value are actually the same reference.  To
display a reference as a machine address has obvious drawbacks!</html:p><html:p>In the first assignment, the expression <html:code>!p</html:code> yields the reference’s
current contents, namely 5.  The assignment changes the contents of <html:code>p</html:code>
to 6.  Most languages do not have an explicit dereferencing operator
(like <html:code>!</html:code>) because of its inconvenience.  Instead, by convention,
occurrences of the reference on the <html:em>left-hand</html:em> side of the <html:code>:=</html:code>
denote locations and those on the <html:em>right-hand</html:em> side denote the contents.
A special ‘address of’ operator may be available to override the convention
and make a reference on the right-hand side to denote a location.  Logically
this is a mess, but it makes programs shorter.</html:p><html:p>The list <html:code>ps</html:code> is declared to hold a new reference (initially
containing 77) as well as <html:code>p</html:code>.  Then the new reference is
updated to hold 3.  The assignment to <html:code>hd ps</html:code> does <html:em>not</html:em>
update <html:code>ps</html:code>, only the contents of a reference in that list.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-why-ocaml/</fr:uri><fr:display-uri>focs-why-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-why-ocaml/</fr:route><fr:title
text="Why Program in OCaml?">Why Program in OCaml?</fr:title></fr:frontmatter><fr:mainmatter><html:p>Why program in OCaml at all?</html:p><html:ul><html:li>It is interactive.</html:li>
  <html:li>It has a flexible notion of <html:em>data type</html:em>.</html:li>
  <html:li>It hides the underlying hardware: <html:em>no crashes</html:em>.</html:li>
  <html:li>Programs can easily be understood mathematically.</html:li>
  <html:li>It distinguishes naming something from <html:em>updating memory</html:em>.</html:li>
  <html:li>It manages storage for us.</html:li></html:ul><html:p>Programming languages matter. They affect the reliability, security, and
efficiency of the code you write, as well as how easy it is to read, refactor,
and extend. The languages you know can also change how you think, influencing
the way you design software even when you’re not using them.</html:p><html:p>What makes OCaml special is that it occupies a sweet spot in the space of
programming language designs. It provides a combination of efficiency,
expressiveness and practicality that is difficult to find matched by any other language.
“ML” was originally the meta language of the LCF (Logic for Computable Functions)
proof assistant released by Robin Milner in 1972 (at Stanford, and later at Cambridge).
ML was turned into a compiler in order to make it easier to use LCF on different machines,
and it was gradually turned into a full-fledged system of its own by the 1980s.</html:p><html:p>The modern OCaml emerged in 1996, and the past twenty five years have seen OCaml
attract a significant user base with language improvements being steadily
added to support the growing commercial and academic codebases.
OCaml is therefore the outcome of years of research into programming languages,
and a good base to begin our journey into learning the foundations of computer
science.</html:p><html:p>Because of its connection to mathematics, OCaml programs can be designed and
understood without thinking in detail about how the computer will run them.
Although a program can abort, it cannot crash: it remains under the control of
the OCaml system. It still achieves respectable efficiency and provides
lower-level primitives for those who need them. Most other languages allow
direct access to the underlying machine and even try to execute illegal
operations, causing crashes.</html:p><html:p>The only way to learn programming is by writing and running programs. This web
notebook provides an interactive environment where you can modify the example
fragments and see the results for yourself.  You should also consider
installing OCaml on your own computer so that you try more advanced programs
locally.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:uri><fr:display-uri>focs-ex-4-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-3/</fr:route><fr:title
text="Exercises › A non-exhaustive zip"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › A non-exhaustive zip</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>How does this version of <html:code>zip</html:code> differ from <fr:link
href="/teaching/2627/FoundsCS/forest/focs-zip/"
title="Building a List of Pairs"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-zip/"
display-uri="focs-zip"
type="local">the one above</fr:link>?</html:p><html:pre><![CDATA[let rec zip xs ys =
  match xs, ys with
  | (x::xs, y::ys) -> (x, y) :: zip xs ys
  | ([], [])   -> []]]></html:pre><html:pre><![CDATA[Lines 2-4, characters 5-23:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
(x::xs, [])]]></html:pre></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:uri><fr:display-uri>focs-ex-6-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-4/</fr:route><fr:title
text="Exercises › A type for arithmetic expressions"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › A type for arithmetic expressions</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for arithmetic expressions that have the following
possibilities: floating-point numbers, variables (represented by strings), or expressions of the form <fr:tex
display="inline"><![CDATA[-E]]></fr:tex>,
<fr:tex
display="inline"><![CDATA[E+E]]></fr:tex>, <fr:tex
display="inline"><![CDATA[E\times  E]]></fr:tex>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-2/</fr:uri><fr:display-uri>focs-ex-1-2</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-2/</fr:route><fr:title
text="Exercises › Comparing and adding years"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Comparing and adding years</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Using the date representation of <fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1-1/"
title="Exercises › Two-digit year windowing"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-1/"
display-uri="focs-ex-1-1"
type="local">the previous exercise</fr:link>, code OCaml functions to (a) compare two
years (b) add/subtract some given number of years from another year.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:uri><fr:display-uri>focs-ex-6-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-6-1/</fr:route><fr:title
text="Exercises › Days of the week type"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-6/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-6/"
display-uri="focs-ex-6"
type="local">Exercises</fr:link> › Days of the week type</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Give the declaration of an OCaml type for the days of the week. Comment on the practicality of such
a type in a calendar application.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:uri><fr:display-uri>focs-ex-1-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-5/</fr:route><fr:title
text="Exercises › Floating-point error by repeated addition"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Floating-point error by repeated addition</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Because computer arithmetic is based on binary numbers, simple decimals such as 0.1 often cannot be
represented exactly. Write a function <html:code>mul</html:code> that performs the computation</html:p><fr:tex
display="block"><![CDATA[\underbrace {x+x+\cdots +x}_{n}]]></fr:tex><html:p>where <fr:tex
display="inline"><![CDATA[x]]></fr:tex> has type <html:code>float</html:code>. (It is essential to use repeated addition rather than multiplication!)</html:p><html:p>The value computed with <html:code>n = 10000</html:code> and <html:code>x = 0.1</html:code> may print as
<html:code>1000.0</html:code>, which looks exact. If that happens, then evaluate the
expression <html:code>mul 0.1 10000 -. 1000.0</html:code></html:p><html:p>An error of this type has been blamed for the failure of an American Patriot Missile battery to
intercept an incoming Iraqi missile during the <fr:link
href="https://en.wikipedia.org/wiki/MIM-104_PatriotFailure_at_Dhahran"
type="external">first Gulf War</fr:link>.
The missile hit an American Army barracks, killing 28.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:uri><fr:display-uri>focs-ex-1-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-6/</fr:route><fr:title
text="Exercises › Golden ratio instability"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Golden ratio instability</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Another example of the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-floating-point/"
title="Example 2: Floating Point Numbers"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-floating-point/"
display-uri="focs-floating-point"
type="local">inaccuracy of floating-point arithmetic</fr:link> takes the golden ratio
<fr:tex
display="inline"><![CDATA[\phi \approx 1.618\ldots ]]></fr:tex> as its starting point:</html:p><fr:tex
display="block"><![CDATA[\gamma _0 = \frac {1+\sqrt 5}{2} \quad \text {and}\quad \gamma _{n+1} = \frac {1}{\gamma _n-1}.]]></fr:tex><html:p>In theory, it is easy to prove that <fr:tex
display="inline"><![CDATA[\gamma _n=\cdots  = \gamma _1 = \gamma _0]]></fr:tex> for all <fr:tex
display="inline"><![CDATA[n>0]]></fr:tex>. Code this
computation in OCaml and report the value of <fr:tex
display="inline"><![CDATA[\gamma _{50}]]></fr:tex>. <html:em>Hint:</html:em> in OCaml, <fr:tex
display="inline"><![CDATA[\sqrt 5]]></fr:tex> is expressed
as <html:code>sqrt 5.0</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:uri><fr:display-uri>focs-ex-11-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-1/</fr:route><fr:title
text="Exercises › Lists of references"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Lists of references</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Comment, with examples, on the differences between an <html:code>int ref list</html:code> and an <html:code>int list ref</html:code>.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3-4/</fr:uri><fr:display-uri>focs-ex-3-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-3-4/</fr:route><fr:title
text="Exercises › Polymorphic types of id and loop"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-3/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-3/"
display-uri="focs-ex-3"
type="local">Exercises</fr:link> › Polymorphic types of id and loop</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Consider the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
title="Polymorphism"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-polymorphism/"
display-uri="focs-def-polymorphism"
type="local">polymorphic types</fr:link> in these two function declarations:</html:p><html:pre><![CDATA[# let id x = x
val id : 'a -> 'a = <fun>
# let rec loop x = loop x
val loop : 'a -> 'b = <fun>]]></html:pre><html:p>Explain why these types make logical sense, preventing run time type errors, even for expressions
like <html:code>id [id [id 0]]</html:code> or <html:code>loop true / loop 3</html:code>. (<html:code>/</html:code> is the integer division operator in OCaml)</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:uri><fr:display-uri>focs-ex-4-6</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-4-6/</fr:route><fr:title
text="Exercises › Reasoning from polymorphic types"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-4/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-4/"
display-uri="focs-ex-4"
type="local">Exercises</fr:link> › Reasoning from polymorphic types</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>We know nothing about the functions <html:code>f</html:code> and <html:code>g</html:code> other than their polymorphic types:
<html:code>val f : 'a * 'b -&gt; 'b * 'a</html:code> and <html:code>val g : 'a -&gt; 'a list</html:code>.
Suppose that <html:code>f (1, true)</html:code> and <html:code>g 0</html:code> are evaluated and return their results. State, with reasons,
what you think the resulting values will be.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-3/</fr:uri><fr:display-uri>focs-ex-1-3</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-3/</fr:route><fr:title
text="Exercises › Redundant conditionals"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Redundant conditionals</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Why would no experienced programmer write an expression of the form <html:code>if</html:code> … <html:code>then true else false</html:code>?
What about expressions of the form <html:code>if</html:code> … <html:code>then false else true</html:code>?</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-1/</fr:uri><fr:display-uri>focs-ex-1-1</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-1/</fr:route><fr:title
text="Exercises › Two-digit year windowing"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Two-digit year windowing</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>One solution to the <fr:link
href="/teaching/2627/FoundsCS/forest/focs-dates/"
title="Example 1: Dates"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-dates/"
display-uri="focs-dates"
type="local">year 2000 bug</fr:link> involves storing years as two digits, but interpreting them such
that 50 means 1950 and 49 means 2049. Comment on the merits and demerits of this approach.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:uri><fr:display-uri>focs-ex-1-4</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-1-4/</fr:route><fr:title
text="Exercises › Type inference in power"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-1/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-1/"
display-uri="focs-ex-1"
type="local">Exercises</fr:link> › Type inference in power</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Functions <fr:link
href="/teaching/2627/FoundsCS/forest/focs-npower/"
title="Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-npower/"
display-uri="focs-npower"
type="local"><html:code>npower</html:code></fr:link> and <fr:link
href="/teaching/2627/FoundsCS/forest/focs-power/"
title="Efficiently Raising a Number to a Power"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-power/"
display-uri="focs-power"
type="local"><html:code>power</html:code></fr:link> both return a <html:code>float</html:code>. The definition of <html:code>npower</html:code> returns the float
value <html:code>1.0</html:code> in its base case. The definition of <html:code>power</html:code> does not, so how does the OCaml type checker
know that <html:code>power</html:code> returns a <html:code>float</html:code>?</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-strings/</fr:uri><fr:display-uri>focs-topic-strings</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-strings/</fr:route><fr:title
text="Strings">Strings</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-currying/</fr:uri><fr:display-uri>focs-currying</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-currying/</fr:route><fr:title
text="Curried Functions">Curried Functions</fr:title></fr:frontmatter><fr:mainmatter><html:p>A <html:em>curried function</html:em> returns another function as its result. We use
the string concatenation operator <html:code>(^)</html:code> to illustrate how this works.</html:p><html:pre><![CDATA[# (^)
- : string -> string -> string = <fun>
# let prefix = fun a -> fun b -> a ^ b
val prefix : string -> string -> string = <fun>
# let promote = prefix "Senior "
val promote : string -> string = <fun>
# prefix "Junior " "Professor"
- : string = "Junior Professor"
# promote "Professor"
- : string = "Senior Professor"]]></html:pre><html:p>A short form for the definition of <html:code>prefix</html:code> is simply to pass multiple
arguments to the function definition.  The following two definitions
are equivalent in OCaml:</html:p><html:pre><![CDATA[# let prefix = fun a -> fun b -> a ^ b
val prefix : string -> string -> string = <fun>
# let prefix a b = a ^ b
val prefix : string -> string -> string = <fun>]]></html:pre><html:p>Currying is the technique of expressing a function taking multiple arguments as nested functions, each taking a single argument.
The <html:code>fun</html:code>-notation lets us package <html:code>n*2</html:code> as the function
<html:code>fun n -&gt; n * 2</html:code>, but what if there are several variables, as in
<html:code>fun n -&gt; n * 2 + k</html:code>?  A function of two arguments could be coded using
<fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
title="Pattern matching"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-pattern-matching/"
display-uri="focs-def-pattern-matching"
type="local">pattern-matching</fr:link> on pairs, writing <html:code>fun (n, k) -&gt; n * 2 + k</html:code>.</html:p><html:p>Currying is an alternative, where we <html:em>nest</html:em> the <html:code>fun</html:code>-notation:</html:p><html:pre><![CDATA[# fun k -> fun n -> n * 2 + k
- : int -> int -> int = <fun>]]></html:pre><html:p>Applying this curried function to the argument 1 yields another function, in which <html:code>k</html:code> has been replaced by 1:</html:p><html:pre><![CDATA[# let fn = fun k -> fun n -> n * 2 + k
val fn : int -> int -> int = <fun>
# let fn' = fn 1 (* n * 2 + 1 *)
val fn' : int -> int = <fun>
# fn' 3  (* 3 * 2 + 1 *)
- : int = 7]]></html:pre><html:p>And this function, when applied to 3, yields the result 7. The two arguments are supplied one after another.</html:p><html:p>The earlier <html:code>prefix</html:code> example is similar and uses the expression <html:code>a ^ b</html:code>,
where <html:code>^</html:code> is the infix operator for string concatenation. Function <html:code>promote</html:code> binds the first argument of <html:code>prefix</html:code> to
<html:code>"Senior "</html:code>; the resulting function prefixes that title
to any string to which it is applied.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-strings-chars/</fr:uri><fr:display-uri>focs-strings-chars</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-strings-chars/</fr:route><fr:title
text="Lists, Strings and Characters">Lists, Strings and Characters</fr:title></fr:frontmatter><fr:mainmatter><html:p>Strings are provided in most programming languages to allow text processing.
Strings are essential for communication with users. Even a purely numerical
program formats its results ultimately as strings.</html:p><html:pre><![CDATA[# 'a'   (* a character constant *)
- : char = 'a'
# "a"   (* a string constant of length 1 *)
- : string = "a"
# "abc" (* a string constant of length 3 *)
- : string = "abc"
# String.length "abc"
- : int = 3
# "abc" ^ "def"  (* concatenate two strings *)
- : string = "abcdef"]]></html:pre><html:p>In a few programming languages, strings simply are lists of characters. In
OCaml they are a separate type, unrelated to lists, reflecting the fact that
strings are an abstract concept in themselves.</html:p><html:p>Similarly, characters are not strings of size one, but are a primitive concept.
Character constants in OCaml have the form <html:code>'c'</html:code>, where <fr:tex
display="inline"><![CDATA[c]]></fr:tex> is any character.
For example, the comma character is <html:code>','</html:code>.</html:p><html:p>Special characters are coded in strings using <html:em>escape sequences</html:em> involving the
backslash character; among many others, a double quote is written <html:code><![CDATA["\\"]]></html:code> and
the newline character is written <html:code><![CDATA["\n"]]></html:code>. For example, the string
<html:code><![CDATA["I\nLIKE\nCHEESE\n"]]></html:code> represents three text lines.</html:p><html:p>In addition to the operators described above, the relations <html:code>&lt;</html:code>, <html:code>&lt;=</html:code>, <html:code>&gt;</html:code>, and
<html:code>&gt;=</html:code> work for strings and yield alphabetic order (more precisely, lexicographic
order with respect to ASCII character codes).</html:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-topic-matrices/</fr:uri><fr:display-uri>focs-topic-matrices</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-topic-matrices/</fr:route><fr:title
text="Matrices">Matrices</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/</fr:uri><fr:display-uri>focs-transpose</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-transpose/</fr:route><fr:title
text="Example: Matrix Transpose">Example: Matrix Transpose</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {pmatrix}
           a   & b & c \\
           d   & e & f
   \end {pmatrix}^T =
   \begin {pmatrix}
        a & d     \\
        b & e     \\
        c & f
\end {pmatrix}
]]></fr:tex><html:pre><![CDATA[# let rec transp = function
    | []::_ -> []
    | rows -> (map List.hd rows) ::
              (transp (map List.tl rows))
val transp : 'a list list -> 'a list list = <fun>]]></html:pre><html:p>A matrix can be viewed as a list of rows, each row a list of matrix elements.
This representation is not especially efficient compared with the conventional
one (using arrays).  Lists of lists turn up often, though, and we can see how
to deal with them by taking familiar matrix operations as examples.
<html:em>ML for the Working Programmer</html:em> goes as far as Gaussian elimination,
which presents surprisingly few difficulties.</html:p><html:p>The transpose of the matrix
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix} a & b & c \\
                           d & e & f\end {smallmatrix}\right )]]></fr:tex>
is
<fr:tex
display="inline"><![CDATA[\left (\begin {smallmatrix}
        a & d     \\
        b & e     \\
        c & f
   \end {smallmatrix}\right )]]></fr:tex>,
which in OCaml corresponds to the following transformation on lists of lists:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {[[a; b; c]; [d; e; f]]} \Rightarrow & \text { [[a; d]; [b; e]; [c; f]]}
\end {aligned}
]]></fr:tex><html:p>The workings of function <html:code>transp</html:code> are simple.  If <html:code>rows</html:code> is the
matrix to be transposed, then <html:code>map hd</html:code> extracts its first column and
<html:code>map tl</html:code> extracts its second column:</html:p><fr:tex
display="block"><![CDATA[
\begin {aligned}
\text {map hd rows} \Rightarrow  & \text { [a; d]}\\
\text {map tl rows} \Rightarrow  & \text { [[b; c]; [e; f]]}
\end {aligned}
]]></fr:tex><html:p>A recursive call transposes the latter matrix, which is then given the column
<html:code>[a; d]</html:code> as its first row.
The two functions expressed using <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> would otherwise have to be declared
separately.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:uri><fr:display-uri>focs-matmul-ocaml</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-matmul-ocaml/</fr:route><fr:title
text="Matrix Multiplication in OCaml">Matrix Multiplication in OCaml</fr:title></fr:frontmatter><fr:mainmatter><html:p><html:em>Dot product</html:em> of two vectors—a <html:em><fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-currying/"
title="Currying"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-currying/"
display-uri="focs-def-currying"
type="local">curried function</fr:link></html:em></html:p><html:pre><![CDATA[# let rec dotprod xs ys =
    match xs, ys with
    | [], [] -> 0.0
    | x::xs, y::ys ->  (x *. y) +. (dotprod xs ys)
Lines 2-4, characters 5-51:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
([], _::_)

val dotprod : float list -> float list -> float = <fun>]]></html:pre><html:p><html:em>Matrix product</html:em></html:p><html:pre><![CDATA[# let rec matprod arows brows =
    let cols = transp brows in
    map (fun row -> map (dotprod row) cols) arows
val matprod : float list list -> float list list -> float list list = <fun>]]></html:pre><html:p>The <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local"><html:code>transp brows</html:code></fr:link> converts <fr:tex
display="inline"><![CDATA[B]]></fr:tex> into a list of columns, yielding a
list whose elements are the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Each row of <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is
obtained by multiplying a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> by the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><html:p>Because <html:code>dotprod</html:code> is curried, it can be applied to a row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The
resulting function is applied to all the columns of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  We have another
example of currying and partial application.</html:p><html:p>The outer <fr:link
href="/teaching/2627/FoundsCS/forest/focs-map/"
title="map: the “Apply to All” Function"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-map/"
display-uri="focs-map"
type="local"><html:code>map</html:code></fr:link> applies <html:code>dotprod</html:code> to each row of <fr:tex
display="inline"><![CDATA[A]]></fr:tex>.  The inner
<html:code>map</html:code>, using <html:code>fun</html:code>-notation, applies <html:code>dotprod row</html:code> to each
column of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.  Compare with the version in <html:em>ML for the Working
  Programmer</html:em> (page 89) which does not use <html:code>map</html:code> and requires two
additional function declarations.</html:p><html:p>In the dot product function, the two vectors must have the same length.
Otherwise, <fr:link
href="/teaching/2627/FoundsCS/forest/focs-def-exception/"
title="Exception"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-def-exception/"
display-uri="focs-def-exception"
type="local">exception</fr:link> <html:code>Match_failure</html:code> is raised.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-matrix-multiplication/</fr:uri><fr:display-uri>focs-matrix-multiplication</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-matrix-multiplication/</fr:route><fr:title
text="Review of Matrix Multiplication">Review of Matrix Multiplication</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block"><![CDATA[
\begin {pmatrix} A_1 & \cdots  & A_k \end {pmatrix}  \cdot 
   \begin {pmatrix}
        B_1 \\ \vdots  \\ B_k
   \end {pmatrix}   =
   \begin {pmatrix}
        A_1 B_1 + \cdots  + A_k B_k
   \end {pmatrix}
]]></fr:tex><html:p>The right side is the <html:em>vector dot product</html:em> <fr:tex
display="inline"><![CDATA[\vec {A}\cdot  \vec {B}]]></fr:tex>.
Repeat for each <html:em>row</html:em> of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> and <html:em>column</html:em> of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><html:p>The <html:em>dot product</html:em> of two vectors is</html:p><fr:tex
display="block"><![CDATA[ (a_1,\ldots ,a_k) \cdot  (b_1,\ldots ,b_k) = a_1b_1 + \cdots  + a_kb_k ]]></fr:tex><html:p>A simple case of matrix multiplication is when <fr:tex
display="inline"><![CDATA[A]]></fr:tex> consists of a single row
and <fr:tex
display="inline"><![CDATA[B]]></fr:tex> consists of a single column.  Provided <fr:tex
display="inline"><![CDATA[A]]></fr:tex> and <fr:tex
display="inline"><![CDATA[B]]></fr:tex> contain the same
number <fr:tex
display="inline"><![CDATA[k]]></fr:tex> of elements, multiplying them yields a <fr:tex
display="inline"><![CDATA[1\times 1]]></fr:tex> matrix whose
single element is the dot product shown above.</html:p><html:p>If <fr:tex
display="inline"><![CDATA[A]]></fr:tex> is an <fr:tex
display="inline"><![CDATA[m\times  k]]></fr:tex> matrix and <fr:tex
display="inline"><![CDATA[B]]></fr:tex> is a <fr:tex
display="inline"><![CDATA[k\times  n]]></fr:tex> matrix
then <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is an <fr:tex
display="inline"><![CDATA[m\times  n]]></fr:tex> matrix.
For each <fr:tex
display="inline"><![CDATA[i]]></fr:tex> and <fr:tex
display="inline"><![CDATA[j]]></fr:tex>, the <fr:tex
display="inline"><![CDATA[(i,j)]]></fr:tex> element of <fr:tex
display="inline"><![CDATA[A\times  B]]></fr:tex> is the dot
product of row <fr:tex
display="inline"><![CDATA[i]]></fr:tex> of <fr:tex
display="inline"><![CDATA[A]]></fr:tex> with column <fr:tex
display="inline"><![CDATA[j]]></fr:tex> of <fr:tex
display="inline"><![CDATA[B]]></fr:tex>.</html:p><fr:tex
display="block"><![CDATA[
\begin {pmatrix}
        2 & 0 \\
        3 &-1 \\
        0 & 1 \\
        1 & 1
   \end {pmatrix}
   \begin {pmatrix}
        1 & 0 & 2 \\
        4 &-1 & 0
   \end {pmatrix}   =
   \begin {pmatrix}
        2 & 0 & 4 \\
       -1 & 1 & 6 \\
        4 &-1 & 0 \\
        5 &-1 & 2
\end {pmatrix}
]]></fr:tex><html:p>The (1, 1) element above is computed by</html:p><fr:tex
display="block"><![CDATA[ (2,0)\cdot (1,4) = 2\times 1 + 0\times 4 = 2. ]]></fr:tex><html:p>Coding matrix multiplication in a conventional programming language usually
involves three nested loops.  It is hard to avoid mistakes in the subscripting,
which often runs slowly due to redundant internal calculations.</html:p></fr:mainmatter></fr:tree><fr:tree
show-metadata="true"
expanded="false"
toc="false"
numbered="false"><fr:frontmatter><fr:authors><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author><fr:author><fr:link
href="/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
title="Anil Madhavapeddy"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/anil-madhavapeddy/"
display-uri="anil-madhavapeddy"
type="local">Anil Madhavapeddy</fr:link></fr:author></fr:authors><fr:uri>https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:uri><fr:display-uri>focs-ex-11-5</fr:display-uri><fr:route>/teaching/2627/FoundsCS/forest/focs-ex-11-5/</fr:route><fr:title
text="Exercises › Matrix operations on arrays"><fr:link
href="/teaching/2627/FoundsCS/forest/focs-ex-11/"
title="Exercises"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-ex-11/"
display-uri="focs-ex-11"
type="local">Exercises</fr:link> › Matrix operations on arrays</fr:title><fr:taxon>Exercise</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>Arrays of multiple dimensions are represented in OCaml by arrays of arrays. Write functions to
(a) create an <fr:tex
display="inline"><![CDATA[n\times  n]]></fr:tex> identity matrix, given <fr:tex
display="inline"><![CDATA[n]]></fr:tex>, and
(b) to <fr:link
href="/teaching/2627/FoundsCS/forest/focs-transpose/"
title="Example: Matrix Transpose"
uri="https://www.cl.cam.ac.uk/teaching/2627/FoundsCS/forest/focs-transpose/"
display-uri="focs-transpose"
type="local">transpose</fr:link> an <fr:tex
display="inline"><![CDATA[m\times  n]]></fr:tex> matrix. Identity matrices have the following form:</html:p><fr:tex
display="block"><![CDATA[
\left ( {
\begin {array}{cccc}
   1 & 0 &  \cdots   & 0  \\
   0 & 1 &  \cdots   & 0  \\
    \vdots   &  \vdots   &  \ddots   &  \vdots    \\
   0 & 0 &  \cdots   & 1  \\
 \end {array}
 } \right )
]]></fr:tex></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
show-metadata="false"
hidden-when-empty="true"><fr:frontmatter><fr:authors /><fr:title
text="Contributions">Contributions</fr:title></fr:frontmatter><fr:mainmatter /></fr:tree></fr:backmatter></fr:tree>