<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="default.xsl"?>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="true"
expanded="true"
root="true"><fr:frontmatter><fr:anchor>1825</fr:anchor><fr:taxon>Course</fr:taxon><fr:addr>150-notes</fr:addr><fr:route>index.xml</fr:route><fr:title>15-150: Principles of Functional Programming (Summer 2024)</fr:title><fr:date><fr:year>2024</fr:year></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors><fr:meta
name="external">https://www.cs.cmu.edu/~15150/</fr:meta></fr:frontmatter><fr:mainmatter><fr:p>These lecture notes were prepared using the <fr:link
href="https://www.forester-notes.org"
type="external">Forester</fr:link> software by <fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link> based partially on lectures by <fr:link
href="sb21.xml"
type="local"
addr="sb21">Stephen Brookes</fr:link>, <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>, <fr:link
href="dilsunk.xml"
type="local"
addr="dilsunk">Dilsun Kaynar</fr:link>, <fr:link
href="jacobneu.xml"
type="local"
addr="jacobneu">Jacob Neumann</fr:link>, and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p><fr:p>Use <fr:code>Ctrl-K</fr:code> to search the notes.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1690</fr:anchor><fr:addr>150-0001</fr:addr><fr:route>150-0001.xml</fr:route><fr:title>Course policies</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Course policies can be found on <fr:link
href="https://www.cs.cmu.edu/~15150/policy.html"
type="external">the course website</fr:link>.</fr:p></fr:mainmatter></fr:tree>
  
  <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1818</fr:anchor><fr:addr>150-concepts</fr:addr><fr:route>150-concepts.xml</fr:route><fr:title>Concepts and definitions</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1691</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000M</fr:addr><fr:route>150-000M.xml</fr:route><fr:title><fr:code>val</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>val</fr:code> declaration gives a variable name to the result of an expression evaluation.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val x : t = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1692</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0015</fr:addr><fr:route>150-0015.xml</fr:route><fr:title><fr:code>fun</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (x : t1) : t2 = e
</html:code></fr:pre><fr:p>The value assigned to <fr:code>f</fr:code> is <fr:code>fn (x : t1) =&gt; e</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1693</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001J</fr:addr><fr:route>150-001J.xml</fr:route><fr:title><fr:code>case</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">case e of
  pat1 =&gt; e1
| pat2 =&gt; e2
  ...
| patn =&gt; en
</html:code></fr:pre><fr:p>To evaluate a <fr:code>case</fr:code> expression:</fr:p><fr:ol><fr:li>Evaluate <fr:code>e</fr:code> to a value.</fr:li>
  <fr:li>Then, evaluate the first branch matching the value.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1694</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001P</fr:addr><fr:route>150-001P.xml</fr:route><fr:title><fr:code>if</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>SML has shorthand notation ("syntactic sugar") for casing on a boolean.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">case e of
  true  =&gt; e1
| false =&gt; e0

if e then e1 else e0
</html:code></fr:pre><fr:p>In other languages:</fr:p><fr:ul><fr:li>Python: <fr:code>e1 if e else e0</fr:code></fr:li>
  <fr:li>C: <fr:code>e ? e1 : e0</fr:code></fr:li></fr:ul><fr:p>Not to be confused with <fr:code>if</fr:code> "statements"!</fr:p><fr:p>The following further syntactic sugars are available:</fr:p><fr:ul><fr:li><fr:code>e1 andalso e2</fr:code> is sugar for <fr:code>if e1 then e2 else false</fr:code></fr:li>
  <fr:li><fr:code>e1 orelse e2</fr:code> is sugar for <fr:code>if e1 then true else e2</fr:code></fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1695</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004E</fr:addr><fr:route>150-004E.xml</fr:route><fr:title><fr:code>order</fr:code> datatype</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following datatype is built into the standard library of Standard ML:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype order = LESS | EQUAL | GREATER
</html:code></fr:pre><fr:p>As the constructor names indicate, these constructors indicate the result of a comparison of elements in a <fr:link
href="https://en.wikipedia.org/wiki/Law_of_trichotomy"
type="external">trichotomous relation</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1696</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007K</fr:addr><fr:route>150-007K.xml</fr:route><fr:title><fr:code>regexp</fr:code> datatype</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype regexp
  = Char of char
  | Zero
  | One
  | Plus of regexp * regexp
  | Times of regexp * regexp
  | Star of regexp
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1697</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AZ</fr:addr><fr:route>150-00AZ.xml</fr:route><fr:title><fr:code>raise</fr:code> expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:code>raise Fail "TODO"</fr:code> has most general type <fr:code>'a</fr:code>, filling in for any type we wish. More generally, <fr:code>raise e</fr:code> has most general type <fr:code>'a</fr:code>, for any exception <fr:code>e</fr:code>.</fr:p><fr:p>Unlike other expressions, it does not evaluate to <fr:em>any</fr:em> value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1698</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00B0</fr:addr><fr:route>150-00B0.xml</fr:route><fr:title><fr:code>exn</fr:code> type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An exception, like <fr:code>Fail "TODO"</fr:code> or <fr:code>Div</fr:code>, has type <fr:code>exn</fr:code>. So, note that <fr:code>Fail : string -&gt; exn</fr:code>. We can write <fr:code>raise e</fr:code> for any <fr:code>e : exn</fr:code>.</fr:p><fr:p>The type <fr:code>exn</fr:code> can be thought of as a datatype with infinitely many constructors:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype exn = Fail of string | Div | ...
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1699</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00B5</fr:addr><fr:route>150-00B5.xml</fr:route><fr:title><fr:code>handle</fr:code> expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>handle</fr:code> expression has the following structure:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">e handle pat1 =&gt; e1
       | pat2 =&gt; e2
       | ...
       | patn =&gt; en
</html:code></fr:pre><fr:p>Note the similarity to a <fr:link
href="150-001J.xml"
type="local"
addr="150-001J"><fr:code>case</fr:code> expressions</fr:link>. For this to typecheck, we must have that <fr:code>e : t</fr:code> for some type <fr:code>t</fr:code>, and each <fr:code>ei : t</fr:code>, and each <fr:code>pati</fr:code> is a pattern matching the <fr:link
href="150-00B0.xml"
type="local"
addr="150-00B0"><fr:code>exn</fr:code> type</fr:link>. A <fr:code>handle</fr:code> expression will first evaluate <fr:code>e</fr:code>. If it evaluates to a value, that value is provided immediately; or, if it raises an exception, the corresponding handler is evaluated. If no patterns match, the expression is simply re-raised.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1700</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0080</fr:addr><fr:route>150-0080.xml</fr:route><fr:title>Accepted language of a machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a string <fr:tex>\texttt {s}</fr:tex> is <fr:em>accepted</fr:em> by a <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">machine</fr:link> <fr:tex>\texttt {m}</fr:tex> when <fr:tex>\texttt {run m s} \cong  \texttt {true}</fr:tex>. We write <fr:tex
display="block">\mathcal {A}(\tt m) = \{\texttt {s : char list} \mid  \texttt {run m s} \cong  \texttt {true}\}</fr:tex> for the set of all strings accepted by machine <fr:tex>\texttt {m}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1701</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A8</fr:addr><fr:route>150-00A8.xml</fr:route><fr:title>Associative function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>g : t * t -&gt; t</fr:code>. We say that <fr:code>g</fr:code> is a <fr:em>associative</fr:em> when for all <fr:code>a</fr:code>, <fr:code>b</fr:code>, <fr:code>c</fr:code>: <fr:tex
display="block">\texttt {g (g (a, b), c)} \cong  \texttt {g (a, g (b, c))}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1702</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0007</fr:addr><fr:route>150-0007.xml</fr:route><fr:title>Base types</fr:title></fr:frontmatter><fr:mainmatter>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>int</fr:code></html:td>

  <html:td><fr:code>0</fr:code>, <fr:code>1</fr:code>, <fr:code>150</fr:code>, <fr:code>~12</fr:code>, ...</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>real</fr:code></html:td>

  <html:td><fr:code>1.5</fr:code>, <fr:code>3.14</fr:code>, <fr:code>0.0001</fr:code>, ...</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>bool</fr:code></html:td>

  <html:td><fr:code>false</fr:code>, <fr:code>true</fr:code></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>char</fr:code></html:td>

  <html:td><fr:code>#"a"</fr:code>, <fr:code>#"b"</fr:code>, <fr:code>#"7"</fr:code>, ...</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>string</fr:code></html:td>

  <html:td><fr:code>""</fr:code>, <fr:code>"hello world"</fr:code>, ...</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1703</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0038</fr:addr><fr:route>150-0038.xml</fr:route><fr:title>Big-<fr:tex>\mathcal {O}</fr:tex></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Sometimes, we wish to simplify exact bounds, ignoring linear factors. To do this, we use big-<fr:tex>\mathcal {O}</fr:tex> notation.</fr:p><fr:p>Let <fr:tex>X</fr:tex> be a set and let <fr:tex>f, g : X \to  \mathbb {N}</fr:tex>. We say that <fr:tex>f \in  \mathcal {O}(g)</fr:tex> when there exist constants <fr:tex>a, b : \mathbb {N}</fr:tex> such that <fr:tex>f \le  ag + b</fr:tex>, i.e. <fr:tex
display="block">\forall  x : X, f(x) \le  ag(x) + b.</fr:tex></fr:p><fr:p>We write <fr:tex>\mathcal {O}(g)</fr:tex> for the set of all functions <fr:tex>f</fr:tex> bounded by <fr:tex>g</fr:tex>, i.e. <fr:tex
display="block">\mathcal {O}(g) = \{f : X \to  \mathbb {N} \mid  f \in  \mathcal {O}(g) \}.</fr:tex></fr:p><fr:p>Traditionally, <fr:tex>X = \mathbb {N}</fr:tex> and function inputs are assumed to be named <fr:tex>n</fr:tex>: for example, <fr:tex>\mathcal {O}(n^2)</fr:tex> is syntactic sugar for <fr:tex>\mathcal {O}(n \mapsto  n^2)</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1704</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002N</fr:addr><fr:route>150-002N.xml</fr:route><fr:title>Binary tree with <fr:code>int</fr:code>s at the nodes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We define the following <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link> to represent binary trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype tree
  = Empty
  | Node of tree * int * tree
</html:code></fr:pre><fr:p>Note that <fr:code>tree</fr:code> is used recursively.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1705</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006R</fr:addr><fr:route>150-006R.xml</fr:route><fr:title>Bind abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-006L.xml"
type="local"
addr="150-006L"><fr:code>bind</fr:code></fr:link>, which takes a function <fr:code>f : 'a -&gt; 'b list</fr:code> and a list <fr:code>'a list</fr:code> and applies the function on each <fr:code>'a</fr:code> to get a resulting flattened <fr:code>'b list</fr:code>.</fr:p><fr:p>This specification can be generalized beyond <fr:code>'a list</fr:code> to arbitrary types <fr:code>'a t</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* bind : ('a -&gt; 'b t) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES: ...
 *)
</html:code></fr:pre><fr:p>The ENSURES should contain some conditions similar to those given for the <fr:link
href="150-006D.xml"
type="local"
addr="150-006D">map abstraction</fr:link>, but we elide them in this class.</fr:p><fr:p>We can always implement the infix <fr:code>&gt;&gt;=</fr:code> using a <fr:code>bind</fr:code> implementation:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (x : 'a t) &gt;&gt;= (f : 'a -&gt; 'b t) : 'b t = bind f x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1706</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0059</fr:addr><fr:route>150-0059.xml</fr:route><fr:title>Circularity error</fr:title></fr:frontmatter><fr:mainmatter><fr:p>With recursion, sometimes there is no valid type for an expression because the output type contains itself as a component. For example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f 0 = 0
  | f n = (f (n - 1), 0)
</html:code></fr:pre><fr:p>This function is not well typed.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>653</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#188</fr:addr><fr:route>unstable-188.xml</fr:route><fr:parent>150-0059</fr:parent></fr:frontmatter><fr:mainmatter>
  Assume <fr:code>f : int -&gt; t</fr:code>, for some <fr:code>t</fr:code>.
  Then, in the second clause, <fr:code>(f (n - 1), 0) : t * int</fr:code>.
  However, since this is returned by <fr:code>f</fr:code> itself, this would mean that <fr:code>t = t * int</fr:code>, leading to a contradiction.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1707</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003A</fr:addr><fr:route>150-003A.xml</fr:route><fr:title>Common big-<fr:tex>\mathcal {O}</fr:tex> classes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following classes are distinct, ordered by inclusion from top to bottom:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:td><fr:strong>Class</fr:strong></html:td>

  <html:td><fr:strong>Common Name</fr:strong></html:td>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>

  <html:td>constant</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(\log  n)</fr:tex></html:td>

  <html:td>logarithmic</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n)</fr:tex></html:td>

  <html:td>linear</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n \log  n)</fr:tex></html:td>

  <html:td>quasilinear/log-linear</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n^2)</fr:tex></html:td>

  <html:td>quadratic</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n^3)</fr:tex></html:td>

  <html:td>cubic</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(2^n)</fr:tex></html:td>

  <html:td>exponential</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1708</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005I</fr:addr><fr:route>150-005I.xml</fr:route><fr:title>Comparison function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the implementation of the <fr:link
href="150-004J.xml"
type="local"
addr="150-004J">insert auxiliary function</fr:link>, we used <fr:code>Int.compare : int * int -&gt; order</fr:code>. To sort a list of <fr:code>'a</fr:code>s, we need a function of type <fr:code>'a * 'a -&gt; order</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1709</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001D</fr:addr><fr:route>150-001D.xml</fr:route><fr:title>Constant pattern</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Constants, such as <fr:code>int</fr:code>, <fr:code>string</fr:code>, and <fr:code>bool</fr:code> values, are patterns. Make sure to match them all!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1710</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004V</fr:addr><fr:route>150-004V.xml</fr:route><fr:title>Contradiction in type inference</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If a variable is used in such a way that it has two incompatible types, a type error will be produced.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1711</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0077</fr:addr><fr:route>150-0077.xml</fr:route><fr:title>Corecursion</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Definitions such as <fr:ref
addr="150-0074"
href="150-0074.xml"
taxon="Example"></fr:ref> do not go by recursion on an input; nothing needs to ever shrink. Instead, they go by <fr:em>corecursion</fr:em>, producing a finite amount of data but offering to produce more if desired.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1712</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0031</fr:addr><fr:route>150-0031.xml</fr:route><fr:title>Cost analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:em>Goal:</fr:em> understand the cost of programs. Some choices:</fr:p><fr:ul><fr:li>Time each execution. However, this is machine-dependent.</fr:li>
  <fr:li>Count a given metric (recursive calls; additions; evaluation steps; etc.). This is abstract enough to be proved, and it corresponds to real time.</fr:li></fr:ul><fr:p>First, we choose a <fr:em>cost metric</fr:em> and <fr:em>size metrics</fr:em> for inputs. Then, we:</fr:p><fr:ol><fr:li>Write a recurrence following the structure of the code, computing cost from input sizes.</fr:li>
  <fr:li>Solve for a closed form.</fr:li>
  <fr:li>Give a simple asymptotic (big-<fr:tex>\mathcal {O}</fr:tex>) solution.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1713</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009S</fr:addr><fr:route>150-009S.xml</fr:route><fr:title>Cost graph</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>cost graph</fr:em> is a visualization technique for parallel processes consisting of a directed acyclic graph with designated start and end nodes. They are defined inductively as follows, where we implicitly treat all edges as top-to-bottom:</fr:p><fr:ol><fr:li>
    Atomic units are variables representing cost of an abstract operation, drawn using a hexagon:
    <fr:embedded-tex
hash="47e3f60755d4d4f26d0f504419e5c6c9"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  [hexagon] {\texttt {f}};
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>
    There is an empty cost graph <fr:tex>0</fr:tex>:
    <fr:embedded-tex
hash="f81f9820b8348f991649a49e01e0eabf"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  {$\bullet $};
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>Two cost graphs <fr:tex>G_1</fr:tex> and <fr:tex>G_2</fr:tex> can be composed in sequence, written <fr:tex>G_1 \triangleright  G_2</fr:tex>, representing data dependency:
    <fr:embedded-tex
hash="528359005d8acb8bc148f28d342173aa"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  (G1) at (0,1) {$G_1$};
        \node  (G2) at (0,0) {$G_2$};
        \path  (G1) edge (G2);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>
    Two cost graphs <fr:tex>G_1</fr:tex> and <fr:tex>G_2</fr:tex> can be composed in parallel, written <fr:tex>G_1 \otimes  G_2</fr:tex>, representing data independence:
    <fr:embedded-tex
hash="8b34a78034ef9eb4849773bd8a1b4d05"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  (G1) at (-1,0) {$G_1$};
        \node  (G2) at (1,0) {$G_2$};
        \node  (start) at (0,1) {$\bullet $};
        \node  (end) at (0,-1) {$\bullet $};
        \path  (start) edge (G1);
        \path  (start) edge (G2);
        \path  (G1) edge (end);
        \path  (G2) edge (end);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1714</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0068</fr:addr><fr:route>150-0068.xml</fr:route><fr:title>Currying</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a function is <fr:em>curried</fr:em>, named for mathematician <fr:link
href="https://en.wikipedia.org/wiki/Haskell_Curry"
type="external">Haskell Curry</fr:link>, when it takes in multiple arguments one at a time, producing a function accepting the rest of the arguments.</fr:p><fr:p>For example, the type <fr:code>t1 -&gt; t2 -&gt; t3</fr:code> is curried, but the type <fr:code>t1 * t2 -&gt; t3</fr:code> is not (sometimes called "uncurried").</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1715</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002H</fr:addr><fr:route>150-002H.xml</fr:route><fr:title>Datatype declaration</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>datatype</fr:code> declaration lets us define a new type that can be pattern-matched on.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype newTypeName
  = Constructor1 of dataToContain1
  | Constructor2 of dataToContain2
  | Constructor3  (* does not contain any data *)
  | ...
  | ConstructorN of dataToContainN
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1716</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BB</fr:addr><fr:route>150-00BB.xml</fr:route><fr:title>Effect</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An <fr:em>effect</fr:em> is something the evaluation of a program can do aside from returning a value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1717</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AH</fr:addr><fr:route>150-00AH.xml</fr:route><fr:title>Empty sequence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, we can define a function to create an empty sequence:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* empty : unit -&gt; 'a Seq.t
 * REQUIRES: true
 * ENSURES: empty () ~= &lt;&gt;
 *)
fun empty () = Seq.tabulate (fn _ =&gt; raise Fail "impossible") 0
</html:code></fr:pre><fr:p>This function has constant work and span.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1718</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00BT</fr:addr><fr:route>150-00BT.xml</fr:route><fr:title>Equality of reference cells</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Reference cells can be compared for equality using <fr:code>op = : 'a ref * 'a ref -&gt; bool</fr:code>. This compares the "addresses", not the contained data. Every reference cell created (using <fr:code>ref</fr:code>) is fresh and not equal to any previously-defined reference cells.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1719</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00B1</fr:addr><fr:route>150-00B1.xml</fr:route><fr:title>Exception declaration</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An exception can be declared as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">exception Constructor1
exception Constructor2 of dataToContain2
</html:code></fr:pre><fr:p>Notice the similarity to <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link>. However, here, we only give one constructor per declaration: since the <fr:link
href="150-00B0.xml"
type="local"
addr="150-00B0"><fr:code>exn</fr:code> type</fr:link> has infinitely many constructors, we only provide one more.</fr:p><fr:p>Like a <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link>, an exception declaration can also go in a signature, requiring that the structure provide a matching exception declaration.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1720</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0005</fr:addr><fr:route>150-0005.xml</fr:route><fr:title>Expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An expression <fr:tex>e</fr:tex> is a program that can be evaluated.</fr:p><fr:ul><fr:li>Every value is also an expression.</fr:li>
  <fr:li>Until the end of the course, we make the blanket assumption that all expressions <fr:tex>e</fr:tex> evaluate to some value <fr:tex>v</fr:tex>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1721</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-007D</fr:addr><fr:route>150-007D.xml</fr:route><fr:title>Extensional equivalence at <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">stream</fr:link> type: coinduction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>t</fr:code> be an arbitrary type, and let <fr:code>s0</fr:code> and <fr:code>s0'</fr:code> be of type <fr:code>t stream</fr:code>. To show that <fr:tex>\texttt {s0} \cong  \texttt {s0'}</fr:tex>:</fr:p><fr:ol><fr:li>Choose a relation <fr:tex>R(-, -)</fr:tex> on pairs of <fr:code>t stream</fr:code>s that relates pairs of streams that you expect to be equivalent.</fr:li>
  <fr:li><fr:strong>Start State:</fr:strong> Show that <fr:tex>R(\texttt {s0}, \texttt {s0'})</fr:tex>, guaranteeing that the streams you care about are related.</fr:li>
  <fr:li><fr:strong>Preservation:</fr:strong> Then, show that for all <fr:code>s</fr:code> and <fr:code>s'</fr:code>, if <fr:tex>R(\texttt {s}, \texttt {s'})</fr:tex>, then:
    <fr:ol><fr:li>the heads are the same, <fr:tex>\texttt {head s} \cong  \texttt {head s'}</fr:tex> (the "co-base case", since no more stream data comes after the head); and</fr:li>
      <fr:li>the tails stay related, <fr:tex>R(\texttt {tail s}, \texttt {tail s'})</fr:tex> (the "coinductive conclusion", dual to the inductive hypothesis).</fr:li></fr:ol></fr:li></fr:ol><fr:p>This proof technique is called <fr:em>coinduction</fr:em>.</fr:p><fr:p>Notice that this definition has some similarities with <fr:link
href="150-000T.xml"
type="local"
addr="150-000T">extensional equivalence at function types</fr:link>: both check that you see equivalent results when you use the expressions in equivalent ways.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1722</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000Q</fr:addr><fr:route>150-000Q.xml</fr:route><fr:title>Extensional equivalence at base types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Two expressions <fr:tex>e</fr:tex> and <fr:tex>e'</fr:tex> (that evaluate to values) are <fr:em>extensionally equivalent</fr:em>, written <fr:tex>e \cong  e'</fr:tex>, when they evaluate to the same value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1723</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000T</fr:addr><fr:route>150-000T.xml</fr:route><fr:title>Extensional equivalence at function types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Suppose <fr:code>f</fr:code> and <fr:code>f'</fr:code> are both of type <fr:code>t1 -&gt; t2</fr:code>. Then, <fr:tex>\texttt {f} \cong  \texttt {f'}</fr:tex> when for all values <fr:code>x</fr:code> and <fr:code>x'</fr:code> of type <fr:code>t1</fr:code>, <fr:tex>\texttt {x} \cong  \texttt {x'}</fr:tex> implies <fr:tex>\texttt {f x} \cong  \texttt {f' x'}</fr:tex>.</fr:p><fr:p>When <fr:code>t1</fr:code> is a <fr:link
href="150-000Q.xml"
type="local"
addr="150-000Q">base type</fr:link>, this is equivalent to: for all values <fr:code>x : t1</fr:code>, <fr:tex>\texttt {f x} \cong  \texttt {f' x}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1724</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000S</fr:addr><fr:route>150-000S.xml</fr:route><fr:title>Extensional equivalence at product types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>It is the case that <fr:tex
display="block">(e_1, e_2) \cong  (e_1', e_2')</fr:tex> when <fr:tex>e_1 \cong  e_1'</fr:tex> and <fr:tex>e_2 \cong  e_2'</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1725</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008A</fr:addr><fr:route>150-008A.xml</fr:route><fr:title>Extensional equivalence of <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">lazy state machines</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>m0</fr:code> and <fr:code>m0'</fr:code> be of type <fr:code>machine</fr:code>. To show that <fr:tex>\texttt {m0} \cong  \texttt {m0'}</fr:tex>:</fr:p><fr:ol><fr:li>Choose a relation <fr:tex>R(-, -)</fr:tex> on pairs of <fr:code>machine</fr:code>s that relates pairs of machines that you expect to be equivalent.</fr:li>
  <fr:li><fr:strong>Start State:</fr:strong> Show that <fr:tex>R(\texttt {m0}, \texttt {m0'})</fr:tex>, guaranteeing that the streams you care about are related.</fr:li>
  <fr:li><fr:strong>Preservation:</fr:strong> Then, show that for all <fr:code>m</fr:code> and <fr:code>m'</fr:code>, if <fr:tex>R(\texttt {m}, \texttt {m'})</fr:tex>, then:
    <fr:ol><fr:li>the statuses are the same, <fr:tex>\texttt {status m} \cong  \texttt {status m'}</fr:tex> (the "co-base case", since no more characters are read after the status is checked); and</fr:li>
      <fr:li>for all <fr:code>c : char</fr:code>, the feeding the machines <fr:code>c</fr:code> causes them to stay related, <fr:tex>R(\texttt {feed m c}, \texttt {feed m' c})</fr:tex> (the "coinductive conclusion", dual to the inductive hypothesis).</fr:li></fr:ol></fr:li></fr:ol><fr:p>This proof technique is called <fr:em>coinduction</fr:em>.</fr:p><fr:p>This definition is analogous to <fr:link
href="150-007D.xml"
type="local"
addr="150-007D">extensional equivalence of streams</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1726</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00B3</fr:addr><fr:route>150-00B3.xml</fr:route><fr:title>Extensional equivalence with effects</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When considering exceptions, we say that <fr:tex>e_1 \cong  e_2</fr:tex> when both:</fr:p><fr:ol><fr:li><fr:tex>e_1</fr:tex> and <fr:tex>e_2</fr:tex> perform indistinguishable effects; for example, they raise the same exceptions, loop infinitely, or print the same string.</fr:li>
  <fr:li>If <fr:tex>e_1 \hookrightarrow  v_1</fr:tex> and <fr:tex>e_2 \hookrightarrow  v_2</fr:tex>, then <fr:tex>v_1 \cong  v_2</fr:tex> as pure expressions (i.e., as described before).</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1727</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006H</fr:addr><fr:route>150-006H.xml</fr:route><fr:title>Fold abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-0063.xml"
type="local"
addr="150-0063"><fr:code>foldr</fr:code></fr:link>. Crucially, it sent <fr:code>[x1, x2, ..., xn]</fr:code>, i.e., <fr:blockquote><fr:code>op:: (x1, op:: (x2, ..., op:: (xn, nil)))</fr:code></fr:blockquote> to <fr:blockquote><fr:code>f (x1, f (x2, ..., f (xn, init)))</fr:code></fr:blockquote> by replacing <fr:code>op::</fr:code> with <fr:code>f</fr:code> and <fr:code>nil</fr:code> with <fr:code>init</fr:code>.</fr:p><fr:p>If we rewrite the list datatype as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a list = Cons of 'a * 'a list | Nil
</html:code></fr:pre><fr:p>We might as well write <fr:code>foldr</fr:code> as:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldr : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b *)
fun foldr (cons : 'a * 'b -&gt; 'b) (nil : 'b) (l : 'a list) : 'b =
  case l of
    Cons (x, xs) =&gt; cons (x, foldr cons nil xs)
  | Nil          =&gt; nil
</html:code></fr:pre><fr:p>The type of each argument matches the type of the constructor, swapping <fr:code>'a list</fr:code> for <fr:code>'b</fr:code>. Here, <fr:code>cons</fr:code> is just a function (not a constructor!) to replace every <fr:code>Cons</fr:code> with, and <fr:code>nil</fr:code> is just a value to replace every <fr:code>Nil</fr:code> with.</fr:p><fr:p>The general recipe is as follows:</fr:p><fr:ol><fr:li>For each constructor, replace the name of the type with <fr:code>'b</fr:code>, including recursive uses.</fr:li>
  <fr:li>Take in each of these functions/values meant to replace the constructor as arguments.</fr:li>
  <fr:li>In the implementation, replace each constructor with its function, performing recursive calls on substructures if there are any.</fr:li></fr:ol><fr:p>For example:</fr:p><fr:ol><fr:li>We have <fr:code>Cons : 'a * 'a list -&gt; 'a list</fr:code> and <fr:code>Nil : 'a list</fr:code>, so we get <fr:code>cons : 'a * 'b -&gt; 'b</fr:code> and <fr:code>nil : 'b</fr:code>.</fr:li>
  <fr:li>We take in <fr:code>cons</fr:code> and <fr:code>nil</fr:code> as arguments.</fr:li>
  <fr:li>The implementation is as above.</fr:li></fr:ol><fr:p>This perspective justifies the <fr:link
href="150-0064.xml"
type="local"
addr="150-0064">universality of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link></fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1728</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009A</fr:addr><fr:route>150-009A.xml</fr:route><fr:title>Freshness of types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If a functor is called multiple times, the opaquely-ascribed types created at each call will be <fr:em>fresh</fr:em>. For example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure D1 = TreeDict (StringOrdered)
structure D2 = TreeDict (StringOrdered)

val d : D1.empty = D2.empty  (* type error: D1.empty is different from D2.empty *)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1729</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000Z</fr:addr><fr:route>150-000Z.xml</fr:route><fr:title>Function application</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Function application is written using a space. If <fr:code>e : t1 -&gt; t2</fr:code> and <fr:code>e1 : t1</fr:code>, then <fr:code>e e1 : t2</fr:code>.</fr:p><fr:p>When evaluating <fr:code>e e1</fr:code>, SML does the following:</fr:p><fr:ol><fr:li><fr:code>e</fr:code> is evaluated to <fr:code>fn (x : t1) =&gt; e'</fr:code>.</fr:li>
  <fr:li><fr:code>e1</fr:code> is evaluated to <fr:code>v1</fr:code> (of type <fr:code>t1</fr:code>).</fr:li>
  <fr:li><fr:code>e'</fr:code> is evaluated, where <fr:code>v1</fr:code> is now bound to <fr:code>x</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1730</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005Z</fr:addr><fr:route>150-005Z.xml</fr:route><fr:title>Function composition</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To compose two functions <fr:code>f : 'a -&gt; 'b</fr:code> and <fr:code>g : 'b -&gt; 'c</fr:code>, we can define <fr:code>(g o f) : 'a -&gt; 'c</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (op o) (g : 'b -&gt; 'c, f : 'a -&gt; 'b) : 'a -&gt; 'c = fn (x : 'a) =&gt; g (f x)
</html:code></fr:pre><fr:p>We can equivalently define composition in the following ways:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun g o f = fn x =&gt; g (f x)
fun (g o f) x = g (f x)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1731</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0013</fr:addr><fr:route>150-0013.xml</fr:route><fr:title>Function specifications</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* f : t1 -&gt; t2
 * REQUIRES: ...some assumptions about x...
 * ENSURES: ...some guarantees about (f x)...
 *)
fun f (x : t1) : t2 = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1732</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000L</fr:addr><fr:route>150-000L.xml</fr:route><fr:title>Function types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In math, we talk about functions <fr:tex
display="block">f : X \to  Y</fr:tex> between sets <fr:tex>X</fr:tex> and <fr:tex>Y</fr:tex>. In SML, we do the same, but where <fr:tex>X</fr:tex> and <fr:tex>Y</fr:tex> are types.</fr:p><fr:p>If <fr:code>t1</fr:code> and <fr:code>t2</fr:code> are types, then <fr:code>t1 -&gt; t2</fr:code> is the type of functions that take a value of type <fr:code>t1</fr:code> as input and produce a value of type <fr:code>t2</fr:code> as an output.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>t1 -&gt; t2</fr:code></html:td>

  <html:td><fr:code>fn (x : t1) =&gt; e</fr:code></html:td>
</html:tr>

  
</html:table>
<fr:p>If assuming that <fr:code>x : t1</fr:code> makes <fr:code>e : t2</fr:code>, then <fr:code>(fn (x : t1) =&gt; e) : t1 -&gt; t2</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1733</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-009P</fr:addr><fr:route>150-009P.xml</fr:route><fr:title>Functional parallelism</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Parallelism and functional programming go hand-in-hand.</fr:p><fr:ul><fr:li>At a low level, parallelism involves scheduling work to processors;</fr:li>
  <fr:li>but at a high level, parallelism involves indicating which expressions can be evaluated in parallel, without baking in a schedule.</fr:li></fr:ul><fr:p><fr:link
href="150-000X.xml"
type="local"
addr="150-000X">Functional programming helps</fr:link>:</fr:p><fr:ul><fr:li>Since there are no effects (like memory updates) available, evaluation order doesn't matter, and race conditions are impossible to even describe in code.</fr:li>
  <fr:li>Higher-order functions and abstract types allow complex parallelism techniques to be implemented under the hood but retain a simple interface.</fr:li>
  <fr:li>Work and span analysis lets us predict the parallel speedup without fixing the number of processors in advance.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1734</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001L</fr:addr><fr:route>150-001L.xml</fr:route><fr:title>Functions are values</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Functions <fr:em>are</fr:em> values: they do not evaluate further.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1735</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0098</fr:addr><fr:route>150-0098.xml</fr:route><fr:title>Functor</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>functor</fr:em> is a function that takes in a <fr:link
href="150-008J.xml"
type="local"
addr="150-008J">structure</fr:link> and produces another structure. The analogy is:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Expression Level</html:th>

  <html:th>Module Level</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td>type</html:td>

  <html:td>signature</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td>expression</html:td>

  <html:td>structure</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td>function</html:td>

  <html:td>functor</html:td>
</html:tr>

  
</html:table>
<fr:p>(Unfortunately, ideas such as "functors are values", "higher-order functors", and "functor signatures" are not present in Standard ML itself.)</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1736</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009C</fr:addr><fr:route>150-009C.xml</fr:route><fr:title>Functor argument syntactic sugar</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When structures take multiple arguments, it is cumbersome to write <fr:code>Arg.</fr:code> before every sub-component. So, Standard ML provides syntactic sugar where the <fr:code>Arg : sig</fr:code> and <fr:code>end</fr:code> can be left off of inputs:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor PairOrdered
  ( structure X : ORDERED
    structure Y : ORDERED
  ) : ORDERED =
  struct
    type t = X.t * Y.t
    fun compare ((x1, y1), (x2, y2)) =
      case X.compare (x1, x2) of
        EQUAL =&gt; Y.compare (y1, y2)
      | ord   =&gt; ord
  end
</html:code></fr:pre><fr:p>This is functionally the same, but it is typically more ergonomic and leads to more readable code.</fr:p><fr:p>Analogous syntactic sugar is available when a functor is applied, allowing the <fr:code>struct</fr:code> and <fr:code>end</fr:code> of an argument to be left off:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ChessOrdered =
  PairOrdered
    ( structure X = CharOrdered
      structure Y = IntOrdered
    )
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1737</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-005P</fr:addr><fr:route>150-005P.xml</fr:route><fr:title>Higher-order function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>higher-order function</fr:em> is a function that takes a function as input or produces a function as output.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1738</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A7</fr:addr><fr:route>150-00A7.xml</fr:route><fr:title>Identity element</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>z : t</fr:code> and <fr:code>g : t * t -&gt; t</fr:code>. We say that <fr:code>z</fr:code> is an <fr:em>identity element</fr:em> for <fr:code>g</fr:code> when for all <fr:code>a</fr:code>: <fr:tex
display="block">\texttt {g (a, z)} \cong  \texttt {a} \cong  \texttt {g (z, a)}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1739</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006Q</fr:addr><fr:route>150-006Q.xml</fr:route><fr:title>Infix <fr:code>&gt;&gt;=</fr:code> notation for bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Similar to the <fr:link
href="150-006P.xml"
type="local"
addr="150-006P">pipe function</fr:link>, we can reverse the argument order of <fr:link
href="150-006L.xml"
type="local"
addr="150-006L">list bind</fr:link> and view it as an infix function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix 4 &gt;&gt;=

(* op &gt;&gt;= : 'a list * ('a -&gt; 'b list) -&gt; 'b list *)
fun l &gt;&gt;= f = bind f l
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1740</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007Z</fr:addr><fr:route>150-007Z.xml</fr:route><fr:title>Lazy state machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We define state machines (sometimes known as <fr:em>automata</fr:em>) as a lazy datatype like <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">streams</fr:link>, but instead of having a single tail via <fr:code>unit -&gt;</fr:code>, we have one tail per character with <fr:code>char -&gt;</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype machine = Machine of bool * (char -&gt; machine)
</html:code></fr:pre><fr:p>We always expect a current value of type <fr:code>bool</fr:code>, representing whether or not the machine is in an accepting state (i.e., would accept the empty string). We could <fr:link
href="150-0072.xml"
type="local"
addr="150-0072">suspend</fr:link> the <fr:code>bool</fr:code>, but we choose not to for convenience.</fr:p><fr:p>Similar to <fr:link
href="150-0073.xml"
type="local"
addr="150-0073"><fr:code>head</fr:code> and <fr:code>tail</fr:code> for streams</fr:link>, we define the following helpers:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* status : machine -&gt; bool *)
fun status (Machine (b, _)) = b

(* feed : machine -&gt; char -&gt; machine *)
fun feed (Machine (_, f)) c = f c
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1741</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005S</fr:addr><fr:route>150-005S.xml</fr:route><fr:title>Left-associativity of function application</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Function application is left-associative. In other words, when <fr:code>f : t1 -&gt; t2 -&gt; t3</fr:code>, <fr:code>e1 : t1</fr:code>, and <fr:code>e2 : t2</fr:code>, the application <fr:code>f e1 e2</fr:code> is the same as <fr:code>(f e1) e2</fr:code>, applying function <fr:code>f</fr:code> to input <fr:code>e1</fr:code>, and then applying that function to <fr:code>e2</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1742</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00A4</fr:addr><fr:route>150-00A4.xml</fr:route><fr:title>Limited sequence signature: free monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can also view sequences inductively, where every sequence arises as the combination of some singletons:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    (* ...as before... *)

    val singleton : 'a -&gt; 'a seq
    val empty : unit -&gt; 'a seq
    val append : 'a seq * 'a seq -&gt; 'a seq
    val mapreduce : ('a -&gt; 'b) -&gt; 'b -&gt; ('b * 'b -&gt; 'b) -&gt; 'a seq -&gt; 'b

    (* ...more to come... *)
  end
</html:code></fr:pre><fr:p>The functions <fr:code>singleton</fr:code>, <fr:code>empty</fr:code>, and <fr:code>append</fr:code> can be implemented using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>. (Alternatively, they can be viewed as the primitive way to construct sequences, where <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link> is implemented in terms of them; however, when working with an array-based implementation of sequences, this cost bound will be worse.) The <fr:code>mapreduce</fr:code> function is the <fr:link
href="150-006H.xml"
type="local"
addr="150-006H">fold abstraction</fr:link> for sequences built this way.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1743</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009X</fr:addr><fr:route>150-009X.xml</fr:route><fr:title>Limited sequence signature: indexed collection</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The sequence signature includes the following specifications:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    type 'a t  (* abstract *)
    type 'a seq = 'a t  (* concrete *)

    val tabulate : (int -&gt; 'a) -&gt; int -&gt; 'a seq
    val length : 'a seq -&gt; int
    val nth : 'a seq -&gt; int -&gt; 'a

    (* ...more to come... *)
  end
</html:code></fr:pre><fr:p>The abstract type <fr:code>'a t</fr:code> represents a sequence of <fr:code>'a</fr:code>s, where <fr:code>'a seq</fr:code> is an alias for signature readability.</fr:p><fr:p>The implementation of <fr:code>SEQUENCE</fr:code> is called <fr:code>Seq</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure Seq :&gt; SEQUENCE = (* ... *)
</html:code></fr:pre><fr:p>The full signature and documentation is available on <fr:link
href="http://www.cs.cmu.edu/~15150/resources/libraries/sequence.pdf"
type="external">the course website</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1744</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0063</fr:addr><fr:route>150-0063.xml</fr:route><fr:title>List <fr:code>foldr</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* sum : int list -&gt; int
 * REQUIRES: true
 * ENSURES: sum [x1, ..., xn] = x1 + (x2 + (... + (xn + 0)))
 *)
fun sum nil       = 0
  | sum (x :: xs) = x + sum xs

(* concat : 'a list list -&gt; 'a list
 * REQUIRES: true
 * ENSURES: concat [x1, ..., xn] = x1 @ (x2 @ (... @ (xn @ nil)))
 *)
fun concat nil       = nil
  | concat (x :: xs) = x @ concat xs

(* commas : string list -&gt; string
 * REQUIRES: true
 * ENSURES: commas [x1, ..., xn] = (x1 ^ ", ") ^ ((x2 ^ ", ") ^ (... ^ ((xn ^ ", ") ^ ".")))
 *)
fun commas nil       = "."
  | commas (x :: xs) = (x ^ ", ") ^ commas xs

(* rebuild : 'a list -&gt; 'a list *)
fun rebuild nil       = nil
  | rebuild (x :: xs) = x :: rebuild xs

(* isort : int list -&gt; int list *)
fun isort nil       = nil
  | isort (x :: xs) = insert (x, isort xs)
</html:code></fr:pre><fr:p>All three share a common structure, combining <fr:code>x</fr:code> into the recursive call on <fr:code>xs</fr:code>. For a base case <fr:code>init : t2</fr:code> and a recursive case <fr:code>f : t1 * t2 -&gt; t2</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* combine : t1 list -&gt; t2
 * REQUIRES: true
 * ENSURES: combine [x1, ..., xn] = f (x1, f (x2, ... f (xn, init)))
 *)
fun combine nil       = init
  | combine (x :: xs) = f (x, combine xs)
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>foldr</fr:code>, that takes in such an initial value <fr:code>init</fr:code> and a combining function <fr:code>f</fr:code> and produces the corresponding <fr:code>combine</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldr : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b
 * REQUIRES: true
 * ENSURES: foldr f init [x1, ..., xn] = f (x1, f (x2, ... f (xn, init)))
 *)
fun foldr f init nil       = init
  | foldr f init (x :: xs) = f (x, foldr f init xs)
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val sum = foldr (op +) 0
val concat = foldr (op @) nil
val commas = foldr (fn (x, y) =&gt; x ^ ", " ^ y) "."
val rebuild = foldr (op ::) nil
val isort = foldr insert nil
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1745</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0065</fr:addr><fr:route>150-0065.xml</fr:route><fr:title>List <fr:code>foldl</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can also traverse a list in the other direction:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldl : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b
 * REQUIRES: true
 * ENSURES: foldr f acc [x1, ..., xn] = f (xn, ... f (x2, f (x1, acc)))
 *)
fun foldl f acc nil       = acc
  | foldl f acc (x :: xs) = foldl f (f (x, acc)) xs
</html:code></fr:pre><fr:p>Here, we traverse the list in the other direction. Rather than the <fr:code>'b</fr:code> input serving as a base case, it serves as an accumulator.</fr:p><fr:p>Equivalently, we can implement <fr:code>foldl</fr:code> using <fr:code>foldr</fr:code> and list reverse:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun foldl f acc = foldr f acc o rev
</html:code></fr:pre><fr:p>This makes it clear that if we choose the first implementation, we could implement <fr:code>rev</fr:code> using <fr:code>foldl</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val rev = foldl (op ::) nil
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1746</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006L</fr:addr><fr:route>150-006L.xml</fr:route><fr:title>List bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>bind</fr:code> takes in a function <fr:code>f : 'a -&gt; 'b list</fr:code> that produces as many <fr:code>'b</fr:code>s as it wishes; we accumulate all of them in a list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* bind : ('a -&gt; 'b list) -&gt; 'a list -&gt; 'b list *)
fun bind f nil       = nil
  | bind f (x :: xs) = f x @ bind f xs
</html:code></fr:pre><fr:p>It generalizes <fr:link
href="150-005X.xml"
type="local"
addr="150-005X">list map</fr:link>, whose function input must always produce exactly one <fr:code>'b</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1747</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0062</fr:addr><fr:route>150-0062.xml</fr:route><fr:title>List filter</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* keepEvens : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: keepEvens l ==&gt; l', where l' contains the even elements of l in the same order
 *)
fun keepEvens nil       = nil
  | keepEvens (x :: xs) =
      if isEven x
        then x :: keepEvens xs
        else keepEvens xs

(* keepMammals : animal list -&gt; animal list
 * REQUIRES: true
 * ENSURES: keepMammals l ==&gt; l', where l' contains the mammals of l in the same order
 *)
fun keepMammals nil       = nil
  | keepMammals (x :: xs) =
      if isMammal x
        then x :: keepMammals xs
        else keepMammals xs
</html:code></fr:pre><fr:p>Both share a common structure, only keeping the elements of the input list satisfying some condition. For a predicate <fr:code>f : t -&gt; bool</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* keepP : t list -&gt; t list
 * REQUIRES: true
 * ENSURES: keepP l ==&gt; l', where l' contains the elements of l satisfying p in the same order
 *)
fun keepP nil       = nil
  | keepP (x :: xs) =
      if p x
        then x :: keepP xs
        else keepP xs
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>filter</fr:code>, that takes in such a predicate <fr:code>p</fr:code> and produces the corresponding <fr:code>keepP</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* filter : ('a -&gt; bool) -&gt; 'a list -&gt; 'a list
 * REQUIRES: true
 * ENSURES: filter p l ==&gt; l', where l' contains the elements of l satisfying p in the same order
 *)
fun filter p nil       = nil
  | filter p (x :: xs) =
      if p x
        then x :: filter p xs
        else filter p xs
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val keepEvens = filter isEven
val keepMammals = filter isMammal
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1748</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005X</fr:addr><fr:route>150-005X.xml</fr:route><fr:title>List map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* incAll : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: incAll [x1, ..., xn] = [x1 + 1, ..., xn + 1]
 *)
fun incAll nil       = nil
  | incAll (x :: xs) = (x + 1) :: incAll xs

(* stringAll : int list -&gt; string list
 * REQUIRES: true
 * ENSURES: stringAll [x1, ..., xn] = [Int.toString x1, ..., Int.toString xn]
 *)
fun stringAll nil       = nil
  | stringAll (x :: xs) = Int.toString x :: stringAll xs

(* bool list -&gt; bool list
 * REQUIRES: true
 * ENSURES: flipAll [x1, ..., xn] = [not x1, ..., not xn]
 *)
fun flipAll nil       = nil
  | flipAll (x :: xs) = not x :: flipAll xs
</html:code></fr:pre><fr:p>All share a common structure, applying a function to each element of the input list. For a function <fr:code>f : t1 -&gt; t2</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* fAll : t1 list -&gt; t2 list
 * REQUIRES: true
 * ENSURES: fAll [x1, ..., xn] = [f x1, ..., f xn]
 *)
fun fAll nil       = nil
  | fAll (x :: xs) = f x :: fAll xs
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>map</fr:code>, that takes in such a function <fr:code>f</fr:code> and produces the corresponding <fr:code>fAll</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a list -&gt; 'b list
 * REQUIRES: true
 * ENSURES: map f [x1, ..., xn] = [f x1, ..., f xn]
 *)
fun map f nil       = nil
  | map f (x :: xs) = f x :: map f xs
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val incAll = map (fn x =&gt; x + 1)
val stringAll = map Int.toString
val flipAll = map not
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1749</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0022</fr:addr><fr:route>150-0022.xml</fr:route><fr:title>Lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, the type <fr:code>t list</fr:code> represents ordered lists of values of type <fr:code>t</fr:code>.</fr:p><fr:p>The values of type <fr:code>t list</fr:code> are:</fr:p><fr:ol><fr:li><fr:code>nil</fr:code>, the empty list</fr:li>
  <fr:li><fr:code>v1 :: v2</fr:code> (pronounced "cons"), where <fr:code>v1 : t</fr:code> is an element and <fr:code>v2 : t list</fr:code> is the remainder of the list</fr:li></fr:ol><fr:p>Syntactic sugar <fr:code>[v1, v2, ..., vn]</fr:code> is equivalent to <fr:code>v1 :: v2 :: ... :: vn</fr:code>, i.e. <fr:code>v1 :: (v2 :: (... :: (vn :: nil)))</fr:code>.</fr:p><fr:p>There are corresponding expressions that evaluate left-to-right.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1750</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006D</fr:addr><fr:route>150-006D.xml</fr:route><fr:title>Map abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-005X.xml"
type="local"
addr="150-005X"><fr:code>map</fr:code></fr:link>, which takes a function <fr:code>f : 'a -&gt; 'b</fr:code> and a list <fr:code>'a list</fr:code> and applies the function on each <fr:code>'a</fr:code> to get a resulting <fr:code>'b list</fr:code>.</fr:p><fr:p>This specification can be generalized beyond <fr:code>'a list</fr:code> to arbitrary types <fr:code>'a t</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES:
 * - map id = id, ie map id s = s
 * - map (f o g) = map f o map g, ie map f (map g s) = map (f o g) s
 *)
</html:code></fr:pre><fr:p>In other words, the ENSURES guarantees that <fr:code>map</fr:code> is structure-preserving.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1751</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-007A</fr:addr><fr:route>150-007A.xml</fr:route><fr:title>Maximal laziness</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a function on streams is <fr:em>maximally lazy</fr:em> when it exposes as few elements of input streams as possible at any given point in evaluation.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1752</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AV</fr:addr><fr:route>150-00AV.xml</fr:route><fr:title>Middle-tree view</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a view of sequences as trees with data at the nodes as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    (* ...as before... *)

    datatype 'a mview = Bud | Branch of 'a seq * 'a * 'a seq
    val join : 'a seq * 'a * 'a seq -&gt; 'a seq

    val showm : 'a seq -&gt; 'a mview
    val hidem : 'a mview -&gt; 'a seq
  end
</html:code></fr:pre><fr:p>These functions make sequences look like trees, hiding away some indexing:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun join (S1, x, S2) =
  Seq.append (S1, Seq.append (Seq.singleton x, S2))

fun showm (S : 'a Seq.t) : 'a Seq.mview =
  if Seq.null S then Seq.Bud else
    let
      val n = Seq.length S div 2
    in
      Branch (Seq.take S n, Seq.nth S n, Seq.drop S (n + 1))
    end

fun hidem Seq.Bud = Seq.empty ()
  | hidem (Seq.Branch (s1, x, s2)) = join (s1, x, s2)
</html:code></fr:pre><fr:p>Note: while other views (<fr:code>lview</fr:code> and <fr:code>tview</fr:code>) are available in the given sequence signature, this <fr:code>mview</fr:code> is not included by default.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1753</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A6</fr:addr><fr:route>150-00A6.xml</fr:route><fr:title>Monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>monoid</fr:em> consists of:</fr:p><fr:ol><fr:li>a type <fr:code>t</fr:code>,</fr:li>
  <fr:li>some <fr:code>z : t</fr:code>,</fr:li>
  <fr:li>and some <fr:code>g : t * t -&gt; t</fr:code> such that</fr:li>
  <fr:li><fr:code>z</fr:code> is an <fr:link
href="150-00A7.xml"
type="local"
addr="150-00A7">identity element</fr:link> for <fr:code>g</fr:code>, and</fr:li>
  <fr:li><fr:code>g</fr:code> is an <fr:link
href="150-00A8.xml"
type="local"
addr="150-00A8">associative function</fr:link>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1754</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0057</fr:addr><fr:route>150-0057.xml</fr:route><fr:title>Most general type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:em>most general type</fr:em> of an expression <fr:code>e</fr:code> is the type <fr:code>t</fr:code> such that all other types <fr:code>t'</fr:code> that could be assigned to <fr:code>e</fr:code> can be achieved by plugging in for type variables in <fr:code>t</fr:code>.</fr:p><fr:p>We say that these other types <fr:code>t'</fr:code> are <fr:em>instances of</fr:em> type <fr:code>t</fr:code>.</fr:p><fr:p>When we say that "<fr:code>e</fr:code> has type <fr:code>t</fr:code>", we implicitly mean that <fr:code>e</fr:code> has most general type <fr:code>t</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1755</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002E</fr:addr><fr:route>150-002E.xml</fr:route><fr:title>Option types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, the type <fr:code>t option</fr:code> represents at most one value of type <fr:code>t</fr:code>.</fr:p><fr:p>The values of type <fr:code>t option</fr:code> are:</fr:p><fr:ol><fr:li><fr:code>NONE</fr:code>, with no other data</fr:li>
  <fr:li><fr:code>SOME v</fr:code>, where <fr:code>v : t</fr:code> is the single element contained</fr:li></fr:ol><fr:p>There are analogous expressions and patterns.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1756</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003M</fr:addr><fr:route>150-003M.xml</fr:route><fr:title>Parallel evaluation of tuples</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In Standard ML, we can evaluate components of a tuple in parallel.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1757</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000X</fr:addr><fr:route>150-000X.xml</fr:route><fr:title>Parallelizing functional programs</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The "how" of imperative programming does not parallelize easily, since instructions can accidentally interact with each other. The "what" of functional programming does.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1758</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005C</fr:addr><fr:route>150-005C.xml</fr:route><fr:title>Parameterized type and datatype declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link> can include type variable parameters:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype ('a, 'b, 'c, ...) t = ...
</html:code></fr:pre><fr:p>In the common case that only one type variable parameter is included, the parentheses and commas are excluded:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a t = ...
</html:code></fr:pre><fr:p>Similarly, <fr:link
href="150-002K.xml"
type="local"
addr="150-002K">type alias declaration</fr:link> can include type variable parameters, too:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type ('a, 'b, 'c, ...) t = ...
type 'a t = ...
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1759</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0094</fr:addr><fr:route>150-0094.xml</fr:route><fr:title>Partial transparency using <fr:code>where type</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the signature former <fr:code>where type</fr:code>, we can make parts of a signature transparent, even if parts remain opaque. We write <fr:code>MY_SIGATURE where type t = someKnownType</fr:code> to make <fr:code>type t</fr:code> transparently be <fr:code>someKnownType</fr:code>, leaving all other types abstract.</fr:p><fr:p>This feature is commonly used alongside <fr:link
href="150-0091.xml"
type="local"
addr="150-0091">type classes</fr:link> to reveal the definition of some type in a signature.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1760</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001E</fr:addr><fr:route>150-001E.xml</fr:route><fr:title>Pattern inputs in <fr:code>fun</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f &lt;pattern&gt; : t2 = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1761</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00BK</fr:addr><fr:route>150-00BK.xml</fr:route><fr:title>Pattern matching and purity</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the presence of effects, a function defined by pattern matching only says what happens given a pure argument, since in a <fr:link
href="150-000Z.xml"
type="local"
addr="150-000Z">function application</fr:link>, arguments are evaluated first.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1762</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006P</fr:addr><fr:route>150-006P.xml</fr:route><fr:title>Pipe function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following function, pronounced "pipe", is useful for building data pipelines:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix 4 |&gt;

(* op |&gt; : 'a * ('a -&gt; 'b) -&gt; 'b *)
fun x |&gt; f = f x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1763</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005A</fr:addr><fr:route>150-005A.xml</fr:route><fr:title>Polymorphic quantification in proofs</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When proving a fact about polymorphic functions, we must be careful with quantification.</fr:p><fr:ul><fr:li>❌ If we say "for all <fr:code>l : 'a list</fr:code>, we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>", this means "for all <fr:code>l</fr:code> such that (for all types <fr:code>t</fr:code>, <fr:code>l : t list</fr:code>), we have we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>". However, the only list <fr:code>l</fr:code> satisfying "for all types <fr:code>t</fr:code>, <fr:code>l : t list</fr:code>" is <fr:code>nil</fr:code>.</fr:li>
  <fr:li>✅ If we say "for all types <fr:code>t</fr:code>, for all <fr:code>l : t list</fr:code>, we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>", this generalizes the proof that "for all <fr:code>l : int list</fr:code>, we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>", replacing <fr:code>int</fr:code> with an arbitrary type <fr:code>t</fr:code>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1764</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000V</fr:addr><fr:route>150-000V.xml</fr:route><fr:title>Principles of functional programming</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:strong>Simplicity:</fr:strong> pure, functional code is easy to reason about, test, and parallelize.</fr:li>
  <fr:li><fr:strong>Compositionality:</fr:strong> build bigger programs out of smaller ones, taking advantage of patterns.</fr:li>
  <fr:li><fr:strong>Abstraction:</fr:strong> use types/specification to guide program development.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1765</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000G</fr:addr><fr:route>150-000G.xml</fr:route><fr:title>Product types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:em>product type</fr:em> <fr:code>t1 * t2</fr:code> represents pairs whose first component is a value of type <fr:code>t1</fr:code> and whose second component is a value of type <fr:code>t2</fr:code>.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>t1 * t2</fr:code></html:td>

  <html:td><fr:code>(v1, v2)</fr:code></html:td>
</html:tr>

  
</html:table>
<fr:p>If <fr:tex>e_1 : t_1</fr:tex> and <fr:tex>e_2 : t_2</fr:tex>, then <fr:tex>(e_1, e_2) : t_1 \texttt {*} t_2</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1766</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000W</fr:addr><fr:route>150-000W.xml</fr:route><fr:title>Programming as a linguistic process</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:strong>Imperative programming</fr:strong> is telling a computer <fr:em>how</fr:em> to compute a result.<fr:tex
display="block">   \begin {aligned}     x &amp;\leftarrow  2; \\     y &amp;\leftarrow  x + x   \end {aligned} </fr:tex></fr:p><fr:p><fr:strong>Functional programming</fr:strong> is explaining what you want to compute. <fr:tex
display="block">2 + 2</fr:tex></fr:p><fr:p>Functional programming is applicable in all "high-level" programming languages.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1767</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-001V</fr:addr><fr:route>150-001V.xml</fr:route><fr:title>Proof structure mirrors program structure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The structure of a <fr:em>proof</fr:em> should mirror the structure of the <fr:em>program</fr:em>.</fr:p><fr:ol><fr:li>If the program uses recursion on a natural number <fr:code>n</fr:code>, the proof should use induction on <fr:code>n</fr:code>.</fr:li>
  <fr:li>If the program uses recursion with cases <fr:code>0</fr:code>, <fr:code>1</fr:code>, and <fr:code>n</fr:code>, the proof should use induction with base cases for <fr:code>0</fr:code> and <fr:code>1</fr:code> and an inductive case for <fr:code>n</fr:code>.</fr:li>
  <fr:li>If the program cases on <fr:code>b : bool</fr:code>, the proof should case in the same way.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1768</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00B4</fr:addr><fr:route>150-00B4.xml</fr:route><fr:title>Pure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Say that an expression <fr:tex>e</fr:tex> is <fr:em>pure</fr:em> when there exists some value <fr:tex>v</fr:tex> such that <fr:tex>e \hookrightarrow  v</fr:tex> without performing any observable effects.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1769</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009H</fr:addr><fr:route>150-009H.xml</fr:route><fr:title>Red-black invariants</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A full, balanced tree has the same number of nodes on every path from the root to each <fr:code>Empty</fr:code>. However, such trees only can have <fr:tex>2^d - 1</fr:tex> nodes, where <fr:tex>d</fr:tex> is the height (depth) of the tree. In order to maintain a similar invariant, we color some nodes <fr:em>black</fr:em> and some nodes <fr:em>red</fr:em> and only count the <fr:em>black</fr:em> nodes. The <fr:em>red</fr:em> nodes are just to fix "off-by-one" errors, where we want to add more data to a tree but don't want to increase the black height. This leads us to the following pair of invariants.</fr:p><fr:p>The <fr:em>red-black tree invariants</fr:em> require that:
<fr:ol><fr:li>Every path from the root to each <fr:code>Empty</fr:code> have the same number of black nodes, called the <fr:em>black height</fr:em>. (We treat <fr:code>Empty</fr:code> as black with black height zero.)</fr:li>
  <fr:li>There are no two red nodes adjacent to each other (referred to as <fr:em>red-red violations</fr:em>), i.e. every red parent node has two black child nodes.</fr:li></fr:ol>
The first invariant guarantees that the trees are balanced ignoring red nodes, and the second invariant ensures that ther aren't "too many" red nodes in a given tree.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1770</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BP</fr:addr><fr:route>150-00BP.xml</fr:route><fr:title>Reference primitives</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The standard library includes the following signature:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature REF =
  sig
    type 'a ref

    val ref : 'a -&gt; 'a ref
    val !   : 'a ref -&gt; 'a
    val :=  : 'a ref * 'a -&gt; unit  (* infix *)

    (* ...some helper functions... *)
  end
</html:code></fr:pre><fr:ol><fr:li>The type <fr:code>t ref</fr:code> represents mutable reference cells that store a value of type <fr:code>t</fr:code>.</fr:li>
  <fr:li>The function <fr:code>ref</fr:code> allocates a new reference cell, where the starting value of the cell is the input.</fr:li>
  <fr:li>The function <fr:code>!</fr:code> accesses the current value of the reference cell given.</fr:li>
  <fr:li>The infix function <fr:code>op :=</fr:code> takes a reference cell (of type <fr:code>t ref</fr:code>) and a compatible value (of type <fr:code>t</fr:code>) and replaces the data in the reference cell with the given value.</fr:li></fr:ol><fr:p>All of these definitions are available at the top level. The use of references is considered an <fr:link
href="150-00BB.xml"
type="local"
addr="150-00BB">effect</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1771</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0088</fr:addr><fr:route>150-0088.xml</fr:route><fr:title>Regular expression matching using machines</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can compile every regular expression to a <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">lazy state machine</fr:link>, and then we can use <fr:link
href="150-0082.xml"
type="local"
addr="150-0082"><fr:code>run</fr:code></fr:link> to figure out if a given string is accepted.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* compile : regexp -&gt; machine
 * REQUIRES: true
 * ENSURES: A(compile r) = L(r)
 *)
fun compile (Char a) = char a
  | compile Zero = zero ()
  | compile One = one ()
  | compile (Plus (r1, r2)) = plus (compile r1, compile r2)
  | compile (Times (r1, r2)) = times (compile r1, compile r2)
  | compile (Star r) = star (compile r)

(* accept : regexp -&gt; string -&gt; bool *)
fun accept r s = run (compile r) (String.explode s)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1772</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007U</fr:addr><fr:route>150-007U.xml</fr:route><fr:title>Regular expressions</fr:title></fr:frontmatter><fr:mainmatter>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Regex <fr:tex>\texttt {r}</fr:tex></html:th>

  <html:th>Language <fr:tex>\mathcal {L}(\tt r)</fr:tex></html:th>

  <html:th><fr:tex>s \in  \mathcal {L}(r)</fr:tex> when...</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>\text {a}</fr:tex></html:td>

  <html:td><fr:tex>\{\text {a}\}</fr:tex></html:td>

  <html:td><fr:tex>s = \text {a}</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathbf {0}</fr:tex></html:td>

  <html:td><fr:tex>\varnothing </fr:tex></html:td>

  <html:td>never</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathbf {1}</fr:tex></html:td>

  <html:td><fr:tex>\{\texttt {""}\}</fr:tex></html:td>

  <html:td><fr:tex>s</fr:tex> is empty</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>{r_1 + r_2}</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {L}(\tt r_1) \cup  \mathcal {L}(\tt r_2)</fr:tex></html:td>

  <html:td><fr:tex>s</fr:tex> matches <fr:tex>r_1</fr:tex> or <fr:tex>r_2</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>r_1r_2</fr:tex></html:td>

  <html:td><fr:tex>\{s_1s_2 \mid  {s_1 \in  \mathcal {L}(\tt r_1)} \text { and } {s_2 \in  \mathcal {L}(\tt r_2)}\}</fr:tex></html:td>

  <html:td><fr:tex>s = s_1s_2</fr:tex>, where <fr:tex>s_1</fr:tex> matches <fr:tex>r_1</fr:tex> and <fr:tex>s_2</fr:tex> matches <fr:tex>r_2</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>r^\ast </fr:tex></html:td>

  <html:td><fr:tex>\{s_1 \cdots  s_n \mid  {s_i \in  \mathcal {L}(\tt r)} {\text { for all } i}, \text {where } n \ge  0\}</fr:tex></html:td>

  <html:td><fr:tex>s</fr:tex> is empty, or <fr:tex>s = s_1s_2</fr:tex> where <fr:tex>s_1</fr:tex> matches <fr:tex>r</fr:tex> and <fr:tex>s_2</fr:tex> matches <fr:tex>r^\ast </fr:tex></html:td>
</html:tr>

  
</html:table>
<fr:p>In these notes, we conflate strings and character lists, e.g. <fr:code>"ab"</fr:code> with <fr:code>[#"a", #"b"]</fr:code> and <fr:code>""</fr:code> with <fr:code>[]</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1773</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005R</fr:addr><fr:route>150-005R.xml</fr:route><fr:title>Right-associativity of arrows</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Function types are right-associative. In other words, the type <fr:code>t1 -&gt; t2 -&gt; t3</fr:code> means <fr:code>t1 -&gt; (t2 -&gt; t3)</fr:code>, taking an input of type <fr:code>t1</fr:code> and producing a function of type <fr:code>t2 -&gt; t3</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1774</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0082</fr:addr><fr:route>150-0082.xml</fr:route><fr:title>Running a matching machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can run a machine <fr:code>m : machine</fr:code> on a string <fr:code>s : char list</fr:code> by recursively traversing <fr:code>s</fr:code>, feeding each character to <fr:code>m</fr:code>'s transition function and reading the status at the end.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* run : machine -&gt; char list -&gt; bool *)
fun run m nil       = status m
  | run m (c :: cs) = run (feed m c) cs
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1775</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BQ</fr:addr><fr:route>150-00BQ.xml</fr:route><fr:title>Semicolon expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:code>e1 ; e2</fr:code> is syntactic sugar for the expression <fr:code>let val _ = e1 in e2 end</fr:code>. In other words, it evaluates <fr:code>e1</fr:code> (running any effects but ignoring any returned value) and then evaluates <fr:code>e2</fr:code> (keeping the effects and return value).</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1776</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009Y</fr:addr><fr:route>150-009Y.xml</fr:route><fr:title>Sequence <fr:code>tabulate</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.tabulate</fr:code> creates a new sequence of length <fr:code>n</fr:code>, calling a function on <fr:code>0</fr:code> through <fr:code>n - 1</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.tabulate : (int -&gt; 'a) -&gt; int -&gt; 'a Seq.t
 * REQUIRES: n &gt;= 0
 * ENSURES: Seq.tabulate f n ~= &lt;f 0, f 1, ..., f (n - 1)&gt;
 *)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="0958638bc9fe79a21c5b8adc63da3e96"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node  (start) at (0, 1) {$\bullet $};
      \node [hexagon] (f0) at (-2.5, 0) {\texttt {f}};
      \node [hexagon] (f1) at (-1, 0) {\texttt {f}};
      \node  at (0, 0) {$\cdots $};
      \node [hexagon] (f2) at (1, 0) {\texttt {f}};
      \node [hexagon] (f3) at (2.5, 0) {\texttt {f}};
      \node  (end) at (0, -1) {$\bullet $};

      \path  (start) edge (f0);
      \path  (start) edge (f1);
      \path  (start) edge (f2);
      \path  (start) edge (f3);
      \path  (f0) edge (end);
      \path  (f1) edge (end);
      \path  (f2) edge (end);
      \path  (f3) edge (end);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  Its work and span <fr:em>depend on the cost of <fr:code>f</fr:code></fr:em>, but assuming <fr:code>f</fr:code> is constant-time, then <fr:code>tabulate f n</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(1)</fr:tex>.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1777</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A0</fr:addr><fr:route>150-00A0.xml</fr:route><fr:title>Sequence <fr:code>length</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.length</fr:code> computes the length of a sequence:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.length : 'a Seq.t -&gt; int
 * REQUIRES: true
 * ENSURES: Seq.length &lt;x0, ..., x_{n-1}&gt; ~= n
 *)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as a single node, which by <fr:ref
addr="150-009U"
href="150-009U.xml"
taxon="Assumption"></fr:ref> we assume has constant-time cost:
  <fr:embedded-tex
hash="6ae01abbff0dd11e938ef8bbe940eef6"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node [hexagon] (0, 0) {\small \texttt {length}};
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1778</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A1</fr:addr><fr:route>150-00A1.xml</fr:route><fr:title>Sequence <fr:code>nth</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.nth</fr:code> retrieves an element of a sequence:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.nth : 'a Seq.t -&gt; int -&gt; 'a
 * REQUIRES: 0 &lt;= i &lt; Seq.length S
 * ENSURES: Seq.nth &lt;x0, ..., x_{n-1}&gt; i ~= x_i
 *)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as a single node, which by <fr:ref
addr="150-009U"
href="150-009U.xml"
taxon="Assumption"></fr:ref> we assume has constant-time cost:
  <fr:embedded-tex
hash="d67680d53621114194211ac9c52fd895"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node [hexagon] (0, 0) {\texttt {nth}};
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1779</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A2</fr:addr><fr:route>150-00A2.xml</fr:route><fr:title>Sequence <fr:code>map</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, <fr:link
href="150-00A0.xml"
type="local"
addr="150-00A0">sequence <fr:code>length</fr:code></fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>, we can define a <fr:code>map</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a Seq.t -&gt; 'b Seq.t
 * REQUIRES: true
 * ENSURES: map f &lt;x0, ..., x_{n-1}&gt; ~= &lt;f x0, ..., f x_{n-1}&gt;
 *)
fun map f S = Seq.tabulate (fn i =&gt; f (Seq.nth S i)) (Seq.length S)

(* or equivalently: *)
fun map f S = Seq.tabulate (f o Seq.nth S) (Seq.length S)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="12a829d63d1c06d17213383b7cdf4829"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node [hexagon] (start) at (0, 2) {\small \texttt {length}};

      \node [hexagon] (nth0) at (-2.5, 1) {\texttt {nth}};
      \node [hexagon] (f0) at (-2.5, 0) {\texttt {f}};

      \node [hexagon] (nth1) at (-1, 1) {\texttt {nth}};
      \node [hexagon] (f1) at (-1, 0) {\texttt {f}};

      \node  at (0, 0) {$\cdots $};

      \node [hexagon] (nth2) at (1, 1) {\texttt {nth}};
      \node [hexagon] (f2) at (1, 0) {\texttt {f}};

      \node [hexagon] (nth3) at (2.5, 1) {\texttt {nth}};
      \node [hexagon] (f3) at (2.5, 0) {\texttt {f}};

      \node  (end) at (0, -1) {$\bullet $};

      \path  (start) edge (nth0);
      \path  (start) edge (nth1);
      \path  (start) edge (nth2);
      \path  (start) edge (nth3);
      \path  (nth0) edge (f0);
      \path  (nth1) edge (f1);
      \path  (nth2) edge (f2);
      \path  (nth3) edge (f3);
      \path  (f0) edge (end);
      \path  (f1) edge (end);
      \path  (f2) edge (end);
      \path  (f3) edge (end);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  The work and span of <fr:code>map</fr:code> <fr:em>depend on the cost of <fr:code>f</fr:code></fr:em>, but assuming <fr:code>f</fr:code> is constant-time, then <fr:code>map f S</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(1)</fr:tex>.
</fr:p><fr:p>Although it can be easily implemented as above, this function is included in the <fr:code>SEQUENCE</fr:code> signature for convenience.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1780</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AB</fr:addr><fr:route>150-00AB.xml</fr:route><fr:title>Sequence <fr:code>reduce</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.reduce</fr:code> combines the data in a sequence using a <fr:link
href="150-00A6.xml"
type="local"
addr="150-00A6">monoid</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.reduce : ('a * 'a -&gt; 'a) -&gt; 'a -&gt; 'a Seq.t -&gt; 'a
 * REQUIRES: g and z form a monoid
 * ENSURES: Seq.reduce g z &lt;x0, x1, ..., x_{n-1}&gt; ~= g (x0, g (x1, ..., g (x_{n-1}, z)))
 *)
</html:code></fr:pre><fr:p>Notice that the behavior of <fr:code>reduce</fr:code> exactly mirrors <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>, and its type is an instance of the type of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>. However, thanks to the assumption that <fr:code>g</fr:code> and <fr:code>z</fr:code> form a monoid, <fr:code>reduce</fr:code> is more efficient than <fr:code>foldr</fr:code> in parallel.</fr:p><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="36269934c8d91cfdda875f6a97a99477"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node  (start) at (0, 1) {$\bullet $};
      \node [hexagon] (g0) at (-2.5, 0) {\texttt {g}};
      \node [hexagon] (g1) at (-1, 0) {\texttt {g}};
      \node  at (0, 0) {$\cdots $};
      \node [hexagon] (g2) at (1, 0) {\texttt {g}};
      \node [hexagon] (g3) at (2.5, 0) {\texttt {g}};
      \node [hexagon] (gg0) at (-1.75, -1) {\texttt {g}};
      \node [hexagon] (gg1) at (1.75, -1) {\texttt {g}};
      \node [hexagon] (ggg) at (0, -2) {\texttt {g}};

      \path  (start) edge (g0);
      \path  (start) edge (g1);
      \path  (start) edge (g2);
      \path  (start) edge (g3);
      \path  (g0) edge (gg0);
      \path  (g1) edge (gg0);
      \path  (g2) edge (gg1);
      \path  (g3) edge (gg1);
      \path  (gg0) edge (ggg);
      \path  (gg1) edge (ggg);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  Its work and span <fr:em>depend on the cost of <fr:code>g</fr:code></fr:em>, but assuming <fr:code>g</fr:code> is constant-time, then <fr:code>reduce g z S</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(\log  n)</fr:tex>.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1781</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AE</fr:addr><fr:route>150-00AE.xml</fr:route><fr:title>Sequence <fr:code>mapreduce</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The pattern of <fr:link
href="150-00A2.xml"
type="local"
addr="150-00A2">sequence <fr:code>map</fr:code></fr:link> followed by <fr:link
href="150-00AB.xml"
type="local"
addr="150-00AB">sequence <fr:code>reduce</fr:code></fr:link> is very common. We define a hybrid function <fr:code>mapreduce</fr:code> accordingly:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* mapreduce : ('a -&gt; 'b) -&gt; 'b -&gt; ('b * 'b -&gt; 'b) -&gt; 'a Seq.t -&gt; 'b
 * REQUIRES: g and z form a monoid
 * ENSURES: Seq.mapreduce f z g ~= Seq.reduce g z o Seq.map f
 *)
fun mapreduce f z g = Seq.reduce g z o Seq.map f
</html:code></fr:pre><fr:p>In fact, this function is the <fr:link
href="150-006H.xml"
type="local"
addr="150-006H">fold</fr:link> for sequences defined using <fr:code>singleton</fr:code>, <fr:code>empty</fr:code>, and <fr:code>append</fr:code>:
<fr:tex
display="block">   \begin {aligned}     \texttt {mapreduce f z g (Seq.singleton a)} &amp;\cong  \texttt {f a} \\     \texttt {mapreduce f z g (Seq.empty ())} &amp;\cong  \texttt {z} \\     \texttt {mapreduce f z g (Seq.append (s1, s2))} &amp;\cong  \texttt {g (mr f z g s1, mr f z g s2)}   \end {aligned} </fr:tex>
We abbreviate <fr:code>mapreduce</fr:code> as <fr:code>mr</fr:code> here for brevity.</fr:p><fr:p>The monoid requirements on <fr:code>reduce</fr:code> (and <fr:code>mapreduce</fr:code>) are justified by the behavior of <fr:code>append</fr:code> and <fr:code>empty</fr:code>. For example:
<fr:tex
display="block">   \begin {aligned}     &amp;\texttt {g (z, mapreduce f z g s)} \\     &amp;\cong  \texttt {g (mapreduce f z g (Seq.empty ()), mapreduce f z g s)} \\     &amp;\cong  \texttt {mapreduce f z g (Seq.append (Seq.empty (), s))} \\     &amp;\cong  \texttt {mapreduce f z g s}   \end {aligned} </fr:tex>
Here, since <fr:tex>\texttt {Seq.append (Seq.empty (), s)} \cong  \texttt {s}</fr:tex>, we must have that <fr:code>z</fr:code> is a left identity for <fr:code>g</fr:code>. Similar reasoning justifies that <fr:code>z</fr:code> must be a right identity and <fr:code>g</fr:code> must be associative.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1782</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AI</fr:addr><fr:route>150-00AI.xml</fr:route><fr:title>Sequence append</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, <fr:link
href="150-00A0.xml"
type="local"
addr="150-00A0">sequence <fr:code>length</fr:code></fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>, we can define a function to append two sequences:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* append : 'a Seq.t * 'a Seq.t -&gt; 'a Seq.t
 * REQUIRES: true
 * ENSURES: append (&lt;x0, ..., x_{m-1}&gt;, &lt;y0, ..., y_{n-1}&gt;) ~= &lt;x0, ..., x_{m-1}, y0, ..., y_{n-1}&gt;
 *)
fun append (S1, S2) =
  Seq.tabulate
    (fn i =&gt; if i &lt; Seq.length S1 then Seq.nth S1 i else Seq.nth S2 (i - Seq.length S1))
    (Seq.length S1 + Seq.length S2)
</html:code></fr:pre><fr:p>Based on the cost graphs for <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, <fr:link
href="150-00A0.xml"
type="local"
addr="150-00A0">sequence <fr:code>length</fr:code></fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>, we find that this function has work <fr:tex>\mathcal {O}(m + n)</fr:tex> and span <fr:tex>\mathcal {O}(1)</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1783</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000N</fr:addr><fr:route>150-000N.xml</fr:route><fr:title>Shadowing</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val tau : real = 6.28
val radius : real = 5.0
val area : real = tau * radius
val radius : real = 10.0
</html:code></fr:pre><fr:p>The value bound to <fr:code>area</fr:code> is <fr:code>31.4</fr:code> at the end (not, e.g., <fr:code>62.8</fr:code>). The new definition <fr:code>radius</fr:code> does not affect the previous definition, which <fr:code>area</fr:code> still refers back to.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1784</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008H</fr:addr><fr:route>150-008H.xml</fr:route><fr:title>Signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>signature</fr:em> is the type of a <fr:link
href="150-008J.xml"
type="local"
addr="150-008J">structure</fr:link>. We say that a structure <fr:em>ascribes</fr:em> to a signature.</fr:p><fr:p>We can declare a signature using the <fr:code>signature</fr:code> keyword, and we can write a signature using <fr:code>sig ... end</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature MY_SIGNATURE =
  sig
    (* signature specification here *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1785</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001T</fr:addr><fr:route>150-001T.xml</fr:route><fr:title>Simple induction on natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all natural numbers <fr:tex>n \in  \{0, 1, 2, 3, \cdots \}</fr:tex>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>Inductive Case: Prove that if the property holds on <fr:tex>n</fr:tex>, then the property holds on <fr:tex>n + 1</fr:tex>.</fr:li></fr:ol><fr:p>Then:</fr:p><fr:ul><fr:li>The property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>1 = 0 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>2 = 1 + 1</fr:tex>, since the property holds on <fr:tex>1</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>3 = 2 + 1</fr:tex>, since the property holds on <fr:tex>2</fr:tex>.</fr:li>
  <fr:li>...and so on.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1786</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AG</fr:addr><fr:route>150-00AG.xml</fr:route><fr:title>Singleton sequence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, we can define a function to create a sequence with one element:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* singleton : 'a -&gt; 'a Seq.t
 * REQUIRES: true
 * ENSURES: singleton a ~= &lt;a&gt;
 *)
fun singleton a = Seq.tabulate (fn _ =&gt; a) 1
</html:code></fr:pre><fr:p>This function has constant work and span.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1787</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-004I</fr:addr><fr:route>150-004I.xml</fr:route><fr:title>Sorting algorithm specification</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The result of sorting <fr:code>l : int list</fr:code> should be:</fr:p><fr:ol><fr:li>Sorted (nondecreasing/weakly ascending) according to <fr:link
href="150-004F.xml"
type="local"
addr="150-004F"><fr:code>Int.compare</fr:code></fr:link>.</fr:li>
  <fr:li>A permutation of <fr:code>l</fr:code>.</fr:li></fr:ol><fr:p>For cost, we count the number of comparisons performed.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1788</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0067</fr:addr><fr:route>150-0067.xml</fr:route><fr:title>Staging</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:link
href="150-0068.xml"
type="local"
addr="150-0068">Curried functions</fr:link> can perform some intermediate computation before receiving all of their arguments.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1789</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0073</fr:addr><fr:route>150-0073.xml</fr:route><fr:title>Stream</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using a <fr:link
href="150-0072.xml"
type="local"
addr="150-0072">suspension</fr:link>, we can define a type of streams as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a stream = Stream of unit -&gt; 'a * 'a stream
</html:code></fr:pre><fr:p>Here, <fr:code>Stream</fr:code> takes the role of <fr:code>::</fr:code>, but storing a suspension of a first element and the remainder of the stream.</fr:p><fr:p>Note that in this formulation, <fr:em>every stream is infinite</fr:em>.</fr:p><fr:p>The following helper function computes the first element of a stream and its tail:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* expose : 'a stream -&gt; 'a * 'a stream *)
fun expose (Stream susp : 'a stream) : 'a * 'a stream = susp ()
</html:code></fr:pre><fr:p>We call the first element of a stream its head, and the remainder its tail.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fst (x, y) = x
fun snd (x, y) = y

fun head (s : 'a stream) : 'a = fst (expose s)
fun tail (s : 'a stream) : 'a stream = snd (expose s)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1790</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001X</fr:addr><fr:route>150-001X.xml</fr:route><fr:title>Strong induction on natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all natural numbers <fr:tex>n \in  \{0, 1, 2, 3, \cdots \}</fr:tex>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>Inductive Case: Prove that if the property holds on all <fr:tex>m \le  n</fr:tex>, then the property holds on <fr:tex>n + 1</fr:tex>.</fr:li></fr:ol><fr:p>Then:</fr:p><fr:ul><fr:li>The property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>1 = 0 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>2 = 1 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex> and <fr:tex>1</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>3 = 2 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>, <fr:tex>1</fr:tex>, and <fr:tex>2</fr:tex>.</fr:li>
  <fr:li>...and so on.</fr:li></fr:ul><fr:p>Contrast this technique with <fr:link
href="150-001T.xml"
type="local"
addr="150-001T">simple induction</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1791</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0027</fr:addr><fr:route>150-0027.xml</fr:route><fr:title>Structural induction on <fr:code>int list</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all list values <fr:code>l : int list</fr:code>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:code>nil</fr:code>.</fr:li>
  <fr:li>Inductive Case: Prove that for all <fr:code>x : int</fr:code> and <fr:code>xs : int list</fr:code>, if the property holds on <fr:code>xs</fr:code>, then the property holds on <fr:code>x :: xs</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1792</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002T</fr:addr><fr:route>150-002T.xml</fr:route><fr:title>Structural induction on <fr:link
href="150-002N.xml"
type="local"
addr="150-002N"><fr:code>tree</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all tree values <fr:code>t : tree</fr:code>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:code>Empty</fr:code>.</fr:li>
  <fr:li>Inductive Case: Prove that for all <fr:code>x : int</fr:code> and <fr:code>l, r : tree</fr:code>, if the property holds on both <fr:code>l</fr:code> and <fr:code>r</fr:code> (inductive hypotheses), then the property holds on <fr:code>Node (l, x, r)</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1793</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008J</fr:addr><fr:route>150-008J.xml</fr:route><fr:title>Structure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can declare a structure using the <fr:code>structure</fr:code> keyword, and we can write a structure using <fr:code>struct ... end</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure MyStructure =
  struct
    (* declarations here *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1794</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008V</fr:addr><fr:route>150-008V.xml</fr:route><fr:title>Structure equivalence via representation independence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Two structures <fr:code>M1, M2 : S</fr:code> are equivalent when:</fr:p><fr:ul><fr:li>For each abstract <fr:code>type t</fr:code>, we give a relation <fr:tex>R_\texttt {t}(-, -)</fr:tex> relating <fr:code>M1.t</fr:code> to <fr:code>M2.t</fr:code>.</fr:li>
  <fr:li>All values declared are <fr:tex>\cong </fr:tex>, where <fr:tex>R_\texttt {t}</fr:tex> is taken as the notion of equivalence for <fr:code>type t</fr:code>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1795</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0072</fr:addr><fr:route>150-0072.xml</fr:route><fr:title>Suspension</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:code>v : unit -&gt; t</fr:code> is called a <fr:em>suspension</fr:em> (or <fr:em>thunk</fr:em>), since it contains a "suspended", not-yet-evaluated expression of type <fr:code>t</fr:code>.</fr:p><fr:p>We suspend an expression <fr:code>e : t</fr:code> via <fr:code>fn () =&gt; e</fr:code>.</fr:p><fr:p>To compute the result of the expression <fr:code>e</fr:code>, we evaluate <fr:code>v ()</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1797</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007N</fr:addr><fr:route>150-007N.xml</fr:route><fr:title>The <fr:code>match</fr:code> algorithm using combinators</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a <fr:link
href="150-0067.xml"
type="local"
addr="150-0067">staged</fr:link> version of <fr:link
href="150-007L.xml"
type="local"
addr="150-007L">the <fr:code>match</fr:code> algorithm</fr:link> elegantly using some combinators.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* match : regexp -&gt; char list -&gt; char list validator *)
fun match (r : regexp) (s : char list) : char list validator =
  case r of
    Char a =&gt;
      ( case s of
          nil =&gt; FALSE
        | c :: cs =&gt; if a = c then TEST s' else FALSE
      )
  | Zero =&gt; FALSE
  | One =&gt; TEST s
  | Plus (r1, r2) =&gt; match r1 s ORELSE match r2 s
  | Times (r1, r2) =&gt; match r1 s &gt;&gt;= match r2
  | Star r =&gt;
      TEST s
      ORELSE match r s &gt;&gt;= (fn s' =&gt; if s' &lt;&lt; s then match (Star r) s' else FALSE)
</html:code></fr:pre><fr:p>This is extensionally equivalent to <fr:link
href="150-007L.xml"
type="local"
addr="150-007L">the <fr:code>match</fr:code> algorithm</fr:link> from before, but it uses combinators to avoid threading <fr:code>p</fr:code> through the program manually, and it uses staging to recur over the regular expression up-front.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1798</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BF</fr:addr><fr:route>150-00BF.xml</fr:route><fr:title>Total</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:code>f : t1 -&gt; t2</fr:code> is <fr:em>total</fr:em> when for all values <fr:code>x : t1</fr:code>, we have that <fr:code>f x</fr:code> is a <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> expression.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1799</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008P</fr:addr><fr:route>150-008P.xml</fr:route><fr:title>Transparent and opaque ascription</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When we write <fr:code>MyStruct : MY_SIG</fr:code>, the structure <fr:em>transparently</fr:em> ascribes to <fr:code>MY_SIG</fr:code>: all types in the signature are visible from the outside.</fr:p><fr:p>When we write <fr:code>MyStruct :&gt; MY_SIG</fr:code>, the structure <fr:em>opaquely</fr:em> ascribes to <fr:code>MY_SIG</fr:code>: all <fr:code>type t</fr:code> specifications in the signature are hidden from the outside.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1800</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003H</fr:addr><fr:route>150-003H.xml</fr:route><fr:title>Tree method technique</fr:title></fr:frontmatter><fr:mainmatter><fr:p>
  To guess a solution to a recurrence with multiple recursive calls, the simplest thing to do is to consider the tree of costs.
  Determine the following quantities:
  
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
    

    
  <html:tr>
  <html:td><fr:strong>Symbol</fr:strong></html:td>

  <html:td><fr:strong>Description</fr:strong></html:td>
</html:tr>

    
      
  <html:tr>
  <html:td><fr:tex>L</fr:tex></html:td>

  <html:td>number of levels in the computation tree</html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>n_i</fr:tex></html:td>

  <html:td>nodes at level <fr:tex>i</fr:tex>, where <fr:tex>0</fr:tex> is the top level</html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>w_i</fr:tex></html:td>

  <html:td>non-recursive work at level <fr:tex>i</fr:tex></html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>e</fr:tex></html:td>

  <html:td>number of leaves</html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>b</fr:tex></html:td>

  <html:td>cost per leaf/base case</html:td>
</html:tr>

    
  </html:table>

  Then, the cost should be <fr:tex
display="block">e \cdot  b + \sum _{i = 0}^{L - 1} n_i \cdot  w_i.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1801</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003D</fr:addr><fr:route>150-003D.xml</fr:route><fr:title>Tree size metrics and assumptions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When analyzing the cost of a tree algorithm, we typically use one of the following approaches:</fr:p><fr:ul><fr:li>
    Assume the tree is a <fr:em>left or right spine</fr:em>, only consisting of nonempty left or right children.
    <fr:ul><fr:li>Here, we may use either depth <fr:tex>d</fr:tex> or number of nodes <fr:tex>n</fr:tex>; both are equivalent.</fr:li></fr:ul></fr:li>
  <fr:li>
    Assume the tree is <fr:em>(full and) balanced</fr:em>, where every node has two children and all paths from leaves to the root are of the same length.
    <fr:ul><fr:li>We may use depth <fr:tex>d</fr:tex>, equal to <fr:tex>\log _2(n + 1)</fr:tex>.</fr:li>
      <fr:li>Alternatively, we may use number of nodes <fr:tex>n</fr:tex>, equal to <fr:tex>2^d - 1</fr:tex>.</fr:li></fr:ul></fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1802</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0019</fr:addr><fr:route>150-0019.xml</fr:route><fr:title>Tuple pattern matching</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val (x, y) = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1803</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0004</fr:addr><fr:route>150-0004.xml</fr:route><fr:title>Type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A type is a <fr:em>prediction</fr:em> about the kind of value an expression will evaluate to. When an expression <fr:tex>e</fr:tex> has type <fr:tex>t</fr:tex>, we write <fr:tex>e : t</fr:tex>.</fr:p><fr:p>An expression is <fr:em>well-typed</fr:em> if it has a type and <fr:em>ill-typed</fr:em> otherwise.</fr:p><fr:p>Type-checking happens <fr:em>prior</fr:em> to evaluation: only well-typed programs are evaluated.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1804</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002K</fr:addr><fr:route>150-002K.xml</fr:route><fr:title>Type alias declaration</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To alias a type to a new name, we may use:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type newName = someType
</html:code></fr:pre><fr:p>This is solely for readability, reducing redundancy.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1805</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0091</fr:addr><fr:route>150-0091.xml</fr:route><fr:title>Type class</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>type class</fr:em> is a <fr:link
href="150-008H.xml"
type="local"
addr="150-008H">signature</fr:link> containing a type <fr:em>parameter</fr:em> (meant to be transparent) alongside some operations involving the type.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signtaure MY_TYPE_CLASS =
  sig
    type t  (* parameter *)
    val f1 : (* ...involving t... *)
    val f2 : (* ...involving t... *)
    (* ... *)
  end
</html:code></fr:pre><fr:p>The type should be transparent, since a client is meant to use the operations freely. Type classes do not hide type information; they simply classify types supporting some operations.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1806</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0053</fr:addr><fr:route>150-0053.xml</fr:route><fr:title>Type inference algorithm</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To infer the <fr:link
href="150-0057.xml"
type="local"
addr="150-0057">most general type</fr:link> of a function in SML:</fr:p><fr:ol><fr:li>Give each variable, including the function being defined, an arbitrary type variable.</fr:li>
  <fr:li>Add constraints based on the usage of each variable, and add constraints to make sure all clauses have the same type.</fr:li>
  <fr:li>Solve the constraints.</fr:li>
  <fr:li>Optionally, re-letter the type variables in the answer for convenience.</fr:li></fr:ol><fr:p>For simple functions, this process often occurs implicitly in one's head.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1807</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004T</fr:addr><fr:route>150-004T.xml</fr:route><fr:title>Type variable</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>type variable</fr:em> stands for an arbitrary type, denoted by an <fr:code>'</fr:code> followed by a variable name. We pronounce type variables as Greek letters:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>SML Syntax</html:th>

  <html:th>Greek Letter</html:th>

  <html:th>Pronunciation</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:code>'a</fr:code></html:td>

  <html:td><fr:tex>\alpha </fr:tex></html:td>

  <html:td>alpha</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'b</fr:code></html:td>

  <html:td><fr:tex>\beta </fr:tex></html:td>

  <html:td>beta</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'c</fr:code></html:td>

  <html:td><fr:tex>\gamma </fr:tex></html:td>

  <html:td>gamma</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'d</fr:code></html:td>

  <html:td><fr:tex>\delta </fr:tex></html:td>

  <html:td>delta</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'e</fr:code></html:td>

  <html:td><fr:tex>\epsilon </fr:tex></html:td>

  <html:td>epsilon</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1808</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005G</fr:addr><fr:route>150-005G.xml</fr:route><fr:title>Unit type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The type <fr:code>unit</fr:code> has a single value, <fr:code>() : unit</fr:code>, the empty tuple.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1809</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0033</fr:addr><fr:route>150-0033.xml</fr:route><fr:title>Unrolling technique</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To guess a solution to a recurrence, the simplest thing to do is unfold the definition repeatedly and observe the behavior.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1811</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007O</fr:addr><fr:route>150-007O.xml</fr:route><fr:title>Validator</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>t validator</fr:code> computes a <fr:code>bool</fr:code>, potentially asking "questions" to the input predicate <fr:code>p : t -&gt; bool</fr:code> in the process.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type 'a validator = ('a -&gt; bool) -&gt; bool
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1812</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0006</fr:addr><fr:route>150-0006.xml</fr:route><fr:title>Value</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:tex>v</fr:tex> is a <fr:em>final answer</fr:em> that cannot be simplified further.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1813</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0093</fr:addr><fr:route>150-0093.xml</fr:route><fr:title>Varieties of types in signatures</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Every type in a signature can be annotated to be <fr:em>abstract</fr:em>, <fr:em>parameter</fr:em>, or <fr:em>concrete</fr:em>.</fr:p><fr:ul><fr:li>If the type is unspecified via <fr:code>type t</fr:code>, it can be:
    <fr:ul><fr:li><fr:strong>abstract</fr:strong>, if it is meant to be hidden with opaque ascription; or</fr:li>
      <fr:li><fr:strong>parameter</fr:strong>, if it is meant to be known to clients with transparent ascription.</fr:li></fr:ul></fr:li>
  <fr:li>If type type is specified via <fr:code>type t = ...</fr:code>, it is <fr:strong>concrete</fr:strong>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1814</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00C8</fr:addr><fr:route>150-00C8.xml</fr:route><fr:title>Visualizing cost with the <fr:link
href="150-00BI.xml"
type="local"
addr="150-00BI"><fr:code>print</fr:code> effect</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To visualize the cost of a program, we can run <fr:code>print "$"</fr:code> every time our <fr:link
href="150-0031.xml"
type="local"
addr="150-0031">cost model</fr:link> says we used one abstract unit of cost.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1815</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001B</fr:addr><fr:route>150-001B.xml</fr:route><fr:title>Wildcard pattern</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The wildcard pattern <fr:code>_</fr:code> behaves like a variable but without binding any variables. It is useful when an input is not used.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1816</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003K</fr:addr><fr:route>150-003K.xml</fr:route><fr:title>Work and span</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:strong>Work:</fr:strong> the cost of evaluating an expression sequentially.</fr:li>
  <fr:li><fr:strong>Span:</fr:strong> the cost of evaluating an expression in parallel, assuming unlimited parallel processors.</fr:li></fr:ul><fr:p>In reality, given finite parallel processors, the cost will be between the work and the span.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1817</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009V</fr:addr><fr:route>150-009V.xml</fr:route><fr:title>Work and span of a cost graph</fr:title></fr:frontmatter><fr:mainmatter><fr:ol><fr:li>The <fr:em>work</fr:em> of a cost graph is the sum of the costs of all hexagonal nodes in the graph.</fr:li>
  <fr:li>The <fr:em>span</fr:em> of a cost graph is the sum of the costs of the hexagonal nodes on the path from the start node to the end node with the highest cost.</fr:li></fr:ol></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree>

  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1820</fr:anchor><fr:addr>150-lecture</fr:addr><fr:route>150-lecture.xml</fr:route><fr:title>Lectures</fr:title><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>288</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect01</fr:addr><fr:route>150-lect01.xml</fr:route><fr:title>Types, expressions, and evaluation</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>14</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:p>In this lecture, we begin to discuss the foundations of functional programming in <fr:link
href="standardml.xml"
type="local"
addr="standardml">Standard ML</fr:link>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>222</fr:anchor><fr:addr>150-0009</fr:addr><fr:route>150-0009.xml</fr:route><fr:title>Motivation</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>219</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000W</fr:addr><fr:route>150-000W.xml</fr:route><fr:title>Programming as a linguistic process</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:strong>Imperative programming</fr:strong> is telling a computer <fr:em>how</fr:em> to compute a result.<fr:tex
display="block">   \begin {aligned}     x &amp;\leftarrow  2; \\     y &amp;\leftarrow  x + x   \end {aligned} </fr:tex></fr:p><fr:p><fr:strong>Functional programming</fr:strong> is explaining what you want to compute. <fr:tex
display="block">2 + 2</fr:tex></fr:p><fr:p>Functional programming is applicable in all "high-level" programming languages.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>220</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000V</fr:addr><fr:route>150-000V.xml</fr:route><fr:title>Principles of functional programming</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:strong>Simplicity:</fr:strong> pure, functional code is easy to reason about, test, and parallelize.</fr:li>
  <fr:li><fr:strong>Compositionality:</fr:strong> build bigger programs out of smaller ones, taking advantage of patterns.</fr:li>
  <fr:li><fr:strong>Abstraction:</fr:strong> use types/specification to guide program development.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>221</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000X</fr:addr><fr:route>150-000X.xml</fr:route><fr:title>Parallelizing functional programs</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The "how" of imperative programming does not parallelize easily, since instructions can accidentally interact with each other. The "what" of functional programming does.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>281</fr:anchor><fr:addr>150-0002</fr:addr><fr:route>150-0002.xml</fr:route><fr:title>Values, expressions, and types</fr:title><fr:authors><fr:contributor><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:contributor></fr:authors></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>223</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0006</fr:addr><fr:route>150-0006.xml</fr:route><fr:title>Value</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:tex>v</fr:tex> is a <fr:em>final answer</fr:em> that cannot be simplified further.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>224</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000C</fr:addr><fr:route>150-000C.xml</fr:route><fr:title>Examples of values</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:code>150</fr:code>, <fr:code>"hello"</fr:code>, and <fr:code>true</fr:code> are all values.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>225</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0005</fr:addr><fr:route>150-0005.xml</fr:route><fr:title>Expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An expression <fr:tex>e</fr:tex> is a program that can be evaluated.</fr:p><fr:ul><fr:li>Every value is also an expression.</fr:li>
  <fr:li>Until the end of the course, we make the blanket assumption that all expressions <fr:tex>e</fr:tex> evaluate to some value <fr:tex>v</fr:tex>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>226</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000D</fr:addr><fr:route>150-000D.xml</fr:route><fr:title>Examples of expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:code>149 + 1</fr:code>, <fr:code>150</fr:code>, and <fr:code>"hello " ^ "world"</fr:code> are all expressions.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>240</fr:anchor><fr:taxon>Notation</fr:taxon><fr:addr>150-000E</fr:addr><fr:route>150-000E.xml</fr:route><fr:title>Evaluation notation</fr:title><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter><fr:p>We use the following notation for evaluation.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Notation</html:th>

  <html:th>Meaning</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>e \Longrightarrow ^{n} e'</fr:tex></html:td>

  <html:td><fr:tex>e</fr:tex> evaluates to <fr:tex>e'</fr:tex> in <fr:tex>n</fr:tex> steps</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>e \Longrightarrow  e'</fr:tex></html:td>

  <html:td><fr:tex>e</fr:tex> evaluates to <fr:tex>e'</fr:tex> in an unspecified number of steps</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>e \hookrightarrow  v</fr:tex></html:td>

  <html:td><fr:tex>e</fr:tex> evaluates to the value <fr:tex>v</fr:tex></html:td>
</html:tr>

  
</html:table>
<fr:p>Note that <fr:tex>e \hookrightarrow  v</fr:tex> iff <fr:tex>e \Longrightarrow  v</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>242</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0008</fr:addr><fr:route>150-0008.xml</fr:route><fr:title>Evaluation of numeric expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block">   \begin {aligned}     \texttt {(3 + 4) * 2}       &amp;\Longrightarrow ^{1} \texttt {7 * 2} \\       &amp;\Longrightarrow ^{1} \texttt {14}   \end {aligned} </fr:tex><fr:tex
display="block">   \begin {aligned}     \texttt {(3 + 4) * (2 + 1)}       &amp;\Longrightarrow ^{3} \texttt {21}   \end {aligned} </fr:tex><fr:tex
display="block">   \begin {aligned}     \texttt {(3 + 4) * (2 + 1)}       &amp;\hookrightarrow  \texttt {21}   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>243</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000A</fr:addr><fr:route>150-000A.xml</fr:route><fr:title>Evaluation of string expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block">   \begin {aligned}     \texttt {"the " \textasciicircum {} "walrus"}       &amp;\Longrightarrow  \texttt {"the walrus"}   \end {aligned} </fr:tex><fr:tex
display="block">   \begin {aligned}     \texttt {("the " \textasciicircum {} "walrus") \textasciicircum {} " leaps"}       &amp;\Longrightarrow  \texttt {"the walrus" \textasciicircum {} " leaps"} \\       &amp;\Longrightarrow  \texttt {"the walrus leaps"}   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>244</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000B</fr:addr><fr:route>150-000B.xml</fr:route><fr:title>Ill-typed expressions do not evaluate</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:tex>\texttt {"the walrus" + 1}</fr:tex> does not have a type, so it cannot be evaluated.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>245</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0004</fr:addr><fr:route>150-0004.xml</fr:route><fr:title>Type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A type is a <fr:em>prediction</fr:em> about the kind of value an expression will evaluate to. When an expression <fr:tex>e</fr:tex> has type <fr:tex>t</fr:tex>, we write <fr:tex>e : t</fr:tex>.</fr:p><fr:p>An expression is <fr:em>well-typed</fr:em> if it has a type and <fr:em>ill-typed</fr:em> otherwise.</fr:p><fr:p>Type-checking happens <fr:em>prior</fr:em> to evaluation: only well-typed programs are evaluated.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>265</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0007</fr:addr><fr:route>150-0007.xml</fr:route><fr:title>Base types</fr:title></fr:frontmatter><fr:mainmatter>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>int</fr:code></html:td>

  <html:td><fr:code>0</fr:code>, <fr:code>1</fr:code>, <fr:code>150</fr:code>, <fr:code>~12</fr:code>, ...</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>real</fr:code></html:td>

  <html:td><fr:code>1.5</fr:code>, <fr:code>3.14</fr:code>, <fr:code>0.0001</fr:code>, ...</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>bool</fr:code></html:td>

  <html:td><fr:code>false</fr:code>, <fr:code>true</fr:code></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>char</fr:code></html:td>

  <html:td><fr:code>#"a"</fr:code>, <fr:code>#"b"</fr:code>, <fr:code>#"7"</fr:code>, ...</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>string</fr:code></html:td>

  <html:td><fr:code>""</fr:code>, <fr:code>"hello world"</fr:code>, ...</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>266</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000F</fr:addr><fr:route>150-000F.xml</fr:route><fr:title>Primitive expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li>If <fr:tex>e_1 : \texttt {int}</fr:tex> and <fr:tex>e_2 : \texttt {int}</fr:tex>, then <fr:tex>e_1 \texttt {+} e_2 : \texttt {int}</fr:tex>. Same for <fr:tex>e_1 \texttt {-} e_2</fr:tex>, <fr:tex>e_1 \texttt {*} e_2</fr:tex>, <fr:tex>e_1 \texttt {div} e_2</fr:tex>, <fr:tex>e_1 \texttt {mod} e_2</fr:tex>, ...</fr:li>
  <fr:li>If <fr:tex>e_1 : \texttt {string}</fr:tex> and <fr:tex>e_2 : \texttt {string}</fr:tex>, then <fr:tex>e_1 \texttt {\textasciicircum {}} e_2 : \texttt {string}</fr:tex>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>268</fr:anchor><fr:taxon>Warning</fr:taxon><fr:addr>150-000I</fr:addr><fr:route>150-000I.xml</fr:route><fr:title>Division by zero</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:code>2 div 0 : int</fr:code> is well-typed, but it does not evaluate to a value; instead, it raises an exception.</fr:p><fr:pre><![CDATA[λ> 2 div 0;

uncaught exception Div [divide by zero]
  raised at: stdIn:1.4-1.7]]></fr:pre><fr:p>Here, <fr:code>0</fr:code> violates an assumption that the second argument to <fr:code>div</fr:code> is nonzero.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* div : int * int -&gt; int
 * REQUIRES: y is nonzero
 * ENSURES: `x div y` computes the integer division of `x` by `y`
 *)
</html:code></fr:pre><fr:p>We implicitly assume that all well-typed expressions evaluate to values; in other words, we manually verify that we never use <fr:code>div</fr:code> with the invalid denominator <fr:code>0</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>269</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000Q</fr:addr><fr:route>150-000Q.xml</fr:route><fr:title>Extensional equivalence at base types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Two expressions <fr:tex>e</fr:tex> and <fr:tex>e'</fr:tex> (that evaluate to values) are <fr:em>extensionally equivalent</fr:em>, written <fr:tex>e \cong  e'</fr:tex>, when they evaluate to the same value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>270</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000R</fr:addr><fr:route>150-000R.xml</fr:route><fr:title>Extensional equivalence of <fr:code>int</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:tex>\texttt {21 + 21} \cong  \texttt {42} \cong  \texttt {6 * 7}</fr:tex>, but <fr:tex>\texttt {21 + 21} \ncong  \texttt {7 * 7}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>278</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000G</fr:addr><fr:route>150-000G.xml</fr:route><fr:title>Product types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:em>product type</fr:em> <fr:code>t1 * t2</fr:code> represents pairs whose first component is a value of type <fr:code>t1</fr:code> and whose second component is a value of type <fr:code>t2</fr:code>.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>t1 * t2</fr:code></html:td>

  <html:td><fr:code>(v1, v2)</fr:code></html:td>
</html:tr>

  
</html:table>
<fr:p>If <fr:tex>e_1 : t_1</fr:tex> and <fr:tex>e_2 : t_2</fr:tex>, then <fr:tex>(e_1, e_2) : t_1 \texttt {*} t_2</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>279</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000H</fr:addr><fr:route>150-000H.xml</fr:route><fr:title>Example pairs</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:code>(3 + 4, true) : int * bool</fr:code></fr:li>
  <fr:li><fr:code>(1.0, ~6.28) : real * real</fr:code></fr:li>
  <fr:li><fr:code>(1, 50, false, "hi") : int * int * bool * string</fr:code></fr:li>
  <fr:li><fr:code>(1, (50, false), "hi") : int * (int * bool) * string</fr:code></fr:li></fr:ul><fr:p>Notice in the last example that parentheses matter!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>280</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000S</fr:addr><fr:route>150-000S.xml</fr:route><fr:title>Extensional equivalence at product types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>It is the case that <fr:tex
display="block">(e_1, e_2) \cong  (e_1', e_2')</fr:tex> when <fr:tex>e_1 \cong  e_1'</fr:tex> and <fr:tex>e_2 \cong  e_2'</fr:tex>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>287</fr:anchor><fr:addr>150-0003</fr:addr><fr:route>150-0003.xml</fr:route><fr:title>Declarations and variables</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>284</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000M</fr:addr><fr:route>150-000M.xml</fr:route><fr:title><fr:code>val</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>val</fr:code> declaration gives a variable name to the result of an expression evaluation.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val x : t = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>286</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000N</fr:addr><fr:route>150-000N.xml</fr:route><fr:title>Shadowing</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val tau : real = 6.28
val radius : real = 5.0
val area : real = tau * radius
val radius : real = 10.0
</html:code></fr:pre><fr:p>The value bound to <fr:code>area</fr:code> is <fr:code>31.4</fr:code> at the end (not, e.g., <fr:code>62.8</fr:code>). The new definition <fr:code>radius</fr:code> does not affect the previous definition, which <fr:code>area</fr:code> still refers back to.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>354</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect02</fr:addr><fr:route>150-lect02.xml</fr:route><fr:title>Functions and patterns</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>16</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>299</fr:anchor><fr:addr>150-0012</fr:addr><fr:route>150-0012.xml</fr:route><fr:title>Private declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>296</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000O</fr:addr><fr:route>150-000O.xml</fr:route><fr:title><fr:code>let</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val a : int =
  let
    val b : int = 15
    val c : int = b + 150
  in
    b * c
  end + 1

(* ERROR: b not in scope *)
val d : int = a + b
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>298</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000P</fr:addr><fr:route>150-000P.xml</fr:route><fr:title><fr:code>local</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">local
  val b : int = 15
  val c : int = b + 150
in
  val a : int = b * c + 1
end

(* ERROR: b not in scope *)
val d : int = a + b
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>325</fr:anchor><fr:addr>150-0010</fr:addr><fr:route>150-0010.xml</fr:route><fr:title>Functions</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>307</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000L</fr:addr><fr:route>150-000L.xml</fr:route><fr:title>Function types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In math, we talk about functions <fr:tex
display="block">f : X \to  Y</fr:tex> between sets <fr:tex>X</fr:tex> and <fr:tex>Y</fr:tex>. In SML, we do the same, but where <fr:tex>X</fr:tex> and <fr:tex>Y</fr:tex> are types.</fr:p><fr:p>If <fr:code>t1</fr:code> and <fr:code>t2</fr:code> are types, then <fr:code>t1 -&gt; t2</fr:code> is the type of functions that take a value of type <fr:code>t1</fr:code> as input and produce a value of type <fr:code>t2</fr:code> as an output.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>t1 -&gt; t2</fr:code></html:td>

  <html:td><fr:code>fn (x : t1) =&gt; e</fr:code></html:td>
</html:tr>

  
</html:table>
<fr:p>If assuming that <fr:code>x : t1</fr:code> makes <fr:code>e : t2</fr:code>, then <fr:code>(fn (x : t1) =&gt; e) : t1 -&gt; t2</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>309</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000Y</fr:addr><fr:route>150-000Y.xml</fr:route><fr:title>Doubling function</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val double : int -&gt; int =
  fn (x : int) =&gt; x + x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>310</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001L</fr:addr><fr:route>150-001L.xml</fr:route><fr:title>Functions are values</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Functions <fr:em>are</fr:em> values: they do not evaluate further.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>311</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001M</fr:addr><fr:route>150-001M.xml</fr:route><fr:title>Function value example</fr:title></fr:frontmatter><fr:mainmatter><fr:p>All of the following are values of type <fr:code>int -&gt; int</fr:code>:</fr:p><fr:ol><fr:li><fr:code>fn (x : int) =&gt; x</fr:code></fr:li>
  <fr:li><fr:code>fn (x : int) =&gt; x + 2</fr:code></fr:li>
  <fr:li><fr:code>fn (x : int) =&gt; 2 + 2</fr:code></fr:li>
  <fr:li><fr:code>fn (x : int) =&gt; 4</fr:code></fr:li></fr:ol><fr:p>In other words, none of them evaluate to any of the others.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>312</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000Z</fr:addr><fr:route>150-000Z.xml</fr:route><fr:title>Function application</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Function application is written using a space. If <fr:code>e : t1 -&gt; t2</fr:code> and <fr:code>e1 : t1</fr:code>, then <fr:code>e e1 : t2</fr:code>.</fr:p><fr:p>When evaluating <fr:code>e e1</fr:code>, SML does the following:</fr:p><fr:ol><fr:li><fr:code>e</fr:code> is evaluated to <fr:code>fn (x : t1) =&gt; e'</fr:code>.</fr:li>
  <fr:li><fr:code>e1</fr:code> is evaluated to <fr:code>v1</fr:code> (of type <fr:code>t1</fr:code>).</fr:li>
  <fr:li><fr:code>e'</fr:code> is evaluated, where <fr:code>v1</fr:code> is now bound to <fr:code>x</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>313</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0014</fr:addr><fr:route>150-0014.xml</fr:route><fr:title>Applying the double function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the <fr:link
href="150-000Y.xml"
type="local"
addr="150-000Y">doubling function</fr:link>.</fr:p><fr:tex
display="block">   \begin {aligned}     \texttt {double (70 + 5)}       &amp;\Longrightarrow  \texttt {(fn (x : int) =&gt; x + x) (70 + 5)} \\       &amp;\Longrightarrow  \texttt {(fn (x : int) =&gt; x + x) 75} \\       &amp;\Longrightarrow  \texttt {75 + 75} \\       &amp;\Longrightarrow  \texttt {150}   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>314</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000T</fr:addr><fr:route>150-000T.xml</fr:route><fr:title>Extensional equivalence at function types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Suppose <fr:code>f</fr:code> and <fr:code>f'</fr:code> are both of type <fr:code>t1 -&gt; t2</fr:code>. Then, <fr:tex>\texttt {f} \cong  \texttt {f'}</fr:tex> when for all values <fr:code>x</fr:code> and <fr:code>x'</fr:code> of type <fr:code>t1</fr:code>, <fr:tex>\texttt {x} \cong  \texttt {x'}</fr:tex> implies <fr:tex>\texttt {f x} \cong  \texttt {f' x'}</fr:tex>.</fr:p><fr:p>When <fr:code>t1</fr:code> is a <fr:link
href="150-000Q.xml"
type="local"
addr="150-000Q">base type</fr:link>, this is equivalent to: for all values <fr:code>x : t1</fr:code>, <fr:tex>\texttt {f x} \cong  \texttt {f' x}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>316</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000U</fr:addr><fr:route>150-000U.xml</fr:route><fr:title>Extensional equivalence of doubling functions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall <fr:link
href="150-000K.xml"
type="local"
addr="150-000K">the <fr:code>double</fr:code> function</fr:link>, and consider the following alternate implementation:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val double' : int -&gt; int =
  fn (x : int) =&gt; 2 * x
</html:code></fr:pre><fr:p>It is the case that <fr:tex>\texttt {double} \cong  \texttt {double'}</fr:tex>, since for all <fr:code>x : int</fr:code>, we have <fr:tex>\texttt {x + x} \cong  \texttt {2 * x}</fr:tex> by arithmetic reasoning.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>318</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0015</fr:addr><fr:route>150-0015.xml</fr:route><fr:title><fr:code>fun</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (x : t1) : t2 = e
</html:code></fr:pre><fr:p>The value assigned to <fr:code>f</fr:code> is <fr:code>fn (x : t1) =&gt; e</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>320</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0013</fr:addr><fr:route>150-0013.xml</fr:route><fr:title>Function specifications</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* f : t1 -&gt; t2
 * REQUIRES: ...some assumptions about x...
 * ENSURES: ...some guarantees about (f x)...
 *)
fun f (x : t1) : t2 = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>322</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000K</fr:addr><fr:route>150-000K.xml</fr:route><fr:title>Doubling function using <fr:code>fun</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* double : int -&gt; int
 * REQUIRES: true
 * ENSURES: `double x` evaluates to double `x`
 *)
fun double (x : int) : int = x + x

val () = Test.int ("double 75 test", 150, double 75)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>324</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0016</fr:addr><fr:route>150-0016.xml</fr:route><fr:title>Static variable scope in functions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the concept of <fr:link
href="150-000N.xml"
type="local"
addr="150-000N">shadowing</fr:link>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val pi : real = 3.14

fun area (r : real) : real = pi * r * r

val pi : real = 3.14159
</html:code></fr:pre><fr:p>In the function <fr:code>area</fr:code>, the variable <fr:code>pi</fr:code> is always <fr:code>3.14</fr:code>, never <fr:code>3.14159</fr:code>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>353</fr:anchor><fr:addr>150-0011</fr:addr><fr:route>150-0011.xml</fr:route><fr:title>Patterns</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>326</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001B</fr:addr><fr:route>150-001B.xml</fr:route><fr:title>Wildcard pattern</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The wildcard pattern <fr:code>_</fr:code> behaves like a variable but without binding any variables. It is useful when an input is not used.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>329</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001C</fr:addr><fr:route>150-001C.xml</fr:route><fr:title>Wildcard pattern</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun onefifty (_ : int) : int = 150
</html:code></fr:pre><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">λ&gt; fun onefifty (x : int) : int = 150;
stdIn:2.5-2.35 Warning: variable x is defined but not used
val onefifty = fn : int -&gt; int
λ&gt; fun onefifty (_ : int) : int = 150;
val onefifty = fn : int -&gt; int
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>331</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0019</fr:addr><fr:route>150-0019.xml</fr:route><fr:title>Tuple pattern matching</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val (x, y) = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>333</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001A</fr:addr><fr:route>150-001A.xml</fr:route><fr:title>Tuple pattern matching</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val name_and_age : string * int = ("Polly", 5)

val (name, age) : string * int = name_and_age
(* OR: *)
val (name : string, age : int) = name_and_age
(* OR: *)
val (name, age) = name_and_age

val age' : int =
  let
    val (_, age) = name_and_age
  in
    age + 1
  end

val ((a : string, b : int), (c : string, d : int)) =
  (name_and_age, name_and_age)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>335</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001E</fr:addr><fr:route>150-001E.xml</fr:route><fr:title>Pattern inputs in <fr:code>fun</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f &lt;pattern&gt; : t2 = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>337</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001F</fr:addr><fr:route>150-001F.xml</fr:route><fr:title>Function with a tuple input</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (x : int, y : int) : int = 2 * x + y * y
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>339</fr:anchor><fr:taxon>Warning</fr:taxon><fr:addr>150-001N</fr:addr><fr:route>150-001N.xml</fr:route><fr:title>Linear variable usage</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Variables must occur exactly once in a pattern. The following is invalid:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (x : int, x : int) : int = x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>340</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001D</fr:addr><fr:route>150-001D.xml</fr:route><fr:title>Constant pattern</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Constants, such as <fr:code>int</fr:code>, <fr:code>string</fr:code>, and <fr:code>bool</fr:code> values, are patterns. Make sure to match them all!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>342</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001H</fr:addr><fr:route>150-001H.xml</fr:route><fr:title>Pattern matching on booleans</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun not (false : bool) : bool = true
  | not (true  : bool) : bool = false

(* equivalent, but without type annotations *)
fun not false = true
  | not true  = false
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>344</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001G</fr:addr><fr:route>150-001G.xml</fr:route><fr:title>Pattern matching on multiple integers</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun usesSML (150 : int) : bool = true
  | usesSML (210 : int) : bool = true
  | usesSML (312 : int) : bool = true
  | usesSML (_   : int) : bool = false

(* equivalent, but without type annotations *)
fun usesSML 150 = true
  | usesSML 210 = true
  | usesSML 312 = true
  | usesSML _   = false
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>346</fr:anchor><fr:taxon>Warning</fr:taxon><fr:addr>150-001I</fr:addr><fr:route>150-001I.xml</fr:route><fr:title>Redundant and missing branches</fr:title></fr:frontmatter><fr:mainmatter><fr:p>SML will give a warning/error if branches are missing/redundant.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (0 : int) : int = 150
(* WARNING: missing branches *)

fun f (x : int) : int = 150
  | f (y : int) : int = 122
(* ERROR: redundant branches *)

fun f (x : int) : int = 150
  | f (_ : int) : int = 122
(* ERROR: redundant branches *)

fun f (0 : int) : int = 150
  | f (0 : int) : int = 122
(* ERROR: missing and redundant branches *)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>348</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001J</fr:addr><fr:route>150-001J.xml</fr:route><fr:title><fr:code>case</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">case e of
  pat1 =&gt; e1
| pat2 =&gt; e2
  ...
| patn =&gt; en
</html:code></fr:pre><fr:p>To evaluate a <fr:code>case</fr:code> expression:</fr:p><fr:ol><fr:li>Evaluate <fr:code>e</fr:code> to a value.</fr:li>
  <fr:li>Then, evaluate the first branch matching the value.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>350</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001P</fr:addr><fr:route>150-001P.xml</fr:route><fr:title><fr:code>if</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>SML has shorthand notation ("syntactic sugar") for casing on a boolean.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">case e of
  true  =&gt; e1
| false =&gt; e0

if e then e1 else e0
</html:code></fr:pre><fr:p>In other languages:</fr:p><fr:ul><fr:li>Python: <fr:code>e1 if e else e0</fr:code></fr:li>
  <fr:li>C: <fr:code>e ? e1 : e0</fr:code></fr:li></fr:ul><fr:p>Not to be confused with <fr:code>if</fr:code> "statements"!</fr:p><fr:p>The following further syntactic sugars are available:</fr:p><fr:ul><fr:li><fr:code>e1 andalso e2</fr:code> is sugar for <fr:code>if e1 then e2 else false</fr:code></fr:li>
  <fr:li><fr:code>e1 orelse e2</fr:code> is sugar for <fr:code>if e1 then true else e2</fr:code></fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>352</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001K</fr:addr><fr:route>150-001K.xml</fr:route><fr:title>Casing on an expression</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* mod : int * int -&gt; int
 * REQUIRES: y &gt; 0
 * ENSURES: 0 &lt;= x mod y &lt; y
 *)

(* isEven : int -&gt; bool
 * REQUIRES: n &gt;= 0
 * ENSURES:
 *   isEven n ==&gt; true   if n is even, and
 *   isEven n ==&gt; false  if not
 *)
fun isEven (n : int) : bool =
  case n mod 2 of
    0 =&gt; true
  | 1 =&gt; false
  | _ =&gt; raise Fail "impossible"
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>388</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect03</fr:addr><fr:route>150-lect03.xml</fr:route><fr:title>Recursion and induction</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>21</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>370</fr:anchor><fr:addr>150-0018</fr:addr><fr:route>150-0018.xml</fr:route><fr:title>Recursion</fr:title></fr:frontmatter><fr:mainmatter>
  
  <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>362</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0017</fr:addr><fr:route>150-0017.xml</fr:route><fr:title>Factorial function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The factorial of <fr:tex>n</fr:tex>, written <fr:tex>n!</fr:tex>, is <fr:tex>1 \times  2 \times  \cdots  \times  n</fr:tex>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* fact : int -&gt; int
 * REQUIRES: n &gt;= 0
 * ENSURES: (fact n) evaluates to n!
 *)
fun fact (0 : int) : int = 1
  | fact (n : int) : int = n * fact (n - 1)
</html:code></fr:pre></fr:mainmatter></fr:tree>
  <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>365</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001O</fr:addr><fr:route>150-001O.xml</fr:route><fr:title>Fibonacci function</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* fib : int -&gt; int
 * REQUIRES: n &gt;= 0
 * ENSURES: fib n ==&gt; the nth Fibonacci number
 *)
fun fib 0 = 0
  | fib 1 = 1
  | fib n = fib (n - 1) + fib (n - 2)
</html:code></fr:pre><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">local
  (* helper : int -&gt; int * int
   * REQUIRES: n &gt;= 0
   * ENSURES: helper n ==&gt; (the nth Fibonacci number, the n+1'th Fibonacci number)
   *)
  fun helper 0 = (0, 1)
    | helper n =
        let
          val (a, b) = helper (n - 1)
        in
          (b, a + b)
        end
in
  (* fib : int -&gt; int
   * REQUIRES: n &gt;= 0
   * ENSURES: fib n ==&gt; the nth Fibonacci number
   *)
  fun fib' n =
    let
      val (a, _) = helper n
    in
      a
    end
end
</html:code></fr:pre></fr:mainmatter></fr:tree>
  <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>367</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000J</fr:addr><fr:route>150-000J.xml</fr:route><fr:title>Passing a function as an argument</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun repeat (f : string -&gt; string, x : string, 0 : int) : string = x
  | repeat (f, x, n) = f (repeat (f, x, n - 1))
</html:code></fr:pre></fr:mainmatter></fr:tree>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>369</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001S</fr:addr><fr:route>150-001S.xml</fr:route><fr:title>Even tester</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* isEven : int -&gt; bool
 * REQUIRES: n &gt;= 0
 * ENSURES: isEven n ==&gt; true if n is even,
            isEven n ==&gt; false otherwise
 *)
fun isEven (0 : int) : bool = true
  | isEven n = not (isEven (n - 1))
</html:code></fr:pre><fr:p>Here, we use <fr:link
href="150-001H.xml"
type="local"
addr="150-001H"><fr:code>not</fr:code></fr:link> as a helper function.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>383</fr:anchor><fr:addr>150-001Q</fr:addr><fr:route>150-001Q.xml</fr:route><fr:title>Power function</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>372</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001R</fr:addr><fr:route>150-001R.xml</fr:route><fr:title>Simple power implementation</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* pow : int * int -&gt; int
 * REQUIRES: k &gt;= 0
 * ENSURES: pow (n , k) evaluates to n^k
 *)
fun pow (_ : int, 0 : int) : int = 1
  | pow (n      , k      )       = n * pow (n, k - 1)
</html:code></fr:pre><fr:p>The application <fr:code>pow (n, k)</fr:code> evaluates <fr:code>k</fr:code> multiplications.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>373</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001T</fr:addr><fr:route>150-001T.xml</fr:route><fr:title>Simple induction on natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all natural numbers <fr:tex>n \in  \{0, 1, 2, 3, \cdots \}</fr:tex>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>Inductive Case: Prove that if the property holds on <fr:tex>n</fr:tex>, then the property holds on <fr:tex>n + 1</fr:tex>.</fr:li></fr:ol><fr:p>Then:</fr:p><fr:ul><fr:li>The property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>1 = 0 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>2 = 1 + 1</fr:tex>, since the property holds on <fr:tex>1</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>3 = 2 + 1</fr:tex>, since the property holds on <fr:tex>2</fr:tex>.</fr:li>
  <fr:li>...and so on.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>375</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-001U</fr:addr><fr:route>150-001U.xml</fr:route><fr:title>Correctness of <fr:link
href="150-001R.xml"
type="local"
addr="150-001R"><fr:code>pow</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all values <fr:code>n : int</fr:code> and <fr:code>k : int</fr:code> such that <fr:code>k &gt;= 0</fr:code>, we have <fr:tex>\texttt {pow (n, k)} \Longrightarrow  n^k</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>374</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#211</fr:addr><fr:route>unstable-211.xml</fr:route><fr:parent>150-001U</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>By induction on <fr:code>k</fr:code>.</fr:p>
  <fr:ol><fr:li>Case <fr:code>0</fr:code>: By the first clause of <fr:code>pow</fr:code>, we have <fr:tex>\texttt {pow (n, 0)} \Longrightarrow  \texttt {1}</fr:tex>, and <fr:tex>n^0 = 1</fr:tex>.</fr:li>
    <fr:li>Case <fr:code>k + 1</fr:code>:
      <fr:p><fr:strong>IH:</fr:strong> <fr:tex>\texttt {pow (n, k)} \Longrightarrow  n^k</fr:tex></fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {pow (n, k+1)} \Longrightarrow  n^{k + 1}</fr:tex></fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {pow (n, k + 1)} \\           &amp;\Longrightarrow  \texttt {n * pow (n, k)} &amp;&amp;\text {(\texttt {pow} clause 2)} \\           &amp;\Longrightarrow  \texttt {n * }n^{k} &amp;&amp;\text {(inductive hypothesis)} \\           &amp;\Longrightarrow  n^{k + 1} &amp;&amp;\text {(math)}         \end {aligned}       </fr:tex></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>376</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-001V</fr:addr><fr:route>150-001V.xml</fr:route><fr:title>Proof structure mirrors program structure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The structure of a <fr:em>proof</fr:em> should mirror the structure of the <fr:em>program</fr:em>.</fr:p><fr:ol><fr:li>If the program uses recursion on a natural number <fr:code>n</fr:code>, the proof should use induction on <fr:code>n</fr:code>.</fr:li>
  <fr:li>If the program uses recursion with cases <fr:code>0</fr:code>, <fr:code>1</fr:code>, and <fr:code>n</fr:code>, the proof should use induction with base cases for <fr:code>0</fr:code> and <fr:code>1</fr:code> and an inductive case for <fr:code>n</fr:code>.</fr:li>
  <fr:li>If the program cases on <fr:code>b : bool</fr:code>, the proof should case in the same way.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>379</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001W</fr:addr><fr:route>150-001W.xml</fr:route><fr:title>Fast exponentiation</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fpow (_ : int, 0 : int) : int = 1
  | fpow (n, k) =
      case isEven k of
        true  =&gt;
          let
            val halfAns = fpow (n, k div 2)
          in
            halfAns * halfAns
          end
      | false =&gt; n * fpow (n, k - 1)
</html:code></fr:pre><fr:p>The application <fr:code>fpow (n, k)</fr:code> evaluates between <fr:code>log2 k</fr:code> and <fr:code>2 * log2 k</fr:code> multiplications, where we say <fr:code>log2 0 = 0</fr:code>.</fr:p><fr:p>The following alternative also works for the <fr:code>true</fr:code> case:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">        true  =&gt; fpow (n * n, k div 2)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>380</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001X</fr:addr><fr:route>150-001X.xml</fr:route><fr:title>Strong induction on natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all natural numbers <fr:tex>n \in  \{0, 1, 2, 3, \cdots \}</fr:tex>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>Inductive Case: Prove that if the property holds on all <fr:tex>m \le  n</fr:tex>, then the property holds on <fr:tex>n + 1</fr:tex>.</fr:li></fr:ol><fr:p>Then:</fr:p><fr:ul><fr:li>The property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>1 = 0 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>2 = 1 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex> and <fr:tex>1</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>3 = 2 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>, <fr:tex>1</fr:tex>, and <fr:tex>2</fr:tex>.</fr:li>
  <fr:li>...and so on.</fr:li></fr:ul><fr:p>Contrast this technique with <fr:link
href="150-001T.xml"
type="local"
addr="150-001T">simple induction</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>382</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-001Y</fr:addr><fr:route>150-001Y.xml</fr:route><fr:title>Correctness of <fr:link
href="150-001W.xml"
type="local"
addr="150-001W"><fr:code>fpow</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all values <fr:code>n : int</fr:code> and <fr:code>k : int</fr:code> such that <fr:code>k &gt;= 0</fr:code>, we have <fr:tex>\texttt {fpow (n, k)} \Longrightarrow  n^k</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>381</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#210</fr:addr><fr:route>unstable-210.xml</fr:route><fr:parent>150-001Y</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>By strong induction on <fr:code>k</fr:code>.</fr:p>
  <fr:ol><fr:li>Case <fr:code>0</fr:code>: By the first clause of <fr:code>fpow</fr:code>, we have <fr:tex>\texttt {fpow (n, 0)} \Longrightarrow  \texttt {1}</fr:tex>, and <fr:tex>n^0 = 1</fr:tex>.</fr:li>
    <fr:li>Case <fr:code>k + 1</fr:code>:
      <fr:p><fr:strong>IH:</fr:strong> for all <fr:tex>k' \le  k</fr:tex>, we have <fr:tex>\texttt {fpow (n, k')} \Longrightarrow  n^{k'}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {fpow (n, k + 1)} \Longrightarrow  n^{k + 1}</fr:tex>.</fr:p>
      The code cases on whether <fr:code>k + 1</fr:code> is even, so we will, too.
      <fr:ol><fr:li>Case <fr:code>k + 1</fr:code> is even:
          By the IH, since <fr:code>(k + 1) div 2 &lt;= k</fr:code>, we have <fr:tex>\texttt {fpow (n, (k + 1) div 2)} \Longrightarrow  n^\texttt {(k + 1) div 2}</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {fpow (n, k + 1)} \\               &amp;\Longrightarrow  \texttt {let ... in ... end} &amp;&amp;\text {(\texttt {true} branch of clause 2)} \\               &amp;\Longrightarrow  n^\texttt {(k + 1) div 2}\texttt { * }n^\texttt {(k + 1) div 2} &amp;&amp;\text {(IH)} \\               &amp;\Longrightarrow  n^\texttt {k + 1} &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex></fr:li>
        <fr:li>Case <fr:code>k + 1</fr:code> is odd:
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {fpow (n, k + 1)} \\               &amp;\Longrightarrow  \texttt {n * fpow (n, k)} &amp;&amp;\text {(\texttt {false} branch of clause 2)} \\               &amp;\Longrightarrow  \texttt {n * }n^k &amp;&amp;\text {(IH)} \\               &amp;\Longrightarrow  n^{k + 1} &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex></fr:li></fr:ol></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>387</fr:anchor><fr:addr>150-001Z</fr:addr><fr:route>150-001Z.xml</fr:route><fr:title>Lists</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>384</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0022</fr:addr><fr:route>150-0022.xml</fr:route><fr:title>Lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, the type <fr:code>t list</fr:code> represents ordered lists of values of type <fr:code>t</fr:code>.</fr:p><fr:p>The values of type <fr:code>t list</fr:code> are:</fr:p><fr:ol><fr:li><fr:code>nil</fr:code>, the empty list</fr:li>
  <fr:li><fr:code>v1 :: v2</fr:code> (pronounced "cons"), where <fr:code>v1 : t</fr:code> is an element and <fr:code>v2 : t list</fr:code> is the remainder of the list</fr:li></fr:ol><fr:p>Syntactic sugar <fr:code>[v1, v2, ..., vn]</fr:code> is equivalent to <fr:code>v1 :: v2 :: ... :: vn</fr:code>, i.e. <fr:code>v1 :: (v2 :: (... :: (vn :: nil)))</fr:code>.</fr:p><fr:p>There are corresponding expressions that evaluate left-to-right.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>386</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0023</fr:addr><fr:route>150-0023.xml</fr:route><fr:title>List length function</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun length (nil : string list) : int = 0
  | length (_ :: xs) = 1 + length xs
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>417</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect04</fr:addr><fr:route>150-lect04.xml</fr:route><fr:title>Lists and structural induction</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>23</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>405</fr:anchor><fr:addr>150-0025</fr:addr><fr:route>150-0025.xml</fr:route><fr:title>List append</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>395</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0022</fr:addr><fr:route>150-0022.xml</fr:route><fr:title>Lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, the type <fr:code>t list</fr:code> represents ordered lists of values of type <fr:code>t</fr:code>.</fr:p><fr:p>The values of type <fr:code>t list</fr:code> are:</fr:p><fr:ol><fr:li><fr:code>nil</fr:code>, the empty list</fr:li>
  <fr:li><fr:code>v1 :: v2</fr:code> (pronounced "cons"), where <fr:code>v1 : t</fr:code> is an element and <fr:code>v2 : t list</fr:code> is the remainder of the list</fr:li></fr:ol><fr:p>Syntactic sugar <fr:code>[v1, v2, ..., vn]</fr:code> is equivalent to <fr:code>v1 :: v2 :: ... :: vn</fr:code>, i.e. <fr:code>v1 :: (v2 :: (... :: (vn :: nil)))</fr:code>.</fr:p><fr:p>There are corresponding expressions that evaluate left-to-right.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>397</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0020</fr:addr><fr:route>150-0020.xml</fr:route><fr:title>List append</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infixr 5 @

(* op @ : int list * int list -&gt; int list
 * REQUIRES: true
 * ENSURES: l1 @ l2 ==&gt; l, where l is the elements of l1 followed by the elements of l2 in order
 *)
fun (l1 : int list) @ (l2 : int list) : int list =
  case l1 of
    nil     =&gt; l2
  | x :: xs =&gt; x :: (xs @ l2)
</html:code></fr:pre><fr:p>These declarations (both the infix and function declarations) are present in the prelude and are always available.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>399</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-0021</fr:addr><fr:route>150-0021.xml</fr:route><fr:title>Appending <fr:code>nil</fr:code> on the left</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all values <fr:code>l : int list</fr:code>, <fr:tex
display="block">\texttt {nil @ l} \hookrightarrow  l.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>398</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#209</fr:addr><fr:route>unstable-209.xml</fr:route><fr:parent>150-0021</fr:parent></fr:frontmatter><fr:mainmatter>
  Immediate, by Clause 1 of <fr:link
href="150-0020.xml"
type="local"
addr="150-0020">the definition of <fr:code>@</fr:code></fr:link>.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>400</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0027</fr:addr><fr:route>150-0027.xml</fr:route><fr:title>Structural induction on <fr:code>int list</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all list values <fr:code>l : int list</fr:code>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:code>nil</fr:code>.</fr:li>
  <fr:li>Inductive Case: Prove that for all <fr:code>x : int</fr:code> and <fr:code>xs : int list</fr:code>, if the property holds on <fr:code>xs</fr:code>, then the property holds on <fr:code>x :: xs</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>402</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-0024</fr:addr><fr:route>150-0024.xml</fr:route><fr:title>Appending <fr:code>nil</fr:code> on the right</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all values <fr:code>l : int list</fr:code>, <fr:tex
display="block">\texttt {l @ nil} \hookrightarrow  \texttt {l}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>401</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#208</fr:addr><fr:route>unstable-208.xml</fr:route><fr:parent>150-0024</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>l : int list</fr:code> be an arbitrary value.
  By structural induction on <fr:code>l</fr:code>, following <fr:link
href="150-0020.xml"
type="local"
addr="150-0020">the definition of <fr:code>@</fr:code></fr:link>.
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:p>By the first clause of <fr:code>@</fr:code>, <fr:tex>\texttt {nil @ nil} \Longrightarrow  \texttt {nil}</fr:tex>.</fr:p></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:

      <fr:p><fr:strong>IH:</fr:strong> <fr:tex>\texttt {xs @ nil} \hookrightarrow  \texttt {xs}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {(x :: xs) @ nil} \hookrightarrow  \texttt {x :: xs}</fr:tex>.</fr:p>

      We proceed as follows:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {(x :: xs) @ nil} \\           &amp;\Longrightarrow  \texttt {x :: (xs @ nil)} &amp;&amp;\text {(\texttt {@} clause 2)} \\           &amp;\Longrightarrow  \texttt {x :: xs} &amp;&amp;\text {(IH)}         \end {aligned}       </fr:tex></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>404</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-0028</fr:addr><fr:route>150-0028.xml</fr:route><fr:title>Associativity of append</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all values <fr:code>l1, l2, l3 : int list</fr:code>, <fr:tex
display="block">\texttt {(l1 @ l2) @ l3} \cong  \texttt {l1 @ (l2 @ l3)}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>403</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#207</fr:addr><fr:route>unstable-207.xml</fr:route><fr:parent>150-0028</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>l1, l2, l3 : int list</fr:code> be arbitrary values.
  By structural induction on <fr:code>l1</fr:code>, using <fr:link
href="150-0020.xml"
type="local"
addr="150-0020">the definition of <fr:code>@</fr:code></fr:link>.
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:p>First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {(nil @ l2) @ l3} \\           &amp;\cong  \texttt {l2 @ l3} &amp;&amp;\text {(clause 2)}         \end {aligned}       </fr:tex>
      <fr:p>Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {nil @ (l2 @ l3)} \\           &amp;\cong  \texttt {l2 @ l3} &amp;&amp;\text {(clause 2)}         \end {aligned}       </fr:tex>
      <fr:p>Both sides are equivalent to <fr:code>l2 @ l3</fr:code>, so the case is proven.</fr:p></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:

      <fr:p><fr:strong>IH:</fr:strong> <fr:tex>\texttt {(xs @ l2) @ l3} \cong  \texttt {xs @ (l2 @ l3)}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {((x :: xs) @ l2) @ l3} \cong  \texttt {(x :: xs) @ (l2 @ l3)}</fr:tex>.</fr:p>

      <fr:p>First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {((x :: xs) @ l2) @ l3} \\           &amp;\cong  \texttt {(x :: (xs @ l2)) @ l3} &amp;&amp;\text {(\texttt {@} clause 2)} \\           &amp;\cong  \texttt {x :: ((xs @ l2) @ l3)} &amp;&amp;\text {(\texttt {@} clause 2)} \\           &amp;\cong  \texttt {x :: (xs @ (l2 @ l3))} &amp;&amp;\text {(IH)}         \end {aligned}       </fr:tex>
      <fr:p>Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {(x :: xs) @ (l2 @ l3)} \\           &amp;\cong  \texttt {x :: (xs @ (l2 @ l3))} &amp;&amp;\text {(\texttt {@} clause 2)} \\         \end {aligned}       </fr:tex>
      <fr:p>Both sides are equivalent, so the case is proven.</fr:p></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>416</fr:anchor><fr:addr>150-0026</fr:addr><fr:route>150-0026.xml</fr:route><fr:title>List reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>407</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0029</fr:addr><fr:route>150-0029.xml</fr:route><fr:title>Slow list reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* revSlow : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: revSlow l ==&gt; l', where l' is l reversed
 *)
fun revSlow (l : int list) : int list =
  case l of
    nil =&gt; nil
  | x :: xs =&gt; revSlow xs @ [x]
</html:code></fr:pre><fr:p>Notice that <fr:link
href="150-0020.xml"
type="local"
addr="150-0020">appending to the end of a list</fr:link> is slow, so <fr:code>revSlow</fr:code> is very slow (quadratic time).</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>409</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002A</fr:addr><fr:route>150-002A.xml</fr:route><fr:title>Reverse-append hybrid</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* revApp : int list * int list -&gt; int list
 * REQUIRES: true
 * ENSURES: revApp (l, acc) ~= revSlow l @ acc
 *)
fun revApp (l : int list, acc : int list) : int list =
  case l of
    nil =&gt; acc
  | x :: xs =&gt; revApp (xs, x :: acc)
</html:code></fr:pre><fr:p>We use a second "accumulator" argument, <fr:code>acc</fr:code>, to avoid appending each time.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>411</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-002B</fr:addr><fr:route>150-002B.xml</fr:route><fr:title>Correctness of <fr:code>revApp</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>ENSURES</fr:code> of <fr:code>revApp</fr:code> is correct: for all values <fr:code>l, acc : int list</fr:code>, we have <fr:tex
display="block">\texttt {revApp (l, acc)} \cong  \texttt {revSlow l @ acc}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>410</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#206</fr:addr><fr:route>unstable-206.xml</fr:route><fr:parent>150-002B</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>We use the definitions of <fr:link
href="150-0020.xml"
type="local"
addr="150-0020"><fr:code>@</fr:code></fr:link>, <fr:link
href="150-0029.xml"
type="local"
addr="150-0029"><fr:code>revSlow</fr:code></fr:link>, and <fr:link
href="150-002A.xml"
type="local"
addr="150-002A"><fr:code>revApp</fr:code></fr:link>.</fr:p>
  <fr:p>Let <fr:code>l : int list</fr:code> be an arbitrary value. We prove "for all values <fr:code>acc' : int list</fr:code>, <fr:tex>\texttt {revApp (l, acc')} \cong  \texttt {revSlow l @ acc'}</fr:tex>" by induction on <fr:code>l</fr:code>.</fr:p>
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:p>Let <fr:code>acc : int list</fr:code> be arbitrary. First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revApp (nil, acc)} \\           &amp;\cong  \texttt {acc} &amp;&amp;\text {(clause 1 of \texttt {revApp})}         \end {aligned}       </fr:tex>
      <fr:p>Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revSlow nil @ acc} \\           &amp;\cong  \texttt {nil @ acc} &amp;&amp;\text {(first clause of \texttt {revSlow})} \\           &amp;\cong  \texttt {acc}  &amp;&amp;\text {(first clause of \texttt {@})}         \end {aligned}       </fr:tex>
      <fr:p>Both sides are equivalent, so the case is proven.</fr:p></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:
      <fr:p><fr:strong>IH:</fr:strong> for all <fr:code>acc' : int list</fr:code>, <fr:tex>\texttt {revApp (xs, acc')} \cong  \texttt {revSlow xs @ acc'}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> for all <fr:code>acc : int list</fr:code>, <fr:tex>\texttt {revApp (x :: xs, acc)} \cong  \texttt {revSlow (x :: xs) @ acc}</fr:tex>.</fr:p>
      <fr:p>We name <fr:code>acc</fr:code> and <fr:code>acc'</fr:code> separately to reduce confusion.</fr:p>
      <fr:p>Let <fr:code>acc : int list</fr:code> be arbitrary. First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revApp (x :: xs, acc)} \\           &amp;\cong  \texttt {revApp (xs, x :: acc)}  &amp;&amp;\text {(clause 2 of \texttt {revApp})} \\           &amp;\cong  \texttt {revSlow xs @ (x :: acc)}  &amp;&amp;\text {(IH)}         \end {aligned}       </fr:tex>
      <fr:p>Here, we use the IH with <fr:code>acc'</fr:code> as <fr:code>x :: acc</fr:code>. Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revSlow (x :: xs) @ acc} \\           &amp;\cong  \texttt {(revSlow xs @ [x]) @ acc}  &amp;&amp;\text {(clause 2 of \texttt {revSlow})} \\           &amp;\cong  \texttt {revSlow xs @ ([x] @ acc)}  &amp;&amp;\text {(associativity of \texttt {@})} \\           &amp;\cong  \texttt {revSlow xs @ ((x :: nil) @ acc)} \\           &amp;\cong  \texttt {revSlow xs @ (x :: (nil @ acc))}  &amp;&amp;\text {(clause 2 of \texttt {@})} \\           &amp;\cong  \texttt {revSlow xs @ (x :: acc)}  &amp;&amp;\text {(clause 1 of \texttt {@})} \\         \end {aligned}       </fr:tex>
      <fr:p>Here, we used the <fr:link
href="150-0028.xml"
type="local"
addr="150-0028">associativity of <fr:code>@</fr:code></fr:link>. Both sides are then equivalent, so the case is proven.</fr:p></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>413</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002C</fr:addr><fr:route>150-002C.xml</fr:route><fr:title>List reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* rev : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: rev l ==&gt; l', where l' is l reversed
 *)
fun rev (l : int list) : int list = revApp (l, nil)
</html:code></fr:pre><fr:p>We use the stronger <fr:link
href="150-002A.xml"
type="local"
addr="150-002A"><fr:code>revApp</fr:code></fr:link> to implement <fr:code>rev</fr:code> efficiently.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>415</fr:anchor><fr:taxon>Corollary</fr:taxon><fr:addr>150-002D</fr:addr><fr:route>150-002D.xml</fr:route><fr:title>Correctness of <fr:code>rev</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:link
href="150-002C.xml"
type="local"
addr="150-002C"><fr:code>rev</fr:code></fr:link> and <fr:link
href="150-0029.xml"
type="local"
addr="150-0029"><fr:code>revSlow</fr:code></fr:link> are extensionally equivalent: <fr:tex
display="block">\texttt {rev} \cong  \texttt {revSlow}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>414</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#205</fr:addr><fr:route>unstable-205.xml</fr:route><fr:parent>150-002D</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p><fr:link
href="150-000T.xml"
type="local"
addr="150-000T">To show that two functions are extensionally equivalent</fr:link>, we take in an arbitrary input and show that its application makes both sides equivalent. Let <fr:code>l : int list</fr:code> be arbitrary; we show that <fr:tex
display="block">\texttt {rev l} \cong  \texttt {revSlow l}.</fr:tex></fr:p>
  <fr:p>By the <fr:link
href="150-002B.xml"
type="local"
addr="150-002B">correctness of <fr:code>revApp</fr:code></fr:link>, our lemma about <fr:link
href="150-0024.xml"
type="local"
addr="150-0024">appending <fr:code>nil</fr:code> on the right</fr:link>, and <fr:link
href="150-002C.xml"
type="local"
addr="150-002C">the definition of <fr:code>rev</fr:code></fr:link>, we have:</fr:p>
  <fr:tex
display="block">     \begin {aligned}       &amp;\texttt {rev l} \\       &amp;\cong  \texttt {revApp (l, nil)}  &amp;&amp;\text {(definition of \texttt {rev})} \\       &amp;\cong  \texttt {revSlow l @ nil}  &amp;&amp;\text {(correctness of \texttt {revApp})} \\       &amp;\cong  \texttt {revSlow l}  &amp;&amp;\text {(appending \texttt {nil} lemma)}     \end {aligned}   </fr:tex>
  <fr:p>This completes the proof.</fr:p>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>459</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect05</fr:addr><fr:route>150-lect05.xml</fr:route><fr:title>Datatypes and trees</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>28</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>441</fr:anchor><fr:addr>150-002F</fr:addr><fr:route>150-002F.xml</fr:route><fr:title>Datatypes</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>424</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002E</fr:addr><fr:route>150-002E.xml</fr:route><fr:title>Option types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, the type <fr:code>t option</fr:code> represents at most one value of type <fr:code>t</fr:code>.</fr:p><fr:p>The values of type <fr:code>t option</fr:code> are:</fr:p><fr:ol><fr:li><fr:code>NONE</fr:code>, with no other data</fr:li>
  <fr:li><fr:code>SOME v</fr:code>, where <fr:code>v : t</fr:code> is the single element contained</fr:li></fr:ol><fr:p>There are analogous expressions and patterns.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>427</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002G</fr:addr><fr:route>150-002G.xml</fr:route><fr:title>List minimum</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* listMin : int list -&gt; int
 * REQUIRES: l nonempty
 * ENSURES: listMin l ==&gt; the smallest integer contained in l
 *)
fun listMin (nil : int list) : int = raise Fail "violates REQUIRES"
  | listMin [x] = x
  | listMin (x :: xs) = Int.min (x, listMin xs)
</html:code></fr:pre><fr:p>Alternatively, using <fr:link
href="150-002E.xml"
type="local"
addr="150-002E">option types</fr:link>, we can implement a function <fr:code>listMin</fr:code> that computes the minimum of a list if one exists, or evaluates to <fr:code>NONE</fr:code> otherwise.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* listMin : int list -&gt; int option
 * REQUIRES: true
 * ENSURES: listMin l ==&gt; SOME (the smallest integer contained in l), or NONE if l is empty
 *)
fun listMin (nil : int list) : int option = NONE
  | listMin (x :: xs) =
      case listMin xs of
        NONE   =&gt; SOME x
      | SOME y =&gt; SOME (Int.min (x, y))
</html:code></fr:pre><fr:p>Here, <fr:code>NONE</fr:code> behaves like an <fr:tex>\infty </fr:tex>: extending <fr:code>int</fr:code> to <fr:code>int option</fr:code> is like adding a value <fr:tex>\infty </fr:tex> that we treat as larger than all integers.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>429</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002H</fr:addr><fr:route>150-002H.xml</fr:route><fr:title>Datatype declaration</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>datatype</fr:code> declaration lets us define a new type that can be pattern-matched on.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype newTypeName
  = Constructor1 of dataToContain1
  | Constructor2 of dataToContain2
  | Constructor3  (* does not contain any data *)
  | ...
  | ConstructorN of dataToContainN
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>431</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002I</fr:addr><fr:route>150-002I.xml</fr:route><fr:title>Existing types as <fr:code>datatype</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The types <fr:link
href="150-0007.xml"
type="local"
addr="150-0007"><fr:code>bool</fr:code></fr:link>, <fr:link
href="150-002E.xml"
type="local"
addr="150-002E"><fr:code>option</fr:code></fr:link>, and <fr:link
href="150-001Z.xml"
type="local"
addr="150-001Z"><fr:code>list</fr:code></fr:link> can all be implemented via <fr:code>datatype</fr:code> declarations.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype bool
  = false
  | true

datatype intoption
  = NONE
  | SOME of int

datatype intlist
  = nil
  | :: of int * intlist
</html:code></fr:pre><fr:p>Note that here, we define <fr:code>intoption</fr:code> and <fr:code>intlist</fr:code> (as one word), rather than <fr:code>int option</fr:code> and <fr:code>int list</fr:code>. We will define the more general latter versions soon.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>433</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002K</fr:addr><fr:route>150-002K.xml</fr:route><fr:title>Type alias declaration</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To alias a type to a new name, we may use:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type newName = someType
</html:code></fr:pre><fr:p>This is solely for readability, reducing redundancy.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>436</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002L</fr:addr><fr:route>150-002L.xml</fr:route><fr:title>Coordinate type alias</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using a <fr:link
href="150-002K.xml"
type="local"
addr="150-002K">type alias declaration</fr:link>, we can define aliases for points and vectors in a 2D plane:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type point = int * int
type vector = int * int
</html:code></fr:pre><fr:p>We then use <fr:code>point</fr:code> and <fr:code>vector</fr:code> as if they are <fr:code>int * int</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* distance : point * point -&gt; vector *)
fun distance ((x1, y1) : point, (x2, y2) : point) : vector =
  (x2 - x1, y2 - y1)
</html:code></fr:pre><fr:p><fr:em>Warning:</fr:em> This code would still typecheck if <fr:code>vector</fr:code> was swapped for <fr:code>point</fr:code> or vice versea, since both are <fr:code>int * int</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>440</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002J</fr:addr><fr:route>150-002J.xml</fr:route><fr:title>Custom datatype for messages</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When implementing a messaging app, we may consider three varieties of messages:</fr:p><fr:ol><fr:li>A simple text message, consisting of a string.</fr:li>
  <fr:li>An image, and optionally a caption for the image.</fr:li>
  <fr:li>A voice message.</fr:li></fr:ol><fr:p>We can represent these options using the following <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype message
  = Text of string
  | Image of image * string option
  | Voice of audio
</html:code></fr:pre><fr:p>We assume that <fr:code>image</fr:code> and <fr:code>audio</fr:code> are defined prior.</fr:p><fr:p>To implement a search functionality, we can pattern match on the <fr:code>message</fr:code> type.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun contains (m : message, s : string) : bool =
  case m of
    Text s' =&gt; isSubstring (s, s')
  | Image (_, NONE) =&gt; false
  | Image (_, SOME s') =&gt; isSubstring (s, s')
  | Voice _ =&gt; false
</html:code></fr:pre><fr:p>We may also use a <fr:link
href="150-002K.xml"
type="local"
addr="150-002K">type alias declaration</fr:link> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type messages = message list

fun anyContains (l : messages, s : string) : bool =
  case l of
    nil =&gt; false
  | m :: ms =&gt; contains (m, s) orelse anyContains (ms, s)
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>458</fr:anchor><fr:addr>150-002M</fr:addr><fr:route>150-002M.xml</fr:route><fr:title>Trees</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>443</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002N</fr:addr><fr:route>150-002N.xml</fr:route><fr:title>Binary tree with <fr:code>int</fr:code>s at the nodes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We define the following <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link> to represent binary trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype tree
  = Empty
  | Node of tree * int * tree
</html:code></fr:pre><fr:p>Note that <fr:code>tree</fr:code> is used recursively.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>445</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002O</fr:addr><fr:route>150-002O.xml</fr:route><fr:title>Sample tree</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the definition of <fr:link
href="150-002N.xml"
type="local"
addr="150-002N">binary trees</fr:link>, we can write down sample trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun leaf (x : int) : tree = Node (Empty, x, Empty)

val myTree : tree =
  Node
    ( Node
        ( leaf 1
        , 2
        , leaf 3
        )
    , 4
    , leaf 5
    )
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>447</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002P</fr:addr><fr:route>150-002P.xml</fr:route><fr:title>Size of a tree</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* size : tree -&gt; int
 * REQUIRES: true
 * ENSURES: size t ==&gt; the number of nodes in t
 *)
fun size (Empty : tree) : int = 0
  | size (Node (l, _, r)) = size l + 1 + size r
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>449</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002Q</fr:addr><fr:route>150-002Q.xml</fr:route><fr:title>In-order traversal of a tree</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* inordSlow : tree -&gt; int list
 * REQUIRES: true
 * ENSURES: inordSlow t ==&gt; a list of elements of t in left-to-right order
 *)
fun inordSlow (Empty : tree) : int list = nil
  | inordSlow (Node (l, x, r)) = inordSlow l @ x :: inordSlow r
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>450</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002T</fr:addr><fr:route>150-002T.xml</fr:route><fr:title>Structural induction on <fr:link
href="150-002N.xml"
type="local"
addr="150-002N"><fr:code>tree</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all tree values <fr:code>t : tree</fr:code>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:code>Empty</fr:code>.</fr:li>
  <fr:li>Inductive Case: Prove that for all <fr:code>x : int</fr:code> and <fr:code>l, r : tree</fr:code>, if the property holds on both <fr:code>l</fr:code> and <fr:code>r</fr:code> (inductive hypotheses), then the property holds on <fr:code>Node (l, x, r)</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>452</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-002S</fr:addr><fr:route>150-002S.xml</fr:route><fr:title>Length of in-order traversal is tree size</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the definitions of <fr:link
href="150-002P.xml"
type="local"
addr="150-002P"><fr:code>size</fr:code></fr:link>, <fr:link
href="150-0023.xml"
type="local"
addr="150-0023"><fr:code>length</fr:code></fr:link>, and <fr:link
href="150-002O.xml"
type="local"
addr="150-002O"><fr:code>inordSlow</fr:code></fr:link>.</fr:p><fr:p>For all <fr:code>t : tree</fr:code>, it is the case that <fr:tex
display="block">\texttt {size t} \cong  \texttt {length (inordSlow t)}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>451</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#204</fr:addr><fr:route>unstable-204.xml</fr:route><fr:parent>150-002S</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>t : tree</fr:code> be arbitrary; we go by structural induction on <fr:code>t</fr:code>.
  <fr:ol><fr:li>
      Case <fr:code>Empty</fr:code>:
      <fr:p>On the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           \texttt {size Empty} \cong  \texttt {0} &amp;&amp;\text {(clause 1 of \texttt {size})}         \end {aligned}       </fr:tex>
      <fr:p>On the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {length (inordSlow Empty)} \\           &amp;\cong  \texttt {length nil} &amp;&amp;\text {(first clause of \texttt {inordSlow})} \\           &amp;\cong  \texttt {0}  &amp;&amp;\text {(first clause of \texttt {length})}         \end {aligned}       </fr:tex>
      <fr:p>Both sides are equivalent, so the case is proven.</fr:p></fr:li>
    <fr:li>
      Case <fr:code>Node (l, x, r)</fr:code>:
      <fr:p><fr:strong>IH1:</fr:strong> <fr:tex>\texttt {size l} \cong  \texttt {length (inordSlow l)}</fr:tex></fr:p>
      <fr:p><fr:strong>IH2:</fr:strong> <fr:tex>\texttt {size r} \cong  \texttt {length (inordSlow r)}</fr:tex></fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {size (Node (l, x, r))} \cong  \texttt {length (inordSlow (Node (l, x, r)))}</fr:tex>.</fr:p>
      <fr:p>First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {size (Node (l, x, r))} \\           &amp;\cong  \texttt {size l + 1 + size r}  &amp;&amp;\text {(clause 2 of \texttt {size})} \\           &amp;\cong  \texttt {length (inordSlow l) + 1 + length (inordSlow r)} &amp;&amp;\text {(IHs)}         \end {aligned}       </fr:tex>
      <fr:p>Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {length (inordSlow (Node (l, x, r)))} \\           &amp;\cong  \texttt {length (inordSlow l @ x :: inordSlow r)}  &amp;&amp;\text {(clause 2 of \texttt {inordSlow})} \\           &amp;\cong  \texttt {length (inordSlow l) + length (x :: inordSlow r)}  &amp;&amp;\text {(lemma)} \\           &amp;\cong  \texttt {length (inordSlow l) + (1 + length (inordSlow r))}  &amp;&amp;\text {(clause 2 of \texttt {length})} \\           &amp;\cong  \texttt {length (inordSlow l) + 1 + length (inordSlow r)}  &amp;&amp;\text {(math)}         \end {aligned}       </fr:tex>
      <fr:p>Here, we used <fr:link
href="150-002R.xml"
type="local"
addr="150-002R">a lemma about the length of appended lists</fr:link>. Both sides are then equivalent, so the case is proven.</fr:p></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>454</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002U</fr:addr><fr:route>150-002U.xml</fr:route><fr:title>Efficient in-order traversal</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* inordApp : tree * int list -&gt; int list
 * REQUIRES: true
 * ENSURES: inordApp (t, acc) ~= inordSlow t @ acc
 *)
fun inordApp (Empty : tree, acc : int list) : int list = acc
  | inordApp (Node (l, x, r), acc) = inordApp (l, x :: inordApp (r, acc))

(* inord : tree -&gt; int list
 * REQUIRES: true
 * ENSURES: inord t ==&gt; a list of elements of t in left-to-right order
 *)
fun inord (t : tree) : int list = inordApp (t, nil)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>455</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-002V</fr:addr><fr:route>150-002V.xml</fr:route><fr:title>Correctness of <fr:code>inordApp</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>v : tree</fr:code> and <fr:code>l : int list</fr:code>, we have <fr:tex
display="block">\texttt {inordApp (t, acc)} \cong  \texttt {inordSlow t @ acc}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>457</fr:anchor><fr:taxon>Corollary</fr:taxon><fr:addr>150-002W</fr:addr><fr:route>150-002W.xml</fr:route><fr:title>Correctness of <fr:code>inord</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:link
href="150-002U.xml"
type="local"
addr="150-002U"><fr:code>inord</fr:code></fr:link> and <fr:link
href="150-002O.xml"
type="local"
addr="150-002O"><fr:code>inordSlow</fr:code></fr:link> are extensionally equivalent: <fr:tex
display="block">\texttt {inord} \cong  \texttt {inordSlow}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>456</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#203</fr:addr><fr:route>unstable-203.xml</fr:route><fr:parent>150-002W</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>This follows immediately from the <fr:link
href="150-002V.xml"
type="local"
addr="150-002V">correctness of <fr:code>inordApp</fr:code></fr:link>, our lemma about <fr:link
href="150-0024.xml"
type="local"
addr="150-0024">appending <fr:code>nil</fr:code> on the right</fr:link>, and <fr:link
href="150-002U.xml"
type="local"
addr="150-002U">the definition of <fr:code>inord</fr:code></fr:link>.</fr:p>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>606</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect06</fr:addr><fr:route>150-lect06.xml</fr:route><fr:title>Cost analysis</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>30</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>478</fr:anchor><fr:addr>150-002X</fr:addr><fr:route>150-002X.xml</fr:route><fr:title>Basic cost analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>466</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0031</fr:addr><fr:route>150-0031.xml</fr:route><fr:title>Cost analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:em>Goal:</fr:em> understand the cost of programs. Some choices:</fr:p><fr:ul><fr:li>Time each execution. However, this is machine-dependent.</fr:li>
  <fr:li>Count a given metric (recursive calls; additions; evaluation steps; etc.). This is abstract enough to be proved, and it corresponds to real time.</fr:li></fr:ul><fr:p>First, we choose a <fr:em>cost metric</fr:em> and <fr:em>size metrics</fr:em> for inputs. Then, we:</fr:p><fr:ol><fr:li>Write a recurrence following the structure of the code, computing cost from input sizes.</fr:li>
  <fr:li>Solve for a closed form.</fr:li>
  <fr:li>Give a simple asymptotic (big-<fr:tex>\mathcal {O}</fr:tex>) solution.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>468</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0032</fr:addr><fr:route>150-0032.xml</fr:route><fr:title>Recurrence for slow list reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the definition of <fr:code>revSlow</fr:code>:</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>467</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0029</fr:addr><fr:route>150-0029.xml</fr:route><fr:title>Slow list reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* revSlow : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: revSlow l ==&gt; l', where l' is l reversed
 *)
fun revSlow (l : int list) : int list =
  case l of
    nil =&gt; nil
  | x :: xs =&gt; revSlow xs @ [x]
</html:code></fr:pre><fr:p>Notice that <fr:link
href="150-0020.xml"
type="local"
addr="150-0020">appending to the end of a list</fr:link> is slow, so <fr:code>revSlow</fr:code> is very slow (quadratic time).</fr:p></fr:mainmatter></fr:tree><fr:p>We give its recurrence as follows, counting <fr:em>recursive calls</fr:em> as our cost metric, in terms of the length of the input list.</fr:p><fr:tex
display="block">   \begin {aligned}     W(0) &amp;= 0 \\     W(n) &amp;= W(n - 1) + W_\texttt {@}(n-1, 1) + 1 \\           &amp;= W(n - 1) + (n - 1) + 1 \\           &amp;= W(n - 1) + n   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>469</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0033</fr:addr><fr:route>150-0033.xml</fr:route><fr:title>Unrolling technique</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To guess a solution to a recurrence, the simplest thing to do is unfold the definition repeatedly and observe the behavior.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>471</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0034</fr:addr><fr:route>150-0034.xml</fr:route><fr:title>Closed form for slow list reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To solve the <fr:link
href="150-0032.xml"
type="local"
addr="150-0032">recurrence for slow list reverse</fr:link>, we first guess a solution by unrolling.
<fr:tex
display="block">   \begin {aligned}     W(n)       &amp;= W(n-1) + n \\       &amp;= W(n-2) + (n-1) + n \\       &amp;= W(n-3) + (n-2) + (n-1) + n \\       &amp;= \cdots  \\       &amp;= W(0) + 1 + 2 + \cdots  + (n-1) + n \\       &amp;= 0 + 1 + 2 + \cdots  + (n-1) + n   \end {aligned} </fr:tex>
It is well-known that <fr:tex>\sum _{i = 0}^n = \frac {n(n + 1)}{2}</fr:tex>.
To validate our guess, we prove it by induction.
</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>470</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#202</fr:addr><fr:route>unstable-202.xml</fr:route><fr:parent>150-0034</fr:parent></fr:frontmatter><fr:mainmatter>
  We show that <fr:tex>W(n) = \frac {n(n+1)}{2}</fr:tex> by induction on <fr:tex>n</fr:tex>.
  <fr:ol><fr:li>
      Case <fr:tex>0</fr:tex>:
      <fr:tex
display="block">         \begin {aligned}           W(0)             &amp;= 0 \\             &amp;= \frac {0(1)}{2}         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:tex>n + 1</fr:tex>:
      <fr:p><fr:strong>IH:</fr:strong> <fr:tex>W(n) = \frac {n(n+1)}{2}</fr:tex></fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>W(n+1) = \frac {(n+1)(n+2)}{2}</fr:tex></fr:p>
      <fr:tex
display="block">         \begin {aligned}           W(n + 1)             &amp;= W(n) + (n + 1)  &amp;&amp;\text {(definition)} \\             &amp;= \frac {n(n+1)}{2} + (n + 1) &amp;&amp;\text {(IH)} \\             &amp;= \frac {n(n+1)}{2} + \frac {2(n+1)}{2} &amp;&amp;\text {(math)} \\             &amp;= \frac {n(n+1) + 2(n+1)}{2}  &amp;&amp;\text {(math)} \\             &amp;= \frac {(n + 2)(n + 1)}{2}  &amp;&amp;\text {(math)} \\             &amp;= \frac {(n + 1)(n + 2)}{2}  &amp;&amp;\text {(math)}         \end {aligned}       </fr:tex></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>473</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0035</fr:addr><fr:route>150-0035.xml</fr:route><fr:title>Recurrence for reverse-append hybrid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the definition of <fr:code>revAppend</fr:code>:</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>472</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002A</fr:addr><fr:route>150-002A.xml</fr:route><fr:title>Reverse-append hybrid</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* revApp : int list * int list -&gt; int list
 * REQUIRES: true
 * ENSURES: revApp (l, acc) ~= revSlow l @ acc
 *)
fun revApp (l : int list, acc : int list) : int list =
  case l of
    nil =&gt; acc
  | x :: xs =&gt; revApp (xs, x :: acc)
</html:code></fr:pre><fr:p>We use a second "accumulator" argument, <fr:code>acc</fr:code>, to avoid appending each time.</fr:p></fr:mainmatter></fr:tree><fr:p>We give its recurrence as follows, counting <fr:em>recursive calls</fr:em> as our cost metric, in terms of the length of the input lists.</fr:p><fr:tex
display="block">   \begin {aligned}     W(0, m) &amp;= 0 \\     W(n, m) &amp;= W(n - 1, m + 1) + 1   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>475</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0036</fr:addr><fr:route>150-0036.xml</fr:route><fr:title>Closed form for reverse-append hybrid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To solve the <fr:link
href="150-0035.xml"
type="local"
addr="150-0035">recurrence for reverse-append hybrid</fr:link>, we first guess a solution by unrolling.
<fr:tex
display="block">   \begin {aligned}     W(n, m)       &amp;= W(n-1, m+1) + 1 \\       &amp;= W(n-2, m+2) + 2 \\       &amp;= W(n-3, m+3) + 3 \\       &amp;= \cdots  \\       &amp;= W(0, m+n) + n \\       &amp;= 0 + n \\       &amp;= n   \end {aligned} </fr:tex>
To validate our guess, we prove it by induction.
</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>474</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#201</fr:addr><fr:route>unstable-201.xml</fr:route><fr:parent>150-0036</fr:parent></fr:frontmatter><fr:mainmatter>
  We show that "for all <fr:tex>m</fr:tex>, <fr:tex>W(n, m) = n</fr:tex>" by induction on <fr:tex>n</fr:tex>.
  <fr:ol><fr:li>
      Case <fr:tex>0</fr:tex>:
      <fr:p>Let <fr:tex>m</fr:tex> be arbitrary.</fr:p>
      <fr:tex
display="block">         \begin {aligned}           W(0, m)             &amp;= 0         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:tex>n + 1</fr:tex>:
      <fr:p><fr:strong>IH:</fr:strong> for all <fr:tex>m'</fr:tex>, <fr:tex>W(n, m') = n</fr:tex></fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> for all <fr:tex>m</fr:tex>, <fr:tex>W(n + 1, m) = n + 1</fr:tex></fr:p>
      <fr:p>Let <fr:tex>m</fr:tex> be arbitrary.</fr:p>
      <fr:tex
display="block">         \begin {aligned}           W(n + 1, m)             &amp;= W(n, m + 1) + 1  &amp;&amp;\text {(definition)} \\             &amp;= n + 1 &amp;&amp;\text {(IH)}         \end {aligned}       </fr:tex>
      <fr:p>Here, we use the IH with <fr:tex>m' = m + 1</fr:tex>.</fr:p></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>477</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0037</fr:addr><fr:route>150-0037.xml</fr:route><fr:title>Cost of list reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the definition of <fr:code>rev</fr:code>:</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>476</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-002C</fr:addr><fr:route>150-002C.xml</fr:route><fr:title>List reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* rev : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: rev l ==&gt; l', where l' is l reversed
 *)
fun rev (l : int list) : int list = revApp (l, nil)
</html:code></fr:pre><fr:p>We use the stronger <fr:link
href="150-002A.xml"
type="local"
addr="150-002A"><fr:code>revApp</fr:code></fr:link> to implement <fr:code>rev</fr:code> efficiently.</fr:p></fr:mainmatter></fr:tree><fr:p>We give its "recurrence" (it's not recursive, since the code isn't recursive!) as follows, counting <fr:em>recursive calls</fr:em> as our cost metric, in terms of the length of the input lists.</fr:p><fr:tex
display="block">   \begin {aligned}     W(n) &amp;= W_\texttt {revApp}(n, 0)   \end {aligned} </fr:tex><fr:p>So, by by the <fr:link
href="150-0036.xml"
type="local"
addr="150-0036">closed form for reverse-append hybrid</fr:link>, we have <fr:tex>W(n) = n</fr:tex>. This is much better than <fr:tex>W_\texttt {slowRev}(n) = \frac {1}{2}(n^2 + n)</fr:tex>!</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>537</fr:anchor><fr:addr>150-002Z</fr:addr><fr:route>150-002Z.xml</fr:route><fr:title>Asymptotic analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>479</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0038</fr:addr><fr:route>150-0038.xml</fr:route><fr:title>Big-<fr:tex>\mathcal {O}</fr:tex></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Sometimes, we wish to simplify exact bounds, ignoring linear factors. To do this, we use big-<fr:tex>\mathcal {O}</fr:tex> notation.</fr:p><fr:p>Let <fr:tex>X</fr:tex> be a set and let <fr:tex>f, g : X \to  \mathbb {N}</fr:tex>. We say that <fr:tex>f \in  \mathcal {O}(g)</fr:tex> when there exist constants <fr:tex>a, b : \mathbb {N}</fr:tex> such that <fr:tex>f \le  ag + b</fr:tex>, i.e. <fr:tex
display="block">\forall  x : X, f(x) \le  ag(x) + b.</fr:tex></fr:p><fr:p>We write <fr:tex>\mathcal {O}(g)</fr:tex> for the set of all functions <fr:tex>f</fr:tex> bounded by <fr:tex>g</fr:tex>, i.e. <fr:tex
display="block">\mathcal {O}(g) = \{f : X \to  \mathbb {N} \mid  f \in  \mathcal {O}(g) \}.</fr:tex></fr:p><fr:p>Traditionally, <fr:tex>X = \mathbb {N}</fr:tex> and function inputs are assumed to be named <fr:tex>n</fr:tex>: for example, <fr:tex>\mathcal {O}(n^2)</fr:tex> is syntactic sugar for <fr:tex>\mathcal {O}(n \mapsto  n^2)</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>482</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003B</fr:addr><fr:route>150-003B.xml</fr:route><fr:title>Big-<fr:tex>\mathcal {O}</fr:tex> bounds</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We have <fr:tex>n^2 \in  \mathcal {O}(n^2 + n + 3)</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>480</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#199</fr:addr><fr:route>unstable-199.xml</fr:route><fr:parent>150-003B</fr:parent></fr:frontmatter><fr:mainmatter>
  By <fr:link
href="150-0038.xml"
type="local"
addr="150-0038">the definition</fr:link>, we must choose <fr:tex>a, b : \mathbb {N}</fr:tex> such that <fr:tex>n^2 \le  a(n^2 + n + 3) + b</fr:tex>.
  Let <fr:tex>a = 1</fr:tex> and <fr:tex>b = 0</fr:tex>; we have <fr:tex>n^2 \le  n^2 + n + 3</fr:tex> immediately.
</fr:mainmatter></fr:tree>
 
<fr:p>We have <fr:tex>n^2 + n + 3 \in  \mathcal {O}(n^2)</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>481</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#200</fr:addr><fr:route>unstable-200.xml</fr:route><fr:parent>150-003B</fr:parent></fr:frontmatter><fr:mainmatter>
  By <fr:link
href="150-0038.xml"
type="local"
addr="150-0038">the definition</fr:link>, we must choose <fr:tex>a, b : \mathbb {N}</fr:tex> such that <fr:tex>n^2 + n + 3 \le  an^2 + b</fr:tex>.
  Let <fr:tex>a = 2</fr:tex> and <fr:tex>b = 3</fr:tex>; we have <fr:tex>n^2 + n + 3 \le  2n^2 + 3 = n^2 + n^2 + 3</fr:tex>, since <fr:tex>n^2 \le  n^2</fr:tex>, <fr:tex>n \le  n^2</fr:tex>, and <fr:tex>3 \le  3</fr:tex>.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>483</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-0039</fr:addr><fr:route>150-0039.xml</fr:route><fr:title>Properties of big-<fr:tex>\mathcal {O}</fr:tex></fr:title></fr:frontmatter><fr:mainmatter><fr:ol><fr:li><fr:tex>\mathcal {O}</fr:tex> is a preorder:
    <fr:ul><fr:li><fr:tex>\mathcal {O}</fr:tex> is reflexive: for all <fr:tex>f</fr:tex>, we have <fr:tex>f \in  \mathcal {O}(f)</fr:tex>.</fr:li>
      <fr:li><fr:tex>\mathcal {O}</fr:tex> is transitive: for all <fr:tex>f,g,h</fr:tex>, if <fr:tex>f \in  \mathcal {O}(g)</fr:tex> and <fr:tex>g \in  O(h)</fr:tex>, then <fr:tex>f \in  O(h)</fr:tex>.</fr:li></fr:ul></fr:li>
  <fr:li>If <fr:tex>f \in  \mathcal {O}(g)</fr:tex> and <fr:tex>f' \in  \mathcal {O}(g')</fr:tex>, then <fr:tex>f + f' \in  \mathcal {O}(g + g')</fr:tex>, where <fr:tex>(f + f')(x) = f(x) + f'(x)</fr:tex>.</fr:li>
  <fr:li>For all <fr:tex>f,g : X \to  \mathbb {N}</fr:tex>, we have <fr:tex>\mathcal {O}(f + g) = \mathcal {O}(\max (f, g))</fr:tex>.</fr:li>
  <fr:li>For all <fr:tex>a, b : \mathbb {N}</fr:tex> and <fr:tex>f : X \to  \mathbb {N}</fr:tex>, we have <fr:tex>\mathcal {O}(f) = \mathcal {O}(af + b)</fr:tex>, where <fr:tex
display="block">(af + b)(x) = a \cdot  f(x) + b</fr:tex> by definition.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>509</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003A</fr:addr><fr:route>150-003A.xml</fr:route><fr:title>Common big-<fr:tex>\mathcal {O}</fr:tex> classes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following classes are distinct, ordered by inclusion from top to bottom:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:td><fr:strong>Class</fr:strong></html:td>

  <html:td><fr:strong>Common Name</fr:strong></html:td>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>

  <html:td>constant</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(\log  n)</fr:tex></html:td>

  <html:td>logarithmic</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n)</fr:tex></html:td>

  <html:td>linear</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n \log  n)</fr:tex></html:td>

  <html:td>quasilinear/log-linear</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n^2)</fr:tex></html:td>

  <html:td>quadratic</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(n^3)</fr:tex></html:td>

  <html:td>cubic</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathcal {O}(2^n)</fr:tex></html:td>

  <html:td>exponential</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>510</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003C</fr:addr><fr:route>150-003C.xml</fr:route><fr:title>Big-<fr:tex>\mathcal {O}</fr:tex> bounds for list reverse algorithms</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the bounds <fr:link
href="150-0034.xml"
type="local"
addr="150-0034">for <fr:code>revSlow</fr:code></fr:link>, <fr:tex>\frac {1}{2}(n^2 + n)</fr:tex>, and <fr:link
href="150-0037.xml"
type="local"
addr="150-0037">for <fr:code>rev</fr:code></fr:link>, <fr:tex>n</fr:tex>.</fr:p><fr:p>We have a tight big-<fr:tex>\mathcal {O}</fr:tex> bound <fr:tex>W_\texttt {revSlow}(n) \in  \mathcal {O}(n^2)</fr:tex>. We can prove it using <fr:link
href="150-0039.xml"
type="local"
addr="150-0039">properties of big-<fr:tex>\mathcal {O}</fr:tex></fr:link>:
<fr:tex
display="block">   \begin {aligned}     \frac {1}{2}(n^2 + n)       &amp;\in  \mathcal {O}\left (\frac {1}{2}(n^2 + n)\right ) \\       &amp;= \mathcal {O}(n^2 + n) \\       &amp;= \mathcal {O}(\max (n^2, n)) \\       &amp;= \mathcal {O}(n^2)   \end {aligned} </fr:tex>
In your analyses, you need not justify your asymptotic bounds formally in this way; for example, you are welcome to immediately state that <fr:tex>\frac {1}{2}(n^2 + n) \in  \mathcal {O}(n^2)</fr:tex> without justification.
</fr:p><fr:p>We also have a tight big-<fr:tex>\mathcal {O}</fr:tex> bound <fr:tex>W_\texttt {rev}(n) \in  \mathcal {O}(n)</fr:tex>, by reflexivity.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>536</fr:anchor><fr:taxon>Table</fr:taxon><fr:addr>150-003E</fr:addr><fr:route>150-003E.xml</fr:route><fr:title>Solutions to common recurrences</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the below table, we include solutions to common recurrences, where we let <fr:tex>T(0) = c_0</fr:tex>.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:td><fr:strong>Recurrence</fr:strong> <fr:tex>T(n) = \cdots </fr:tex></html:td>

  <html:td><fr:strong>Exact Solution</fr:strong></html:td>

  <html:td><fr:strong><fr:tex>\mathcal {O}(-)</fr:tex></fr:strong></html:td>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>T(n-1) + c_1</fr:tex></html:td>

  <html:td><fr:tex>c_0 + c_1n</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(n)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>2T(n-1) + c_1</fr:tex></html:td>

  <html:td><fr:tex>c_02^n + c_1\left (2^n-1\right )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(2^n)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>T(n-1) + c_1n + c_2</fr:tex></html:td>

  <html:td><fr:tex>c_0 + c_1\frac {n(n+1)}{2} + c_2n</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(n^2)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>2T(n-1) + c_1n + c_2</fr:tex></html:td>

  <html:td><fr:tex>c_02^n + c_1\left (2^{n+1}-n-2\right ) + c_2(2^n - 1)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(2^n)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>T(n-1) + c_1\log _2(n) + c_2</fr:tex></html:td>

  <html:td><fr:tex>c_0 + c_1\log (n!) + c_2n</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(n \log  n)</fr:tex></html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>598</fr:anchor><fr:addr>150-002Y</fr:addr><fr:route>150-002Y.xml</fr:route><fr:title>Cost analysis of trees</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>538</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003D</fr:addr><fr:route>150-003D.xml</fr:route><fr:title>Tree size metrics and assumptions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When analyzing the cost of a tree algorithm, we typically use one of the following approaches:</fr:p><fr:ul><fr:li>
    Assume the tree is a <fr:em>left or right spine</fr:em>, only consisting of nonempty left or right children.
    <fr:ul><fr:li>Here, we may use either depth <fr:tex>d</fr:tex> or number of nodes <fr:tex>n</fr:tex>; both are equivalent.</fr:li></fr:ul></fr:li>
  <fr:li>
    Assume the tree is <fr:em>(full and) balanced</fr:em>, where every node has two children and all paths from leaves to the root are of the same length.
    <fr:ul><fr:li>We may use depth <fr:tex>d</fr:tex>, equal to <fr:tex>\log _2(n + 1)</fr:tex>.</fr:li>
      <fr:li>Alternatively, we may use number of nodes <fr:tex>n</fr:tex>, equal to <fr:tex>2^d - 1</fr:tex>.</fr:li></fr:ul></fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>540</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003F</fr:addr><fr:route>150-003F.xml</fr:route><fr:title>Tree sum</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* sum : tree -&gt; int *)
fun sum Empty = 0
  | sum (Node (l, x, r)) = sum l + x + sum r
</html:code></fr:pre><fr:p>For our cost analyses, we choose to count <fr:em>number of additions evaluated</fr:em>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>541</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003G</fr:addr><fr:route>150-003G.xml</fr:route><fr:title>Tree sum work analysis, assuming spine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link> in terms of the number of nodes <fr:tex>n</fr:tex> in the tree, assuming the tree is a left spine. We follow <fr:link
href="150-0031.xml"
type="local"
addr="150-0031">the template</fr:link>:</fr:p><fr:ol><fr:li>
    First, we write the recurrence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(n) &amp;= W(n - 1) + W(0) + 2 \\              &amp;= W(n - 1) + 0 + 2 \\              &amp;= W(n - 1) + 2       \end {aligned}     </fr:tex></fr:li>
  <fr:li>By <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">the table</fr:link> (or unrolling and induction), we have that <fr:tex>W(n) = 2n</fr:tex>.</fr:li>
  <fr:li>So, <fr:tex>W(n) \in  \mathcal {O}(n)</fr:tex>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>561</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003H</fr:addr><fr:route>150-003H.xml</fr:route><fr:title>Tree method technique</fr:title></fr:frontmatter><fr:mainmatter><fr:p>
  To guess a solution to a recurrence with multiple recursive calls, the simplest thing to do is to consider the tree of costs.
  Determine the following quantities:
  
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
    

    
  <html:tr>
  <html:td><fr:strong>Symbol</fr:strong></html:td>

  <html:td><fr:strong>Description</fr:strong></html:td>
</html:tr>

    
      
  <html:tr>
  <html:td><fr:tex>L</fr:tex></html:td>

  <html:td>number of levels in the computation tree</html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>n_i</fr:tex></html:td>

  <html:td>nodes at level <fr:tex>i</fr:tex>, where <fr:tex>0</fr:tex> is the top level</html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>w_i</fr:tex></html:td>

  <html:td>non-recursive work at level <fr:tex>i</fr:tex></html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>e</fr:tex></html:td>

  <html:td>number of leaves</html:td>
</html:tr>

    
    
      
  <html:tr>
  <html:td><fr:tex>b</fr:tex></html:td>

  <html:td>cost per leaf/base case</html:td>
</html:tr>

    
  </html:table>

  Then, the cost should be <fr:tex
display="block">e \cdot  b + \sum _{i = 0}^{L - 1} n_i \cdot  w_i.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>562</fr:anchor><fr:taxon>Table</fr:taxon><fr:addr>150-003J</fr:addr><fr:route>150-003J.xml</fr:route><fr:title>Common summations</fr:title></fr:frontmatter><fr:mainmatter><fr:tex
display="block">   \begin {aligned}     \sum _{i = 0}^{n - 1} c &amp;= cn \\     \sum _{i = 0}^{n - 1} i &amp;= \frac {n(n - 1)}{2} \\     \sum _{i = 0}^{n - 1} a^i &amp;= \frac {a^n - 1}{a - 1} \\     \sum _{i = 0}^{n - 1} 2^i &amp;= 2^n - 1 \\     \sum _{i = 0}^{n - 1} 2^{-i} &amp;\le  \sum _{i = 0}^\infty  2^{-i} = 2   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>597</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003I</fr:addr><fr:route>150-003I.xml</fr:route><fr:title>Tree sum work analysis, assuming balanced tree</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We now analyze <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link> in terms of the depth <fr:tex>d</fr:tex> of the tree, assuming the tree is balanced. We follow <fr:link
href="150-0031.xml"
type="local"
addr="150-0031">the template</fr:link>:</fr:p><fr:ol><fr:li>
    First, we write the recurrence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(d) &amp;= W(d - 1) + W(d - 1) + 2 \\              &amp;= 2W(d - 1) + 2       \end {aligned}     </fr:tex></fr:li>
  <fr:li>
    To guess a cost bound, we use the <fr:link
href="150-003H.xml"
type="local"
addr="150-003H">tree method</fr:link>.
    
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
      

      
        
  <html:tr>
  <html:td><fr:tex>L</fr:tex></html:td>

  <html:td><fr:tex>d</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>n_i</fr:tex></html:td>

  <html:td><fr:tex>2^i</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>w_i</fr:tex></html:td>

  <html:td><fr:tex>2</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>e</fr:tex></html:td>

  <html:td><fr:tex>2^d</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>b</fr:tex></html:td>

  <html:td><fr:tex>0</fr:tex></html:td>
</html:tr>

      
    </html:table>

    So, we guess
    <fr:tex
display="block">       \begin {aligned}         \sum _{i = 0}^{d - 1} 2 \cdot  2^i           &amp;= 2 \cdot  \sum _{i = 0}^{d - 1} 2^i \\           &amp;= 2 \cdot  (2^d - 1) \\           &amp;= 2^{d + 1} - 2       \end {aligned}     </fr:tex>
    using the <fr:link
href="150-003J.xml"
type="local"
addr="150-003J">table of common summations</fr:link>.
    We prove it as follows:
    
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>579</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#198</fr:addr><fr:route>unstable-198.xml</fr:route><fr:parent>150-003I</fr:parent></fr:frontmatter><fr:mainmatter>
      We show that <fr:tex>W(d) = 2^{d + 1} - 2</fr:tex> by induction on <fr:tex>d</fr:tex>.
      <fr:ol><fr:li>
          Case <fr:tex>0</fr:tex>:
          <fr:tex
display="block">             \begin {aligned}               W(0)                 &amp;= 0 \\                 &amp;= 2^1 - 2             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Case <fr:tex>d + 1</fr:tex>:
          <fr:p><fr:strong>IH:</fr:strong> <fr:tex>W(d) = 2^{d + 1} - 2</fr:tex></fr:p>
          <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>W(d + 1) = 2^{d + 2} - 2</fr:tex></fr:p>
          <fr:tex
display="block">             \begin {aligned}               W(d + 1)                 &amp;= 2W(d) + 2  &amp;&amp;\text {(definition)} \\                 &amp;= 2(2^{d + 1} - 2) + 2 &amp;&amp;\text {(IH)} \\                 &amp;= 2^{d + 2} - 2 &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex></fr:li></fr:ol>
      This completes the proof.
    </fr:mainmatter></fr:tree>
 

    Alternatively, we can just cite the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, where <fr:tex>c_0 = 0</fr:tex> and <fr:tex>c_1 = 2</fr:tex>.
  </fr:li>
  <fr:li>So, <fr:tex>W(d) \in  \mathcal {O}(2^d)</fr:tex>.</fr:li></fr:ol><fr:p>Intuitively, this makes sense: in a balanced tree of depth <fr:tex>d</fr:tex>, there are <fr:tex>\mathcal {O}(2^d)</fr:tex> nodes, and we do a constant amount of work at each node.</fr:p><fr:p>We can also analyze in terms of the number of nodes, <fr:tex>n = 2^d-1</fr:tex>:</fr:p><fr:ol><fr:li>
    First, we write the recurrence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(2n + 1) &amp;= W(n) + W(n) + 2 \\                   &amp;= 2W(n) + 2       \end {aligned}     </fr:tex>
    We only give cases for <fr:tex>0</fr:tex> and <fr:tex>2n + 1</fr:tex> since the tree is balanced.
  </fr:li>
  <fr:li>
    To guess a cost bound, we use the <fr:link
href="150-003H.xml"
type="local"
addr="150-003H">tree method</fr:link>.
    
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
      

      
        
  <html:tr>
  <html:td><fr:tex>L</fr:tex></html:td>

  <html:td><fr:tex>\log _2(n + 1)</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>n_i</fr:tex></html:td>

  <html:td><fr:tex>2^i</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>w_i</fr:tex></html:td>

  <html:td><fr:tex>2</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>e</fr:tex></html:td>

  <html:td><fr:tex>n+1</fr:tex></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:tex>b</fr:tex></html:td>

  <html:td><fr:tex>0</fr:tex></html:td>
</html:tr>

      
    </html:table>

    So, we guess
    <fr:tex
display="block">       \begin {aligned}         \sum _{i = 0}^{\log _2(n + 1) - 1} 2 \cdot  2^i           &amp;= 2 \cdot  \sum _{i = 0}^{\log _2(n + 1) - 1} 2^i \\           &amp;= 2 \cdot  (2^{\log _2(n + 1)} - 1) \\           &amp;= 2 \cdot  ((n + 1) - 1) \\           &amp;= 2n       \end {aligned}     </fr:tex>
    using the <fr:link
href="150-003J.xml"
type="local"
addr="150-003J">table of common summations</fr:link>.
    We prove it as follows:
    
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>596</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#197</fr:addr><fr:route>unstable-197.xml</fr:route><fr:parent>150-003I</fr:parent></fr:frontmatter><fr:mainmatter>
      We show that <fr:tex>W(n) = 2n</fr:tex> by induction on <fr:tex>n</fr:tex>, where we assume <fr:tex>n</fr:tex> is either <fr:tex>n</fr:tex> or <fr:tex>2n' + 1</fr:tex> by the balance assumption.
      <fr:ol><fr:li>
          Case <fr:tex>0</fr:tex>:
          <fr:tex
display="block">             \begin {aligned}               W(0)                 &amp;= 0 \\                 &amp;= 2 \cdot  0             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Case <fr:tex>2n + 1</fr:tex>:
          <fr:p><fr:strong>IH:</fr:strong> <fr:tex>W(n) = 2n</fr:tex>
          <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>W(2n + 1) = 4n + 2</fr:tex></fr:p>
          <fr:tex
display="block">             \begin {aligned}               W(2n + 1)                 &amp;= 2W(n) + 2  &amp;&amp;\text {(definition)} \\                 &amp;= 2(2n) + 2 &amp;&amp;\text {(IH)} \\                 &amp;= 4n + 2 &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex></fr:p></fr:li>
      This completes the proof.
    </fr:ol>
    Alternatively, we can just cite the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link> if we define <fr:tex>W(n) = W'(\log _2(n + 1))</fr:tex>, where <fr:tex>W'</fr:tex> is the recurrence in terms of depth (still letting <fr:tex>c_0 = 0</fr:tex> and <fr:tex>c_1 = 2</fr:tex>).
    </fr:mainmatter></fr:tree></fr:li>
  <fr:li>So, <fr:tex>W(n) \in  \mathcal {O}(n)</fr:tex>.</fr:li></fr:ol><fr:p>Intuitively, this also makes sense: we have a tree with <fr:tex>n</fr:tex> nodes and we do a constant amount of work at each node.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>605</fr:anchor><fr:addr>150-0030</fr:addr><fr:route>150-0030.xml</fr:route><fr:title>Parallelism</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>599</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003K</fr:addr><fr:route>150-003K.xml</fr:route><fr:title>Work and span</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:strong>Work:</fr:strong> the cost of evaluating an expression sequentially.</fr:li>
  <fr:li><fr:strong>Span:</fr:strong> the cost of evaluating an expression in parallel, assuming unlimited parallel processors.</fr:li></fr:ul><fr:p>In reality, given finite parallel processors, the cost will be between the work and the span.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>600</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-003L</fr:addr><fr:route>150-003L.xml</fr:route><fr:title>Dependence and independence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Note that unlimited parallel processors does <fr:em>not</fr:em> mean that span is always trivial.</fr:p><fr:ul><fr:li>To put on two socks, parallelism helps: with enough hands, they can be put on simultaneously.</fr:li>
  <fr:li>To put on one sock and one shoe, parallelism does not help: no matter how many hands are willing to help, the sock has to be put on before the shoe.</fr:li>
  <fr:li>To put on <fr:tex>n</fr:tex> socks and <fr:tex>n</fr:tex> shoes, parallelism helps partially: all of the socks can be put on in parallel, and then all of the shoes can be put on in parallel.</fr:li></fr:ul><fr:p>Independent tasks can be evaluated in parallel, but dependent tasks have to be evaluated sequentially.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>601</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003M</fr:addr><fr:route>150-003M.xml</fr:route><fr:title>Parallel evaluation of tuples</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In Standard ML, we can evaluate components of a tuple in parallel.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>602</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003N</fr:addr><fr:route>150-003N.xml</fr:route><fr:title>Parallel evaluation of sample expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We demonstrate <fr:link
href="150-003M.xml"
type="local"
addr="150-003M">parallel evaluation of tuples</fr:link>. In parallel:</fr:p><fr:tex
display="block">   \begin {aligned}     (((1 + 1) + 1) + 1, (1 + 1) + 1)       &amp;\Longrightarrow ^{1} ((2 + 1) + 1, 2 + 1) \\       &amp;\Longrightarrow ^{1} (3 + 1, 3) \\       &amp;\Longrightarrow ^{1} (4, 3)   \end {aligned} </fr:tex><fr:p>Notice that the cost of evaluating the tuple is the <fr:em>maximum</fr:em> of both components, since we wait for both components to compute.</fr:p><fr:p>Binary infix operations evaluate in parallel, as well, since they are syntactic sugar for tuples. For example, <fr:code>e1 + e2</fr:code> is syntactic sugar for <fr:code>(op +) (e1, e2)</fr:code>. Re-parenthesizing:</fr:p><fr:tex
display="block">   \begin {aligned}     ((1 + 1) + (1 + 1), 1 + 1 + 1)       &amp;\Longrightarrow ^{1} (2 + 2, 2 + 1) \\       &amp;\Longrightarrow ^{1} (4, 3)   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>603</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003O</fr:addr><fr:route>150-003O.xml</fr:route><fr:title>Tree sum span analysis, assuming spine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link> and the <fr:link
href="150-003G.xml"
type="local"
addr="150-003G">tree sum work analysis, assuming spine</fr:link>. We repeat this analysis but assuming parallelism.</fr:p><fr:ol><fr:li>
    First, we write the recurrence:
    <fr:tex
display="block">       \begin {aligned}         S(0) &amp;= 0 \\         S(n) &amp;= \max (S(n - 1), S(0)) + 2 \\              &amp;= \max (S(n - 1), 0) + 2 \\              &amp;= S(n - 1) + 2       \end {aligned}     </fr:tex></fr:li>
  <fr:li>By <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">the table</fr:link> (or unrolling and induction), we have that <fr:tex>S(n) = 2n</fr:tex>.</fr:li>
  <fr:li>So, <fr:tex>S(n) \in  \mathcal {O}(n)</fr:tex>.</fr:li></fr:ol><fr:p>Notice that this is exactly the same as the work: there are no opportunities for parallelism, since the tree is a spine and must be traversed in order (like a list).</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>604</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003P</fr:addr><fr:route>150-003P.xml</fr:route><fr:title>Tree sum span analysis, assuming balanced tree</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We now analyze the span of <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link> in terms of the depth <fr:tex>d</fr:tex> of the tree, assuming the tree is balanced. We follow <fr:link
href="150-0031.xml"
type="local"
addr="150-0031">the template</fr:link>:</fr:p><fr:ol><fr:li>
    First, we write the recurrence:
    <fr:tex
display="block">       \begin {aligned}         S(0) &amp;= 0 \\         S(d) &amp;= \max (S(d - 1), S(d - 1)) + 2 \\              &amp;= S(d - 1) + 2       \end {aligned}     </fr:tex>
    We take the maximum of the recursive calls: they are executed in parallel since they are added, and <fr:link
href="150-003M.xml"
type="local"
addr="150-003M">tuples are evaluated in parallel</fr:link>.
  </fr:li>
  <fr:li>By the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, <fr:tex>S(d) = 2d</fr:tex>.
  </fr:li>
  <fr:li>So, <fr:tex>S(d) \in  \mathcal {O}(d)</fr:tex>.</fr:li></fr:ol><fr:p>Intuitively, this makes sense: in a balanced tree of depth <fr:tex>d</fr:tex>, we have <fr:tex>d</fr:tex> span, since both subtrees can be evaluated in parallel.</fr:p><fr:p>We can also analyze in terms of the number of nodes, <fr:tex>n = 2^d-1</fr:tex>:</fr:p><fr:ol><fr:li>
    First, we write the recurrence:
    <fr:tex
display="block">       \begin {aligned}         S(0) &amp;= 0 \\         S(2n + 1) &amp;= \max (S(n), S(n)) + 2 \\                   &amp;= S(n) + 2       \end {aligned}     </fr:tex>
    We only give cases for <fr:tex>0</fr:tex> and <fr:tex>2n + 1</fr:tex> since the tree is balanced.
    We take the maximum of the recursive calls: they are executed in parallel since they are added, and <fr:link
href="150-003M.xml"
type="local"
addr="150-003M">tuples are evaluated in parallel</fr:link>.
  </fr:li>
  <fr:li>By the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, <fr:tex>S(n) = 2\log _2(n+1)</fr:tex>.</fr:li>
  <fr:li>So, <fr:tex>S(n) \in  \mathcal {O}(\log  n)</fr:tex>.</fr:li></fr:ol><fr:p>Intuitively, this also makes sense: we have a tree with <fr:tex>n</fr:tex> nodes and we do a constant amount of work at each node, and the depth of the tree is <fr:tex>\mathcal {O}(\log  n)</fr:tex> since the tree is balanced.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>638</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect07</fr:addr><fr:route>150-lect07.xml</fr:route><fr:title>Sequential and parallel sorting</fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>4</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:p>Expanding on our discussion of <fr:link
href="150-lect06.xml"
type="local"
addr="150-lect06">cost analysis</fr:link>, we consider sequential and parallel sorting algorithms as a case study.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>618</fr:anchor><fr:addr>150-004D</fr:addr><fr:route>150-004D.xml</fr:route><fr:title>Sorting specification</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>614</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004E</fr:addr><fr:route>150-004E.xml</fr:route><fr:title><fr:code>order</fr:code> datatype</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following datatype is built into the standard library of Standard ML:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype order = LESS | EQUAL | GREATER
</html:code></fr:pre><fr:p>As the constructor names indicate, these constructors indicate the result of a comparison of elements in a <fr:link
href="https://en.wikipedia.org/wiki/Law_of_trichotomy"
type="external">trichotomous relation</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>616</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004F</fr:addr><fr:route>150-004F.xml</fr:route><fr:title><fr:code>int</fr:code> comparison</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The built-in function <fr:code>Int.compare : int * int -&gt; order</fr:code> compares two integers. We often think of this function as the primitive notion of comparison. For example, we think of <fr:code>op &lt;=</fr:code> implemented as:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (x : int) &lt;= (y : int) : bool =
  case Int.compare (x, y) of
    LESS    =&gt; true
  | EQUAL   =&gt; true
  | GREATER =&gt; false
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>617</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-004I</fr:addr><fr:route>150-004I.xml</fr:route><fr:title>Sorting algorithm specification</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The result of sorting <fr:code>l : int list</fr:code> should be:</fr:p><fr:ol><fr:li>Sorted (nondecreasing/weakly ascending) according to <fr:link
href="150-004F.xml"
type="local"
addr="150-004F"><fr:code>Int.compare</fr:code></fr:link>.</fr:li>
  <fr:li>A permutation of <fr:code>l</fr:code>.</fr:li></fr:ol><fr:p>For cost, we count the number of comparisons performed.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>625</fr:anchor><fr:addr>150-004G</fr:addr><fr:route>150-004G.xml</fr:route><fr:title>Insertion sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Insertion sort works by inserting each element into a list in sorted order, one at a time.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>620</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004J</fr:addr><fr:route>150-004J.xml</fr:route><fr:title>Insert auxiliary function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>insert</fr:code> function adds a single element into a sorted list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* insert : int * int list -&gt; int list
 * REQUIRES: l is sorted
 * ENSURES: insert (x, l) is a sorted permutation of x :: l
 *)
fun insert (x, nil) = [x]
  | insert (x, y :: ys) =
      case Int.compare (x, y) of
        GREATER =&gt; y :: insert (x, ys)
      | _       =&gt; x :: y :: ys
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>622</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-004K</fr:addr><fr:route>150-004K.xml</fr:route><fr:title>Insertion sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Iterating <fr:link
href="150-004J.xml"
type="local"
addr="150-004J"><fr:code>insert</fr:code></fr:link>, we may sort a list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* isort : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: isort l is a sorted permutation of l
 *)
fun isort nil = nil
  | isort (x :: xs) = insert (x, isort xs)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>623</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004L</fr:addr><fr:route>150-004L.xml</fr:route><fr:title>Cost analysis of insertion</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the cost of <fr:link
href="150-004J.xml"
type="local"
addr="150-004J"><fr:code>insert</fr:code></fr:link> as follows:</fr:p><fr:ol><fr:li>
    First, we give the recurence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(n)           &amp;= 1 + \max (W(n - 1), 0) \\           &amp;= W(n - 1) + 1       \end {aligned}     </fr:tex>
    Here, we take the maximum of both branches of the <fr:code>case</fr:code> expression to get an upper bound.
  </fr:li>
  <fr:li>
    By the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, we get that <fr:tex>W(n) = n</fr:tex>.
  </fr:li>
  <fr:li>
    By reflexivity, <fr:tex>W(n) \in  \mathcal {O}(n)</fr:tex>.
  </fr:li></fr:ol><fr:p>There are no opportunities for parallelism, so the span is the same.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>624</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004M</fr:addr><fr:route>150-004M.xml</fr:route><fr:title>Cost analysis of insertion sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the cost of <fr:link
href="150-004K.xml"
type="local"
addr="150-004K"><fr:code>isort</fr:code></fr:link> as follows:</fr:p><fr:ol><fr:li>
    First, we give the recurence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(n)           &amp;= W(n - 1) + W_\texttt {insert}(n - 1)           &amp;= W(n - 1) + n - 1       \end {aligned}     </fr:tex>
    We get <fr:tex>W_\texttt {insert}(n - 1)</fr:tex> from the call to <fr:code>insert</fr:code> on a list of length <fr:tex>n - 1</fr:tex>; we know <fr:code>isort xs</fr:code> has length <fr:tex>n - 1</fr:tex> since <fr:code>isort xs</fr:code> is a permutation of <fr:code>xs</fr:code>.
  </fr:li>
  <fr:li>
    By the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, we get that <fr:tex>W(n) = \frac {n(n-1)}{2}</fr:tex>.
  </fr:li>
  <fr:li>
    So, <fr:tex>W(n) \in  \mathcal {O}(n^2)</fr:tex>.
  </fr:li></fr:ol><fr:p>There are no opportunities for parallelism, so the span is the same.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>637</fr:anchor><fr:addr>150-004H</fr:addr><fr:route>150-004H.xml</fr:route><fr:title>Merge sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Merge sort works by splitting a list in half, sorting the halves, and combining the sorted results.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>627</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004N</fr:addr><fr:route>150-004N.xml</fr:route><fr:title>Split auxiliary function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>split</fr:code> function splits a list into two halves.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* split : int list -&gt; int list * int list
 * REQUIRES: true
 * ENSURES: split l ==&gt; (l1, l2), where
 *   - l1 @ l2 is a permutation of l
 *   - length l1 = length l div 2  (rounding down)
 *)
fun split nil = (nil, nil)
  | split [x] = (nil, [x])
  | split (x1 :: x2 :: xs) =
      let
        val (xs1, xs2) = split xs
      in
        (x1 :: xs1, x2 :: xs2)
      end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>629</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004O</fr:addr><fr:route>150-004O.xml</fr:route><fr:title>Merge auxiliary function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>merge</fr:code> function combines two sorted lists to produce a larger sorted list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* merge : int list * int list -&gt; int list
 * REQUIRES: l1, l2 are sorted
 * ENSURES: merge (l1, l2) ==&gt; l, where l is a sorted permutation of l1 @ l2
 *)
fun merge (nil, l2) = l2
  | merge (l1, nil) = l1
  | merge (x :: xs, y :: ys) =
      case Int.compare (x, y) of
        LESS    =&gt; x :: merge (xs, y :: ys)
      | GREATER =&gt; y :: merge (x :: xs, ys)
      | EQUAL   =&gt; x :: y :: merge (xs, ys)
</html:code></fr:pre><fr:p>Notice that <fr:code>merge</fr:code> does <fr:em>not</fr:em> go by structural recursion on <fr:code>l1</fr:code> or <fr:code>l2</fr:code>; in some recursive calls one shrinks, and in some the other shrinks. Rather, it goes by induction on the sum of their lengths, which always shrinks.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>631</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-004P</fr:addr><fr:route>150-004P.xml</fr:route><fr:title>Merge sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>By splitting a list in halves, recursively sorting the halves, and merging the sorted results back together, we may sort a list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* msort : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: msort l ==&gt; l', where l' is a sorted permutation of l
 *)
fun msort nil = nil
  | msort [x] = [x]
  | msort l =
      let
        val (l1, l2) = split l
        val (l1', l2') = (msort l1', msort l2')
      in
        merge (l1', l2')
      end
</html:code></fr:pre><fr:p>Notice that <fr:code>msort</fr:code> does <fr:em>not</fr:em> go by structural recursion on <fr:code>l</fr:code>; we make recursive calls <fr:code>msort l1'</fr:code> and <fr:code>msort l2'</fr:code> to two lists that are not structural subcomponents of <fr:code>l</fr:code>. However, by the guarantees of the <fr:link
href="150-004N.xml"
type="local"
addr="150-004N">split auxiliary function</fr:link>, we know the lengths of <fr:code>l1'</fr:code> and <fr:code>l2'</fr:code> are smaller than the length of <fr:code>l</fr:code>. Thus, <fr:code>msort</fr:code> goes by recursion on the length of <fr:code>l</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>632</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004Q</fr:addr><fr:route>150-004Q.xml</fr:route><fr:title>Cost analysis of split</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the cost of <fr:link
href="150-004N.xml"
type="local"
addr="150-004N"><fr:code>split</fr:code></fr:link> as follows:</fr:p><fr:ol><fr:li>
    First, we give the recurence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(1) &amp;= 0 \\         W(n) &amp;= W(n - 2)       \end {aligned}     </fr:tex>
    <fr:p>We never incur cost according to the <fr:link
href="150-004I.xml"
type="local"
addr="150-004I">cost model</fr:link> that counts comparisons, since we never use <fr:code>Int.compare</fr:code>.</fr:p></fr:li>
  <fr:li>
    By the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, we get that <fr:tex>W(n) = 0</fr:tex>.
  </fr:li>
  <fr:li>
    By reflexivity, <fr:tex>W(n) \in  \mathcal {O}(0)</fr:tex>.
  </fr:li></fr:ol><fr:p>There are no opportunities for parallelism, so the span is the same.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>633</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004R</fr:addr><fr:route>150-004R.xml</fr:route><fr:title>Cost analysis of merge</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the cost of <fr:link
href="150-004O.xml"
type="local"
addr="150-004O"><fr:code>merge</fr:code></fr:link> in terms of the <fr:em>sum of the lengths of the inputs</fr:em>, <fr:tex>s</fr:tex>, since that is what the implementation goes by recursion on.</fr:p><fr:ol><fr:li>
    First, we give the recurence:
    <fr:tex
display="block">       \begin {aligned}         W(0) &amp;= 0 \\         W(s)           &amp;= \max (0, 0, 1 + \max (W(s - 1), W(s - 1), W(s - 2))) \\           &amp;= 1 + W(s - 1)       \end {aligned}     </fr:tex></fr:li>
  <fr:li>
    By the <fr:link
href="150-003E.xml"
type="local"
addr="150-003E">table of common recurrences</fr:link>, we get that <fr:tex>W(s) = s</fr:tex>.
  </fr:li>
  <fr:li>
    By reflexivity, <fr:tex>W(s) \in  \mathcal {O}(s)</fr:tex>.
  </fr:li></fr:ol><fr:p>There are no opportunities for parallelism, so the span is the same.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>636</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004S</fr:addr><fr:route>150-004S.xml</fr:route><fr:title>Cost analysis of merge sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the cost of <fr:link
href="150-004P.xml"
type="local"
addr="150-004P"><fr:code>msort</fr:code></fr:link> as follows, assuming the length of the input list is a power of two for simplicity:</fr:p><fr:ol><fr:li>
    First, we give the recurence:
    <fr:tex
display="block">       \begin {aligned}         W(1) &amp;= 0 \\         W(n)           &amp;= W_\texttt {split}(n) + (W(n / 2) + W(n / 2)) + W_\texttt {merge}(n / 2 + n /2) \\           &amp;= 2W(n / 2) + n       \end {aligned}     </fr:tex>
    <fr:p>In the inductive case, note that both <fr:code>l1'</fr:code> and <fr:code>l2'</fr:code> have length <fr:tex>n / 2</fr:tex> since <fr:code>msort</fr:code> always computes a permutation and <fr:code>l1</fr:code> and <fr:code>l2</fr:code> have length <fr:tex>n / 2</fr:tex>.</fr:p></fr:li>
  <fr:li>
    By the tree method, we guess that <fr:tex>W(n) = n \log _2(n)</fr:tex>.
    We prove it as follows:
    
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>634</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#190</fr:addr><fr:route>unstable-190.xml</fr:route><fr:parent>150-004S</fr:parent></fr:frontmatter><fr:mainmatter>
      We show that <fr:tex>W(n) = n \log _2(n)</fr:tex> by induction.
      <fr:ol><fr:li>
          Case <fr:tex>1</fr:tex>:
          <fr:tex
display="block">             \begin {aligned}               W(1)                 &amp;= 0 \\                 &amp;= 1 \log _2(0)             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Case <fr:tex>2n</fr:tex>:
          <fr:p><fr:strong>IH:</fr:strong> <fr:tex>W(n) = n\log _2(n)</fr:tex></fr:p>
          <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>W(2n) = 2n\log _2(n)</fr:tex></fr:p>
          <fr:tex
display="block">             \begin {aligned}               W(2n)                 &amp;= 2W(n) + 2n  &amp;&amp;\text {(definition)} \\                 &amp;= 2(n\log _2(n)) + 2n &amp;&amp;\text {(IH)} \\                 &amp;= 2n(\log _2(n) + 1) &amp;&amp;\text {(math)} \\                 &amp;= 2n(\log _2(2n)) &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex></fr:li></fr:ol>
      This completes the proof.
    </fr:mainmatter></fr:tree></fr:li>
  <fr:li>
    So, <fr:tex>W(n) \in  \mathcal {O}(n\log _2(n)) = \mathcal {O}(n\log  n)</fr:tex>.
  </fr:li></fr:ol><fr:p>Since the recursive calls are made in a tuple, <fr:link
href="150-003N.xml"
type="local"
addr="150-003N">they are evaluated in parallel</fr:link>. Thus, we analyze the span of <fr:code>msort</fr:code> separately.</fr:p><fr:ol><fr:li>
    First, we give the recurence:
    <fr:tex
display="block">       \begin {aligned}         S(1) &amp;= 0 \\         S(n)           &amp;= S_\texttt {split}(n) + \max (S(n / 2), S(n / 2)) + S_\texttt {merge}(n / 2 + n /2) \\           &amp;= S(n / 2) + n       \end {aligned}     </fr:tex></fr:li>
  <fr:li>
    By unrolling, we notice that
    <fr:tex
display="block">       \begin {aligned}         S(n)           &amp;= n + \frac {n}{2} + \frac {n}{4} + \cdots  4 + 2 + 0 \\           &amp;= 2\left (\frac {n}{2} + \frac {n}{4} + \cdots  + 2 + 1\right )         \end {aligned}     </fr:tex> so we guess that
    <fr:tex
display="block">       \begin {aligned}         S(n)           &amp;= 2\left (\sum _{i = 0}^{\log _2(n) - 1} 2^i\right ) \\           &amp;= 2(2^{\log _2(n)} - 1) \\           &amp;= 2(n - 1) \\           &amp;= 2n - 2         \end {aligned}     </fr:tex> using the <fr:link
href="150-003J.xml"
type="local"
addr="150-003J">table of common summations</fr:link>.
    We prove it as follows:
    
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>635</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#189</fr:addr><fr:route>unstable-189.xml</fr:route><fr:parent>150-004S</fr:parent></fr:frontmatter><fr:mainmatter>
      We show that <fr:tex>S(n) = 2n - 2</fr:tex> by induction.
      <fr:ol><fr:li>
          Case <fr:tex>1</fr:tex>:
          <fr:tex
display="block">             \begin {aligned}               S(1)                 &amp;= 0 \\                 &amp;= 2\cdot 1 - 2             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Case <fr:tex>2n</fr:tex>:
          <fr:p><fr:strong>IH:</fr:strong> <fr:tex>S(n) = 2n - 2</fr:tex></fr:p>
          <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>S(2n) = 2(2n) - 2</fr:tex></fr:p>
          <fr:tex
display="block">             \begin {aligned}               S(2n)                 &amp;= S(n) + 2n  &amp;&amp;\text {(definition)} \\                 &amp;= 2n - 2 + 2n &amp;&amp;\text {(IH)} \\                 &amp;= 4n - 2 &amp;&amp;\text {(math)} \\                 &amp;= 2(2n) - 2 &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex></fr:li></fr:ol>
      This completes the proof.
    </fr:mainmatter></fr:tree></fr:li>
  <fr:li>
    So, <fr:tex>S(n) \in  \mathcal {O}(n)</fr:tex>.
  </fr:li></fr:ol><fr:p>
  In the worst case, we found that <fr:link
href="150-004M.xml"
type="local"
addr="150-004M">insertion sort has work and span <fr:tex>\mathcal {O}(n^2)</fr:tex></fr:link>.
  However, merge sort has worst-case work of only <fr:tex>\mathcal {O}(n \log  n)</fr:tex> and worst-case span of <fr:tex>\mathcal {O}(n)</fr:tex>, which is a substantial improvement.
</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>777</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect08</fr:addr><fr:route>150-lect08.xml</fr:route><fr:title>Polymorphism and parameterized datatypes</fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>6</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by analogous lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link> and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>655</fr:anchor><fr:addr>150-004Y</fr:addr><fr:route>150-004Y.xml</fr:route><fr:title>Type inference</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>646</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004U</fr:addr><fr:route>150-004U.xml</fr:route><fr:title>Basic type inference</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When a certain type is required within a program, Standard ML will infer this constraint. For example, all of the following declarations are equivalent and have type <fr:code>int -&gt; int * bool</fr:code>, since the use of <fr:code>x</fr:code> in the expression <fr:code>x + 1</fr:code> forces <fr:code>x</fr:code> to have type <fr:code>int</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (x : int) : int * bool = (x + 1, true)
fun f (x : int) = (x + 1, true)
fun f x : int * bool = (x + 1, true)
fun f x = (x + 1, true)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>647</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004V</fr:addr><fr:route>150-004V.xml</fr:route><fr:title>Contradiction in type inference</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If a variable is used in such a way that it has two incompatible types, a type error will be produced.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>649</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004W</fr:addr><fr:route>150-004W.xml</fr:route><fr:title>Contradictory base types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following code does not typecheck, since <fr:code>x</fr:code> is used as both an <fr:code>int</fr:code> and as a <fr:code>string</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f x = (x + 1, x ^ "!")
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>651</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-004X</fr:addr><fr:route>150-004X.xml</fr:route><fr:title>Contradictory patterns</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following code does not typecheck, since the input is matched as both an <fr:code>int</fr:code> and a tuple:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f 0 = 0
  | f (x, y) = 1
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>654</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0059</fr:addr><fr:route>150-0059.xml</fr:route><fr:title>Circularity error</fr:title></fr:frontmatter><fr:mainmatter><fr:p>With recursion, sometimes there is no valid type for an expression because the output type contains itself as a component. For example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f 0 = 0
  | f n = (f (n - 1), 0)
</html:code></fr:pre><fr:p>This function is not well typed.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>653</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#188</fr:addr><fr:route>unstable-188.xml</fr:route><fr:parent>150-0059</fr:parent></fr:frontmatter><fr:mainmatter>
  Assume <fr:code>f : int -&gt; t</fr:code>, for some <fr:code>t</fr:code>.
  Then, in the second clause, <fr:code>(f (n - 1), 0) : t * int</fr:code>.
  However, since this is returned by <fr:code>f</fr:code> itself, this would mean that <fr:code>t = t * int</fr:code>, leading to a contradiction.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>754</fr:anchor><fr:addr>150-004Z</fr:addr><fr:route>150-004Z.xml</fr:route><fr:title>Polymorphism</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>681</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004T</fr:addr><fr:route>150-004T.xml</fr:route><fr:title>Type variable</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>type variable</fr:em> stands for an arbitrary type, denoted by an <fr:code>'</fr:code> followed by a variable name. We pronounce type variables as Greek letters:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>SML Syntax</html:th>

  <html:th>Greek Letter</html:th>

  <html:th>Pronunciation</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:code>'a</fr:code></html:td>

  <html:td><fr:tex>\alpha </fr:tex></html:td>

  <html:td>alpha</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'b</fr:code></html:td>

  <html:td><fr:tex>\beta </fr:tex></html:td>

  <html:td>beta</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'c</fr:code></html:td>

  <html:td><fr:tex>\gamma </fr:tex></html:td>

  <html:td>gamma</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'d</fr:code></html:td>

  <html:td><fr:tex>\delta </fr:tex></html:td>

  <html:td>delta</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>'e</fr:code></html:td>

  <html:td><fr:tex>\epsilon </fr:tex></html:td>

  <html:td>epsilon</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>685</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0052</fr:addr><fr:route>150-0052.xml</fr:route><fr:title>First function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fst (x : int, y : string) : int = x
</html:code></fr:pre><fr:p>We can remove the type annotations:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fst (x, y) = x
</html:code></fr:pre><fr:p>Nothing restricts the type of <fr:code>x</fr:code> or <fr:code>y</fr:code>, and the result type is whatever the type of <fr:code>x</fr:code> was. Therefore, this declaration of <fr:code>fst</fr:code> has type <fr:code>'a * 'b -&gt; 'a</fr:code>. We can optionally include explicit annotations:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fst (x : 'a, y : 'b) : 'a = x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>686</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0057</fr:addr><fr:route>150-0057.xml</fr:route><fr:title>Most general type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:em>most general type</fr:em> of an expression <fr:code>e</fr:code> is the type <fr:code>t</fr:code> such that all other types <fr:code>t'</fr:code> that could be assigned to <fr:code>e</fr:code> can be achieved by plugging in for type variables in <fr:code>t</fr:code>.</fr:p><fr:p>We say that these other types <fr:code>t'</fr:code> are <fr:em>instances of</fr:em> type <fr:code>t</fr:code>.</fr:p><fr:p>When we say that "<fr:code>e</fr:code> has type <fr:code>t</fr:code>", we implicitly mean that <fr:code>e</fr:code> has most general type <fr:code>t</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>687</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0053</fr:addr><fr:route>150-0053.xml</fr:route><fr:title>Type inference algorithm</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To infer the <fr:link
href="150-0057.xml"
type="local"
addr="150-0057">most general type</fr:link> of a function in SML:</fr:p><fr:ol><fr:li>Give each variable, including the function being defined, an arbitrary type variable.</fr:li>
  <fr:li>Add constraints based on the usage of each variable, and add constraints to make sure all clauses have the same type.</fr:li>
  <fr:li>Solve the constraints.</fr:li>
  <fr:li>Optionally, re-letter the type variables in the answer for convenience.</fr:li></fr:ol><fr:p>For simple functions, this process often occurs implicitly in one's head.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>708</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0054</fr:addr><fr:route>150-0054.xml</fr:route><fr:title>Type inference of a simple function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We formally perform type inference on <fr:link
href="150-0052.xml"
type="local"
addr="150-0052">the <fr:code>fst</fr:code> function</fr:link>.</fr:p><fr:ol><fr:li>
    We give each variable an arbitrary type:
    
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
      

      
        
  <html:tr>
  <html:td><fr:code>fst</fr:code></html:td>

  <html:td><fr:code>'a</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>x</fr:code></html:td>

  <html:td><fr:code>'b</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>y</fr:code></html:td>

  <html:td><fr:code>'c</fr:code></html:td>
</html:tr>

      
    </html:table></fr:li>
  <fr:li>
    We generate constraints:
    <fr:ul><fr:li>Since <fr:code>fst</fr:code> is a function, we must have <fr:code>'a = 'd -&gt; 'e</fr:code>.</fr:li>
      <fr:li>Since <fr:code>fst</fr:code> matches on <fr:code>(x, y)</fr:code>, we must have <fr:code>'d = 'b * 'c</fr:code>.</fr:li>
      <fr:li>Since <fr:code>fst</fr:code> returns <fr:code>x</fr:code>, we must have <fr:code>'b = 'e</fr:code>.</fr:li></fr:ul></fr:li>
  <fr:li>
    We solve the constraints to get:
    
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
      

      
        
  <html:tr>
  <html:td><fr:code>fst</fr:code></html:td>

  <html:td><fr:code>'e * 'c -&gt; 'e</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>x</fr:code></html:td>

  <html:td><fr:code>'e</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>y</fr:code></html:td>

  <html:td><fr:code>'c</fr:code></html:td>
</html:tr>

      
    </html:table></fr:li>
  <fr:li>
    We re-letter to get <fr:code>fst : 'a * 'b -&gt; 'a</fr:code>.
  </fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>748</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0055</fr:addr><fr:route>150-0055.xml</fr:route><fr:title>Type inference of a complicated function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We formally perform type inference on the following function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f (a, b, c, d) =
  case a of
    nil    =&gt; (b + 1, c)
  | e :: _ =&gt; (d    , e)
</html:code></fr:pre><fr:ol><fr:li>
    We give each variable an arbitrary type:
    
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
      

      
        
  <html:tr>
  <html:td><fr:code>a</fr:code></html:td>

  <html:td><fr:code>'a</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>b</fr:code></html:td>

  <html:td><fr:code>'b</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>c</fr:code></html:td>

  <html:td><fr:code>'c</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>d</fr:code></html:td>

  <html:td><fr:code>'d</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>e</fr:code></html:td>

  <html:td><fr:code>'e</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>f</fr:code></html:td>

  <html:td><fr:code>'f</fr:code></html:td>
</html:tr>

      
    </html:table></fr:li>
  <fr:li>
    We generate constraints:
    <fr:ul><fr:li>Since <fr:code>f</fr:code> is a function, we must have <fr:code>'f = 'g -&gt; 'h</fr:code>.</fr:li>
      <fr:li>Since <fr:code>f</fr:code> matches on <fr:code>(a, b, c, d)</fr:code>, we must have <fr:code>'g = 'a * 'b * 'c * 'd</fr:code>.</fr:li>
      <fr:li>Since we match <fr:code>a</fr:code> against list patterns, we must have <fr:code>'a = 'i list</fr:code>.</fr:li>
      <fr:li>Since <fr:code>e :: _</fr:code> is a pattern for <fr:code>'i list</fr:code>, we must have <fr:code>'e = 'i</fr:code>.</fr:li>
      <fr:li>Since we use <fr:code>b + 1</fr:code>, we must have <fr:code>'b = int</fr:code>.</fr:li>
      <fr:li>Since the branches return <fr:code>(b + 1, c)</fr:code> and <fr:code>(d, e)</fr:code>, we must have <fr:code>'h = int * 'c = 'd * 'e</fr:code>.</fr:li></fr:ul></fr:li>
  <fr:li>
    We solve the constraints to get:
    
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
      

      
        
  <html:tr>
  <html:td><fr:code>a</fr:code></html:td>

  <html:td><fr:code>'i list</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>b</fr:code></html:td>

  <html:td><fr:code>int</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>c</fr:code></html:td>

  <html:td><fr:code>'i</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>d</fr:code></html:td>

  <html:td><fr:code>int</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>e</fr:code></html:td>

  <html:td><fr:code>'i</fr:code></html:td>
</html:tr>

      
      
        
  <html:tr>
  <html:td><fr:code>f</fr:code></html:td>

  <html:td><fr:code>'i list * int * 'i * int -&gt; int * 'i</fr:code></html:td>
</html:tr>

      
    </html:table></fr:li>
  <fr:li>
    We re-letter to get <fr:code>f : 'a list * int * 'a * int -&gt; int * 'a</fr:code>.
  </fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>750</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0056</fr:addr><fr:route>150-0056.xml</fr:route><fr:title>Intuitive examples of type inference</fr:title></fr:frontmatter><fr:mainmatter><fr:p>By inspection, we infer the following most general types:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* id : 'a -&gt; 'a *)
fun id x = x

(* two : 'a -&gt; 'a * 'a *)
fun two x = (x, x)

(* f : 'a -&gt; 'b list *)
fun f _ = nil

(* f : int list -&gt; int list *)
fun f [0] = nil
  | f l   = l

(* f : bool * 'a * 'a -&gt; 'a * 'a *)
fun f (b, x, y) =
  if b
    then (x, y)
    else (y, x)

(* length : 'a list -&gt; int *)
fun length nil       = 0
  | length (_ :: xs) = 1 + length xs

(* op @ : 'a list * 'a list -&gt; 'a list *)
fun nil       @ l2 = l2
  | (x :: xs) @ l2 = x :: (xs @ l2)

(* zip : 'a list * 'b list -&gt; ('a * 'b) list *)
fun zip (nil    , _      ) = nil
  | zip (_      , nil    ) = nil
  | zip (x :: xs, y :: ys) = (x, y) :: zip (xs, ys)

(* zip' : 'a list * 'a list -&gt; ('a * 'a) list *)
fun zip' (nil    , _      ) = nil
  | zip' (_      , nil    ) = nil
  | zip' (x :: xs, y :: ys) = (x, y) :: zip' (ys, xs)  (* note (ys, xs), not (xs, ys) *)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>751</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005A</fr:addr><fr:route>150-005A.xml</fr:route><fr:title>Polymorphic quantification in proofs</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When proving a fact about polymorphic functions, we must be careful with quantification.</fr:p><fr:ul><fr:li>❌ If we say "for all <fr:code>l : 'a list</fr:code>, we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>", this means "for all <fr:code>l</fr:code> such that (for all types <fr:code>t</fr:code>, <fr:code>l : t list</fr:code>), we have we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>". However, the only list <fr:code>l</fr:code> satisfying "for all types <fr:code>t</fr:code>, <fr:code>l : t list</fr:code>" is <fr:code>nil</fr:code>.</fr:li>
  <fr:li>✅ If we say "for all types <fr:code>t</fr:code>, for all <fr:code>l : t list</fr:code>, we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>", this generalizes the proof that "for all <fr:code>l : int list</fr:code>, we have <fr:tex>\texttt {rev (rev l)} \cong  \texttt {l}</fr:tex>", replacing <fr:code>int</fr:code> with an arbitrary type <fr:code>t</fr:code>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>753</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-005B</fr:addr><fr:route>150-005B.xml</fr:route><fr:title>Correct polymorphic quantification</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, for all <fr:code>x : t</fr:code>, we have <fr:tex>\texttt {fst (two x)} \cong  \texttt {x}</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>752</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#187</fr:addr><fr:route>unstable-187.xml</fr:route><fr:parent>150-005B</fr:parent></fr:frontmatter><fr:mainmatter>
  Let type <fr:code>t</fr:code> be arbitrary, and let <fr:code>x : t</fr:code> be arbitrary.
  Then:
  <fr:tex
display="block">     \begin {aligned}       &amp;\texttt {fst (two x)} \\       &amp;\cong  \texttt {fst (x, x)} &amp;&amp;\text {(definition of \texttt {two})} \\       &amp;\cong  \texttt {x} &amp;&amp;\text {(definition of \texttt {fst})} \\     \end {aligned}   </fr:tex>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>768</fr:anchor><fr:addr>150-0050</fr:addr><fr:route>150-0050.xml</fr:route><fr:title>Parameterized datatypes</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>758</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005C</fr:addr><fr:route>150-005C.xml</fr:route><fr:title>Parameterized type and datatype declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link> can include type variable parameters:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype ('a, 'b, 'c, ...) t = ...
</html:code></fr:pre><fr:p>In the common case that only one type variable parameter is included, the parentheses and commas are excluded:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a t = ...
</html:code></fr:pre><fr:p>Similarly, <fr:link
href="150-002K.xml"
type="local"
addr="150-002K">type alias declaration</fr:link> can include type variable parameters, too:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type ('a, 'b, 'c, ...) t = ...
type 'a t = ...
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>760</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005D</fr:addr><fr:route>150-005D.xml</fr:route><fr:title>Built-in polymorphic datatypes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Generalizing <fr:link
href="150-002I.xml"
type="local"
addr="150-002I">existing types as <fr:code>datatype</fr:code> declarations</fr:link>, we may include parameters:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a option
  = NONE
  | SOME of 'a

datatype 'a list
  = nil
  | :: of 'a * 'a list
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>762</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005E</fr:addr><fr:route>150-005E.xml</fr:route><fr:title>Polymorphic trees</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Generalizing <fr:link
href="150-002N.xml"
type="local"
addr="150-002N">binary tree with <fr:code>int</fr:code>s at the nodes</fr:link>, we may have a tree storing any element type we wish:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a tree
  = Empty
  | Node of 'a tree * 'a * 'a tree
</html:code></fr:pre><fr:p>To recover the trees of integers, we use <fr:code>int tree</fr:code>. Now, though, we may have <fr:code>string tree</fr:code>, <fr:code>int option tree</fr:code>, <fr:code>int list tree</fr:code>, <fr:code>int tree tree</fr:code>, and more!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>764</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005F</fr:addr><fr:route>150-005F.xml</fr:route><fr:title>Trees with data at the leaves and nodes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If we wish to store <fr:code>'a</fr:code>s at the nodes of a tree but also <fr:code>'b</fr:code>s at the leaves, we may use two type variable parameters:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype ('a, 'b) bush
  = Berry of 'b
  | Brach of ('a, 'b) bush * 'a * ('a, 'b) bush
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>765</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005G</fr:addr><fr:route>150-005G.xml</fr:route><fr:title>Unit type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The type <fr:code>unit</fr:code> has a single value, <fr:code>() : unit</fr:code>, the empty tuple.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>767</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005H</fr:addr><fr:route>150-005H.xml</fr:route><fr:title>Trees from bushes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To recover a type equivalent to <fr:link
href="150-005E.xml"
type="local"
addr="150-005E">polymorphic trees</fr:link> using <fr:link
href="150-005F.xml"
type="local"
addr="150-005F">trees with data at the leaves and nodes</fr:link>, we may define:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type 'a tree = ('a, unit) bush
val Empty : 'a tree = Berry ()
val Node : 'a tree * 'a * 'a tree -&gt; 'a tree = Branch
</html:code></fr:pre><fr:p>We keep <fr:code>'a</fr:code>s at the nodes, bu we choose to include only trivial data of <fr:link
href="150-005G.xml"
type="local"
addr="150-005G">unit type</fr:link> at the leaves, analogous to <fr:code>Empty</fr:code>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>776</fr:anchor><fr:addr>150-0051</fr:addr><fr:route>150-0051.xml</fr:route><fr:title>Polymorphic sorting</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using polymorphism, we may now hope to sort lists containing data of an arbitrary type.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>769</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005I</fr:addr><fr:route>150-005I.xml</fr:route><fr:title>Comparison function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the implementation of the <fr:link
href="150-004J.xml"
type="local"
addr="150-004J">insert auxiliary function</fr:link>, we used <fr:code>Int.compare : int * int -&gt; order</fr:code>. To sort a list of <fr:code>'a</fr:code>s, we need a function of type <fr:code>'a * 'a -&gt; order</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>771</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005J</fr:addr><fr:route>150-005J.xml</fr:route><fr:title>Polymorphic <fr:link
href="150-004J.xml"
type="local"
addr="150-004J">insert auxiliary function</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Assume we have some <fr:code>compare : 'a * 'a -&gt; order</fr:code>. Then, we may implement:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* insert : 'a * 'a list -&gt; 'a list
 * REQUIRES: l is sorted, according to compare
 * ENSURES: insert (x, l) is a sorted permutation of x :: l, according to compare
 *)
fun insert (x, nil) = [x]
  | insert (x, y :: ys) =
      case compare (x, y) of
        GREATER =&gt; y :: insert (x, ys)
      | _       =&gt; x :: y :: ys
</html:code></fr:pre><fr:p>Note that we only replace <fr:code>Int.compare</fr:code> with <fr:code>compare</fr:code>, and we change the specification to say that the list is sorted according to <fr:code>compare</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>773</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005K</fr:addr><fr:route>150-005K.xml</fr:route><fr:title>Polymorphic <fr:link
href="150-004K.xml"
type="local"
addr="150-004K">insertion sort</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>In order to sort some <fr:code>l : 'a list</fr:code>, we must also <fr:em>take in a function</fr:em> <fr:code>compare : 'a * 'a -&gt; order</fr:code> by which we will compare elements of the list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* isort : ('a * 'a -&gt; order) * 'a list -&gt; 'a list
 * REQUIRES: compare is a valid comparison function
 * ENSURES: isort (compare, l) is a sorted permutation of l, according to compare
 *)
fun isort (compare : 'a * 'a -&gt; order, l : 'a list) : 'a list =
  let
    fun insert (x, nil) = [x]
      | insert (x, y :: ys) =
          case compare (x, y) of
            GREATER =&gt; y :: insert (x, ys)
          | _       =&gt; x :: y :: ys

    fun sorter nil = nil
      | sorter (x :: xs) = insert (x, sorter xs)
  in
    sorter l
  end
</html:code></fr:pre><fr:p>We use <fr:link
href="150-005J.xml"
type="local"
addr="150-005J">polymorphic <fr:link
href="150-004J.xml"
type="local"
addr="150-004J">insert auxiliary function</fr:link></fr:link> as an auxiliary function inside the body of <fr:code>isort</fr:code>, once we have access to <fr:code>compare</fr:code>. Here, the logic of <fr:code>sorter</fr:code> is analogous to <fr:code>isort</fr:code> of before, so we conclude by calling <fr:code>sorter l</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>775</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005L</fr:addr><fr:route>150-005L.xml</fr:route><fr:title>Sorting with custom comparison functions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We may use <fr:link
href="150-005K.xml"
type="local"
addr="150-005K">polymorphic <fr:link
href="150-004K.xml"
type="local"
addr="150-004K">insertion sort</fr:link></fr:link> with various choices of comparison functions.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val () =
  Test.int_list
    ( "normal integer sorting"
    , [0, 1, 5]
    , isort (Int.compare, [1, 5, 0])
    )

val () =
  Test.string_list
    ( "normal string sorting"
    , ["alice", "bob", "charlie"]
    , isort (String.compare, ["charlie", "alice", "bob"])
    )


fun intCompareBackwards (x, y) =
  case Int.compare (x, y) of
    LESS    =&gt; GREATER
  | EQUAL   =&gt; EQUAL
  | GREATER =&gt; LESS

val () =
  Test.int_list
    ( "reverse integer sorting"
    , [5, 1, 0]
    , isort (intCompareBackwards, [1, 5, 0])
    )
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>841</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect09</fr:addr><fr:route>150-lect09.xml</fr:route><fr:title>Higher-order functions I: currying and list abstractions</fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>11</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by analogous lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link> and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:p>In this lecture, we begin to take seriously the slogan <fr:strong>functions are values</fr:strong>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>812</fr:anchor><fr:addr>150-005M</fr:addr><fr:route>150-005M.xml</fr:route><fr:title>Currying</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>784</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-005P</fr:addr><fr:route>150-005P.xml</fr:route><fr:title>Higher-order function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>higher-order function</fr:em> is a function that takes a function as input or produces a function as output.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>785</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005R</fr:addr><fr:route>150-005R.xml</fr:route><fr:title>Right-associativity of arrows</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Function types are right-associative. In other words, the type <fr:code>t1 -&gt; t2 -&gt; t3</fr:code> means <fr:code>t1 -&gt; (t2 -&gt; t3)</fr:code>, taking an input of type <fr:code>t1</fr:code> and producing a function of type <fr:code>t2 -&gt; t3</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>786</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005S</fr:addr><fr:route>150-005S.xml</fr:route><fr:title>Left-associativity of function application</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Function application is left-associative. In other words, when <fr:code>f : t1 -&gt; t2 -&gt; t3</fr:code>, <fr:code>e1 : t1</fr:code>, and <fr:code>e2 : t2</fr:code>, the application <fr:code>f e1 e2</fr:code> is the same as <fr:code>(f e1) e2</fr:code>, applying function <fr:code>f</fr:code> to input <fr:code>e1</fr:code>, and then applying that function to <fr:code>e2</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>787</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0068</fr:addr><fr:route>150-0068.xml</fr:route><fr:title>Currying</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a function is <fr:em>curried</fr:em>, named for mathematician <fr:link
href="https://en.wikipedia.org/wiki/Haskell_Curry"
type="external">Haskell Curry</fr:link>, when it takes in multiple arguments one at a time, producing a function accepting the rest of the arguments.</fr:p><fr:p>For example, the type <fr:code>t1 -&gt; t2 -&gt; t3</fr:code> is curried, but the type <fr:code>t1 * t2 -&gt; t3</fr:code> is not (sometimes called "uncurried").</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>790</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005Q</fr:addr><fr:route>150-005Q.xml</fr:route><fr:title>Curried addition</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* add : int * int -&gt; int *)
fun add (x : int, y : int) : int = x + y

val () = Test.int ("uncurried", 51, add (1, 50))


(* cadd : int -&gt; int -&gt; int *)
fun cadd (x : int) : int -&gt; int = (fn y =&gt; x + y)

val () = Test.int ("curried", 51, cadd 1 50)
</html:code></fr:pre><fr:p>We need not give <fr:code>cadd</fr:code> all of its arguments simultaneously:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val incr = cadd 1

val () = Test.int ("curried again, 51, incr 50)
</html:code></fr:pre><fr:p>The type of <fr:code>incr</fr:code> is <fr:code>int -&gt; int</fr:code>, and the value is <fr:code>fn y =&gt; 1 + y</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>793</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005T</fr:addr><fr:route>150-005T.xml</fr:route><fr:title>Curried polymorphic sorting algorithm</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall <fr:link
href="150-005K.xml"
type="local"
addr="150-005K">polymorphic <fr:link
href="150-004K.xml"
type="local"
addr="150-004K">insertion sort</fr:link></fr:link>. Rather than taking the comparison function and list to sort simultaneously, we can take a comparison function as input and produce a sorting function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* isort : ('a * 'a -&gt; order) -&gt; ('a list -&gt; 'a list) *)
fun isort (compare : 'a * 'a -&gt; order) (l : 'a list) : 'a list =
  let
    fun insert (x, nil) = [x]
      | insert (x, y :: ys) =
          case compare (x, y) of
            GREATER =&gt; y :: insert (x, ys)
          | _       =&gt; x :: y :: ys

    fun sorter nil = nil
      | sorter (x :: xs) = insert (x, sorter xs)
  in
    sorter l
  end
</html:code></fr:pre><fr:p>Here, <fr:code>isort</fr:code> is a higher-order function: it takes in a function <fr:code>compare : 'a * 'a -&gt; order</fr:code>, and it produces a function of type <fr:code>'a list -&gt; 'a list</fr:code>.</fr:p><fr:p>Since we don't use <fr:code>l</fr:code> in the implementation of <fr:code>insert</fr:code> or <fr:code>sorter</fr:code>, we can equivalently avoid taking in <fr:code>l</fr:code> ourselves, instead just producing the function <fr:code>sorter : 'a list -&gt; 'a list</fr:code> directly:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* isort : ('a * 'a -&gt; order) -&gt; ('a list -&gt; 'a list) *)
fun isort (compare : 'a * 'a -&gt; order) : 'a list -&gt; 'a list =
  let
    (* insert : 'a * 'a list -&gt; 'a list *)
    fun insert (x, nil) = [x]
      | insert (x, y :: ys) =
          case compare (x, y) of
            GREATER =&gt; y :: insert (x, ys)
          | _       =&gt; x :: y :: ys

    (* sorter : 'a list -&gt; 'a list *)
    fun sorter nil = nil
      | sorter (x :: xs) = insert (x, sorter xs)
  in
    sorter
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>794</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-005V</fr:addr><fr:route>150-005V.xml</fr:route><fr:title>Redundant lambdas (<fr:tex>\eta </fr:tex>-reduction)</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all values <fr:code>f : t1 -&gt; t2</fr:code>, we have <fr:tex
display="block">\texttt {f} \cong  \texttt {fn x =&gt; f x}.</fr:tex> Therefore, if you ever write <fr:code>fn x =&gt; f x</fr:code>, you might as well just write <fr:code>f</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>797</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005W</fr:addr><fr:route>150-005W.xml</fr:route><fr:title>Instantiating <fr:link
href="150-005T.xml"
type="local"
addr="150-005T">curried polymorphic sorting algorithm</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the definition of <fr:code>isort</fr:code>, we can define sorters for various comparison functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun intsort (l : int list) : int list = isort Int.compare l
fun stringsort (l : string list) : string list = isort String.compare l
</html:code></fr:pre><fr:p>We can simplify this using <fr:link
href="150-005V.xml"
type="local"
addr="150-005V"><fr:tex>\eta </fr:tex>-reduction</fr:link>, avoiding the inputs <fr:code>l</fr:code> entirely:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val intsort = isort Int.compare
val stringsort = isort String.compare
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>800</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005Z</fr:addr><fr:route>150-005Z.xml</fr:route><fr:title>Function composition</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To compose two functions <fr:code>f : 'a -&gt; 'b</fr:code> and <fr:code>g : 'b -&gt; 'c</fr:code>, we can define <fr:code>(g o f) : 'a -&gt; 'c</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (op o) (g : 'b -&gt; 'c, f : 'a -&gt; 'b) : 'a -&gt; 'c = fn (x : 'a) =&gt; g (f x)
</html:code></fr:pre><fr:p>We can equivalently define composition in the following ways:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun g o f = fn x =&gt; g (f x)
fun (g o f) x = g (f x)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>805</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0060</fr:addr><fr:route>150-0060.xml</fr:route><fr:title>Reverse list sorting</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To sort a list backwards, we can invert the result of the comparison function.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun invert LESS    = GREATER
  | invert EQUAL   = EQUAL
  | invert GREATER = LESS

fun intCompareBackwards (x, y) = invert (Int.compare (x, y))
</html:code></fr:pre><fr:p>Using <fr:link
href="150-005Z.xml"
type="local"
addr="150-005Z">function composition</fr:link>, this is even simpler:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val intCompareBackwards = invert o Int.compare
</html:code></fr:pre><fr:p>We can view this inversion as a function, too:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun invertCompare (compare : 'a * 'a -&gt; order) : 'a * 'a -&gt; order =
  invert o compare
</html:code></fr:pre><fr:p>We may define a reverse sorting algorithm as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val revSort = isort o invertCompare
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>806</fr:anchor><fr:taxon>Warning</fr:taxon><fr:addr>150-0061</fr:addr><fr:route>150-0061.xml</fr:route><fr:title>Value restriction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Sometimes, <fr:link
href="150-000M.xml"
type="local"
addr="150-000M"><fr:code>val</fr:code> declarations</fr:link> involving polymorphism can trigger a warning called the "value restriction", rendering <fr:link
href="150-004T.xml"
type="local"
addr="150-004T">type variables</fr:link> like <fr:code>'a</fr:code> as <fr:code>?.X1</fr:code>. You may safely ignore such warnings in this class.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>807</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0067</fr:addr><fr:route>150-0067.xml</fr:route><fr:title>Staging</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:link
href="150-0068.xml"
type="local"
addr="150-0068">Curried functions</fr:link> can perform some intermediate computation before receiving all of their arguments.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>811</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0069</fr:addr><fr:route>150-0069.xml</fr:route><fr:title>Staged list search</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the below function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* nth : 'a list -&gt; int -&gt; 'a
 * REQUIRES: 0 &lt;= i &lt; length l
 * ENSURES: nth l i ==&gt; x, where x is the i'th element of l
 *)
fun nth nil       _ = raise Fail "impossible by REQUIRES"
  | nth (x :: _ ) 0 = x
  | nth (_ :: xs) i = nth xs (i - 1)

(* earliest : string list -&gt; int -&gt; string
 * REQUIRES: 0 &lt;= i &lt; length l
 * ENSURES: earliest l i ==&gt; s, where s is the i'th earliest string in l alphabetically
 *)
fun earliest l i = nth (msort String.compare l) i

(* equivalent: *)
val earliest = fn l =&gt; fn i =&gt; nth (msort String.compare l) i
</html:code></fr:pre><fr:p>Here, each call to <fr:code>earliest l i</fr:code> takes <fr:tex>\mathcal {O}(n\log  n)</fr:tex> time. Instead, we can stage the call to <fr:code>msort</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun earliest (l : string list) : int -&gt; string =
  let
    val sorted = msort String.compare l
  in
    nth sorted
  end

(* equivalent: *)
val earliest = fn l =&gt; nth (msort String.compare l)
</html:code></fr:pre><fr:p>Each call to <fr:code>earliest l i</fr:code> still takes <fr:tex>\mathcal {O}(n\log  n)</fr:tex> time. However:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val f : int -&gt; string = earliest ["Bob", "Charlie", "Alice"]
</html:code></fr:pre><fr:p>This call to <fr:code>earliest</fr:code> still takes <fr:tex>\mathcal {O}(n\log  n)</fr:tex>, but each call <fr:code>f i</fr:code> only takes <fr:tex>\mathcal {O}(n)</fr:tex>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>827</fr:anchor><fr:addr>150-005N</fr:addr><fr:route>150-005N.xml</fr:route><fr:title>List transformers</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>813</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-005U</fr:addr><fr:route>150-005U.xml</fr:route><fr:title>Compositionality via higher-order functions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In our <fr:link
href="150-000V.xml"
type="local"
addr="150-000V">principles of functional programming</fr:link>, we include <fr:em>compositionality</fr:em>, the idea that big problems can be broken down into smaller components which are often reusable. Higher-order functions let us accomplish this.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>818</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005X</fr:addr><fr:route>150-005X.xml</fr:route><fr:title>List map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* incAll : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: incAll [x1, ..., xn] = [x1 + 1, ..., xn + 1]
 *)
fun incAll nil       = nil
  | incAll (x :: xs) = (x + 1) :: incAll xs

(* stringAll : int list -&gt; string list
 * REQUIRES: true
 * ENSURES: stringAll [x1, ..., xn] = [Int.toString x1, ..., Int.toString xn]
 *)
fun stringAll nil       = nil
  | stringAll (x :: xs) = Int.toString x :: stringAll xs

(* bool list -&gt; bool list
 * REQUIRES: true
 * ENSURES: flipAll [x1, ..., xn] = [not x1, ..., not xn]
 *)
fun flipAll nil       = nil
  | flipAll (x :: xs) = not x :: flipAll xs
</html:code></fr:pre><fr:p>All share a common structure, applying a function to each element of the input list. For a function <fr:code>f : t1 -&gt; t2</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* fAll : t1 list -&gt; t2 list
 * REQUIRES: true
 * ENSURES: fAll [x1, ..., xn] = [f x1, ..., f xn]
 *)
fun fAll nil       = nil
  | fAll (x :: xs) = f x :: fAll xs
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>map</fr:code>, that takes in such a function <fr:code>f</fr:code> and produces the corresponding <fr:code>fAll</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a list -&gt; 'b list
 * REQUIRES: true
 * ENSURES: map f [x1, ..., xn] = [f x1, ..., f xn]
 *)
fun map f nil       = nil
  | map f (x :: xs) = f x :: map f xs
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val incAll = map (fn x =&gt; x + 1)
val stringAll = map Int.toString
val flipAll = map not
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>821</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005Y</fr:addr><fr:route>150-005Y.xml</fr:route><fr:title>Adding a number to every element of a list</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-005X.xml"
type="local"
addr="150-005X">list map</fr:link>, we can easily implement the following specification:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* addToAll : int * int list -&gt; int list
 * REQUIRES: true
 * ENSURES: addToAll (x, [y1, ..., yn]) = [x + y1, ..., x + yn]
 *)
fun addToAll (x, l) = map (fn y =&gt; x + y) l
</html:code></fr:pre><fr:p>Or, even more concisely using <fr:link
href="150-005Q.xml"
type="local"
addr="150-005Q">curried addition</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun addToAll (x, l) = map (cadd x) l
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>826</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0062</fr:addr><fr:route>150-0062.xml</fr:route><fr:title>List filter</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* keepEvens : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: keepEvens l ==&gt; l', where l' contains the even elements of l in the same order
 *)
fun keepEvens nil       = nil
  | keepEvens (x :: xs) =
      if isEven x
        then x :: keepEvens xs
        else keepEvens xs

(* keepMammals : animal list -&gt; animal list
 * REQUIRES: true
 * ENSURES: keepMammals l ==&gt; l', where l' contains the mammals of l in the same order
 *)
fun keepMammals nil       = nil
  | keepMammals (x :: xs) =
      if isMammal x
        then x :: keepMammals xs
        else keepMammals xs
</html:code></fr:pre><fr:p>Both share a common structure, only keeping the elements of the input list satisfying some condition. For a predicate <fr:code>f : t -&gt; bool</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* keepP : t list -&gt; t list
 * REQUIRES: true
 * ENSURES: keepP l ==&gt; l', where l' contains the elements of l satisfying p in the same order
 *)
fun keepP nil       = nil
  | keepP (x :: xs) =
      if p x
        then x :: keepP xs
        else keepP xs
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>filter</fr:code>, that takes in such a predicate <fr:code>p</fr:code> and produces the corresponding <fr:code>keepP</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* filter : ('a -&gt; bool) -&gt; 'a list -&gt; 'a list
 * REQUIRES: true
 * ENSURES: filter p l ==&gt; l', where l' contains the elements of l satisfying p in the same order
 *)
fun filter p nil       = nil
  | filter p (x :: xs) =
      if p x
        then x :: filter p xs
        else filter p xs
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val keepEvens = filter isEven
val keepMammals = filter isMammal
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>840</fr:anchor><fr:addr>150-005O</fr:addr><fr:route>150-005O.xml</fr:route><fr:title>List folds</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>832</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0063</fr:addr><fr:route>150-0063.xml</fr:route><fr:title>List <fr:code>foldr</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* sum : int list -&gt; int
 * REQUIRES: true
 * ENSURES: sum [x1, ..., xn] = x1 + (x2 + (... + (xn + 0)))
 *)
fun sum nil       = 0
  | sum (x :: xs) = x + sum xs

(* concat : 'a list list -&gt; 'a list
 * REQUIRES: true
 * ENSURES: concat [x1, ..., xn] = x1 @ (x2 @ (... @ (xn @ nil)))
 *)
fun concat nil       = nil
  | concat (x :: xs) = x @ concat xs

(* commas : string list -&gt; string
 * REQUIRES: true
 * ENSURES: commas [x1, ..., xn] = (x1 ^ ", ") ^ ((x2 ^ ", ") ^ (... ^ ((xn ^ ", ") ^ ".")))
 *)
fun commas nil       = "."
  | commas (x :: xs) = (x ^ ", ") ^ commas xs

(* rebuild : 'a list -&gt; 'a list *)
fun rebuild nil       = nil
  | rebuild (x :: xs) = x :: rebuild xs

(* isort : int list -&gt; int list *)
fun isort nil       = nil
  | isort (x :: xs) = insert (x, isort xs)
</html:code></fr:pre><fr:p>All three share a common structure, combining <fr:code>x</fr:code> into the recursive call on <fr:code>xs</fr:code>. For a base case <fr:code>init : t2</fr:code> and a recursive case <fr:code>f : t1 * t2 -&gt; t2</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* combine : t1 list -&gt; t2
 * REQUIRES: true
 * ENSURES: combine [x1, ..., xn] = f (x1, f (x2, ... f (xn, init)))
 *)
fun combine nil       = init
  | combine (x :: xs) = f (x, combine xs)
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>foldr</fr:code>, that takes in such an initial value <fr:code>init</fr:code> and a combining function <fr:code>f</fr:code> and produces the corresponding <fr:code>combine</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldr : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b
 * REQUIRES: true
 * ENSURES: foldr f init [x1, ..., xn] = f (x1, f (x2, ... f (xn, init)))
 *)
fun foldr f init nil       = init
  | foldr f init (x :: xs) = f (x, foldr f init xs)
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val sum = foldr (op +) 0
val concat = foldr (op @) nil
val commas = foldr (fn (x, y) =&gt; x ^ ", " ^ y) "."
val rebuild = foldr (op ::) nil
val isort = foldr insert nil
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>836</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0065</fr:addr><fr:route>150-0065.xml</fr:route><fr:title>List <fr:code>foldl</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can also traverse a list in the other direction:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldl : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b
 * REQUIRES: true
 * ENSURES: foldr f acc [x1, ..., xn] = f (xn, ... f (x2, f (x1, acc)))
 *)
fun foldl f acc nil       = acc
  | foldl f acc (x :: xs) = foldl f (f (x, acc)) xs
</html:code></fr:pre><fr:p>Here, we traverse the list in the other direction. Rather than the <fr:code>'b</fr:code> input serving as a base case, it serves as an accumulator.</fr:p><fr:p>Equivalently, we can implement <fr:code>foldl</fr:code> using <fr:code>foldr</fr:code> and list reverse:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun foldl f acc = foldr f acc o rev
</html:code></fr:pre><fr:p>This makes it clear that if we choose the first implementation, we could implement <fr:code>rev</fr:code> using <fr:code>foldl</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val rev = foldl (op ::) nil
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>838</fr:anchor><fr:taxon>Taxon</fr:taxon><fr:addr>150-0066</fr:addr><fr:route>150-0066.xml</fr:route><fr:title>List folds and <fr:code>for</fr:code> loops</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>for</fr:code> loops of other languages are analogous to <fr:code>foldl</fr:code>. The imperative pseudocode</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">acc = init

for x in l:
    acc = f(x, acc)
</html:code></fr:pre><fr:p>corresponds to the Standard ML code <fr:code>foldl f init l</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>839</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-0064</fr:addr><fr:route>150-0064.xml</fr:route><fr:title>Universality of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The definition of <fr:code>foldr</fr:code> is very natural.</fr:p><fr:ul><fr:li>It takes in a replacement for each constructor: <fr:code>init</fr:code> for <fr:code>nil</fr:code> and <fr:code>f</fr:code> for <fr:code>::</fr:code>.</fr:li>
  <fr:li>By construction, every function defined by structural recursion can be implemented using <fr:code>foldr</fr:code>: the base case is <fr:code>init</fr:code>, and the recursive case is <fr:code>f</fr:code>.</fr:li>
  <fr:li>It goes right-to-left (i.e., bottom-to-top) on lists, which are constructed right-to-left (i.e., bottom-to-top): <fr:code>nil</fr:code> is all the way to the right (or at the bottom, depending on how you think about it).</fr:li></fr:ul><fr:p>These properties naturally generalize to other datatypes. In contrast, <fr:code>foldl</fr:code> does not: datatypes in general need not have a notion of "top down", as trees may have more than one branch.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>907</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect10</fr:addr><fr:route>150-lect10.xml</fr:route><fr:title>Higher-order functions II: <fr:code>map</fr:code>, <fr:code>bind</fr:code>, and <fr:code>fold</fr:code></fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>13</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>, <fr:link
href="sb21.xml"
type="local"
addr="sb21">Stephen Brookes</fr:link>, and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>852</fr:anchor><fr:addr>150-006X</fr:addr><fr:route>150-006X.xml</fr:route><fr:title>Warm-up: data pipelines</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>849</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006P</fr:addr><fr:route>150-006P.xml</fr:route><fr:title>Pipe function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following function, pronounced "pipe", is useful for building data pipelines:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix 4 |&gt;

(* op |&gt; : 'a * ('a -&gt; 'b) -&gt; 'b *)
fun x |&gt; f = f x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>851</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006T</fr:addr><fr:route>150-006T.xml</fr:route><fr:title>Pipeline of higher-order functions using <fr:code>|&gt;</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:code>|&gt;</fr:code>, we can take the sum of the squares of the numbers in a list <fr:code>l</fr:code> greater than some threshold <fr:code>n : int</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun dotProduct (l : int list, n : int) : int list =
  l
  |&gt; List.filter (fn x =&gt; x &gt; n)
  |&gt; List.map (fn x =&gt; x * x)
  |&gt; List.foldr op+ 0
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>862</fr:anchor><fr:addr>150-006B</fr:addr><fr:route>150-006B.xml</fr:route><fr:title>Generalized <fr:code>map</fr:code>: one-to-one transformations</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>854</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006D</fr:addr><fr:route>150-006D.xml</fr:route><fr:title>Map abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-005X.xml"
type="local"
addr="150-005X"><fr:code>map</fr:code></fr:link>, which takes a function <fr:code>f : 'a -&gt; 'b</fr:code> and a list <fr:code>'a list</fr:code> and applies the function on each <fr:code>'a</fr:code> to get a resulting <fr:code>'b list</fr:code>.</fr:p><fr:p>This specification can be generalized beyond <fr:code>'a list</fr:code> to arbitrary types <fr:code>'a t</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES:
 * - map id = id, ie map id s = s
 * - map (f o g) = map f o map g, ie map f (map g s) = map (f o g) s
 *)
</html:code></fr:pre><fr:p>In other words, the ENSURES guarantees that <fr:code>map</fr:code> is structure-preserving.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>856</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006E</fr:addr><fr:route>150-006E.xml</fr:route><fr:title>Tree map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall <fr:link
href="150-005E.xml"
type="local"
addr="150-005E">polymorphic trees</fr:link>. We can implement <fr:code>tmap</fr:code> to map over trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a tree = Empty | Node of 'a tree * 'a * 'a tree

(* tmap : ('a -&gt; 'b) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES:
 * - tmap id = id, ie tmap id t = t
 * - tmap (f o g) = tmap f o tmap g, ie tmap f (tmap g t) = tmap (f o g) t
 *)
fun tmap f Empty = Empty
  | tmap f (Node (l, x, r)) = Node (tmap f l, f x, tmap f r)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>859</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006F</fr:addr><fr:route>150-006F.xml</fr:route><fr:title>Shrub map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following type of polymorphic "shrubs", trees which store data at the leaves rather than the nodes.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a shrub = SEmpty | SLeaf of 'a | SNode of 'a shrub * 'a shrub
</html:code></fr:pre><fr:p>We can implement <fr:code>smap</fr:code> to map over shrubs:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* smap : ('a -&gt; 'b) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES:
 * - smap id = id, ie smap id s = s
 * - smap (f o g) = smap f o smap g, ie smap f (smap g s) = smap (f o g) s
 *)
fun smap f SEmpty = SEmpty
  | smap f (SLeaf x) = SLeaf (f x)
  | smap f (SNode (l, r)) = SNode (smap f l, smap f r)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>861</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006G</fr:addr><fr:route>150-006G.xml</fr:route><fr:title>Option map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement <fr:code>omap</fr:code> to map over options:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* omap : ('a -&gt; 'b) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES:
 * - omap id = id, ie omap id opt = opt
 * - omap (f o g) = omap f o omap g, ie omap f (omap g opt) = omap (f o g) opt
 *)
fun omap f NONE = NONE
  | omap f (SOME x) = SOME (f x)
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>875</fr:anchor><fr:addr>150-006A</fr:addr><fr:route>150-006A.xml</fr:route><fr:title>Generalized <fr:code>foldr</fr:code>: natural folds</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>865</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006H</fr:addr><fr:route>150-006H.xml</fr:route><fr:title>Fold abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-0063.xml"
type="local"
addr="150-0063"><fr:code>foldr</fr:code></fr:link>. Crucially, it sent <fr:code>[x1, x2, ..., xn]</fr:code>, i.e., <fr:blockquote><fr:code>op:: (x1, op:: (x2, ..., op:: (xn, nil)))</fr:code></fr:blockquote> to <fr:blockquote><fr:code>f (x1, f (x2, ..., f (xn, init)))</fr:code></fr:blockquote> by replacing <fr:code>op::</fr:code> with <fr:code>f</fr:code> and <fr:code>nil</fr:code> with <fr:code>init</fr:code>.</fr:p><fr:p>If we rewrite the list datatype as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a list = Cons of 'a * 'a list | Nil
</html:code></fr:pre><fr:p>We might as well write <fr:code>foldr</fr:code> as:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldr : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b *)
fun foldr (cons : 'a * 'b -&gt; 'b) (nil : 'b) (l : 'a list) : 'b =
  case l of
    Cons (x, xs) =&gt; cons (x, foldr cons nil xs)
  | Nil          =&gt; nil
</html:code></fr:pre><fr:p>The type of each argument matches the type of the constructor, swapping <fr:code>'a list</fr:code> for <fr:code>'b</fr:code>. Here, <fr:code>cons</fr:code> is just a function (not a constructor!) to replace every <fr:code>Cons</fr:code> with, and <fr:code>nil</fr:code> is just a value to replace every <fr:code>Nil</fr:code> with.</fr:p><fr:p>The general recipe is as follows:</fr:p><fr:ol><fr:li>For each constructor, replace the name of the type with <fr:code>'b</fr:code>, including recursive uses.</fr:li>
  <fr:li>Take in each of these functions/values meant to replace the constructor as arguments.</fr:li>
  <fr:li>In the implementation, replace each constructor with its function, performing recursive calls on substructures if there are any.</fr:li></fr:ol><fr:p>For example:</fr:p><fr:ol><fr:li>We have <fr:code>Cons : 'a * 'a list -&gt; 'a list</fr:code> and <fr:code>Nil : 'a list</fr:code>, so we get <fr:code>cons : 'a * 'b -&gt; 'b</fr:code> and <fr:code>nil : 'b</fr:code>.</fr:li>
  <fr:li>We take in <fr:code>cons</fr:code> and <fr:code>nil</fr:code> as arguments.</fr:li>
  <fr:li>The implementation is as above.</fr:li></fr:ol><fr:p>This perspective justifies the <fr:link
href="150-0064.xml"
type="local"
addr="150-0064">universality of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link></fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>868</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006I</fr:addr><fr:route>150-006I.xml</fr:route><fr:title>Tree fold</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a fold for type <fr:code>'a tree</fr:code> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* tfold : 'b -&gt; ('b * 'a * 'b -&gt; 'b) -&gt; 'a tree -&gt; 'b *)
fun tfold (empty : 'b) (node : 'b * 'a * 'b -&gt; 'b) (t : 'a tree) : 'b =
  case t of
    Empty =&gt; empty
  | Node (l, x, r) =&gt; node (tfold empty node l, x, tfold empty node r)
</html:code></fr:pre><fr:p>We can use it to concisely implement tree functions, such as <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link> and <fr:link
href="150-002Q.xml"
type="local"
addr="150-002Q">in-order traversal of a tree</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val sum : int tree -&gt; int =
  tfold 0 (fn (m, x, n) =&gt; m + x + n)

val inordSlow : 'a tree -&gt; 'a list =
  tfold nil (fn (l1, x, l2) =&gt; l1 @ x :: l2)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>871</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006J</fr:addr><fr:route>150-006J.xml</fr:route><fr:title>Shrub fold</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a fold for type <fr:code>'a shrub</fr:code> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* sfold : 'b -&gt; ('a -&gt; 'b) -&gt; ('b * 'b -&gt; 'b) -&gt; 'a shrub -&gt; 'b *)
fun sfold (sempty : 'b) (sleaf : 'a -&gt; 'b) (snode : 'b * 'b -&gt; 'b) (s : 'a shrub) : 'b =
  case s of
    SEmpty =&gt; sempty
  | SLeaf x =&gt; sleaf x
  | SNode (l, r) =&gt; snode (sfold sempty sleaf snode l, sfold sempty sleaf snode r)
</html:code></fr:pre><fr:p>We can use it to concisely implement shrub functions. For example, we can take the in-order traversal, and we can count the characters used in a <fr:code>string shrub</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val sinord : 'a tree -&gt; 'a list =
  sfold nil (fn x =&gt; [x]) (op @)

val countChars : string tree -&gt; int =
  sfold 0 String.size (op +)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>874</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006K</fr:addr><fr:route>150-006K.xml</fr:route><fr:title>Option fold</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a fold for <fr:code>'a option</fr:code> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* ofold : 'b -&gt; ('a -&gt; 'b) -&gt; 'a option -&gt; 'b *)
fun ofold (none : 'b) (some : 'a -&gt; 'b) (opt : 'a option) : 'b =
  case opt of
    NONE =&gt; none
  | SOME x =&gt; some x
</html:code></fr:pre><fr:p>Note that we never take in a <fr:code>'b</fr:code> or perform recursive calls since <fr:code>'a option</fr:code> is not recursive.</fr:p><fr:p>We can use <fr:code>ofold</fr:code> to implement functions concisely without explicitly pattern matching. For example, since we sometimes <fr:link
href="150-002G.xml"
type="local"
addr="150-002G">use <fr:code>int option</fr:code> as integers extended with <fr:tex>\infty </fr:tex></fr:link>, we can convert one to a string:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val toString : int option -&gt; string =
  ofold "infinity" Int.toString
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>906</fr:anchor><fr:addr>150-006C</fr:addr><fr:route>150-006C.xml</fr:route><fr:title>Generalized <fr:code>filter</fr:code>: one-to-many transformations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall <fr:link
href="150-0062.xml"
type="local"
addr="150-0062">list filter</fr:link>, where <fr:code>filter : ('a -&gt; bool) -&gt; 'a list -&gt; 'a list</fr:code>. This function sends each element in a list to at most one element. We can generalize this to a new tool, <fr:code>bind</fr:code>, that sends each element to arbitrarily many elements.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>877</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006L</fr:addr><fr:route>150-006L.xml</fr:route><fr:title>List bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>bind</fr:code> takes in a function <fr:code>f : 'a -&gt; 'b list</fr:code> that produces as many <fr:code>'b</fr:code>s as it wishes; we accumulate all of them in a list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* bind : ('a -&gt; 'b list) -&gt; 'a list -&gt; 'b list *)
fun bind f nil       = nil
  | bind f (x :: xs) = f x @ bind f xs
</html:code></fr:pre><fr:p>It generalizes <fr:link
href="150-005X.xml"
type="local"
addr="150-005X">list map</fr:link>, whose function input must always produce exactly one <fr:code>'b</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>879</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006Y</fr:addr><fr:route>150-006Y.xml</fr:route><fr:title>List filter using bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement <fr:link
href="150-0062.xml"
type="local"
addr="150-0062">list filter</fr:link> concisely using <fr:link
href="150-006L.xml"
type="local"
addr="150-006L">list bind</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* filter : ('a -&gt; bool) -&gt; 'a list -&gt; 'a list *)
fun filter p = bind (fn a =&gt; if p a then [a] else [])
</html:code></fr:pre><fr:p>Here, <fr:code>filter</fr:code> either produces a singleton list or an empty list. In this way, <fr:code>bind</fr:code> is a generalization: we can return any length list we choose.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>881</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006M</fr:addr><fr:route>150-006M.xml</fr:route><fr:title>Tree roots via <fr:code>bind</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can use <fr:code>bind</fr:code> to extract data, in addition to merely filtering. For example, we can use <fr:code>bind</fr:code> to get all of the roots from a list of potentially-empty trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* roots : 'a tree list -&gt; 'a list *)
val roots = bind (fn Empty =&gt; [] | Node (_, x, _) =&gt; [x])
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>883</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006N</fr:addr><fr:route>150-006N.xml</fr:route><fr:title>Tree elements using <fr:code>bind</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can use <fr:code>bind</fr:code> to turn each element into multiple elements. For example, we can get all of he elements out of a list of trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* elements : 'a tree list -&gt; 'a list *)
val elements = bind inord
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>885</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006W</fr:addr><fr:route>150-006W.xml</fr:route><fr:title>Cartesian product using <fr:code>bind</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can use <fr:code>bind</fr:code> to get all possible pairs of <fr:code>'a</fr:code>s and <fr:code>'b</fr:code>s:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun product (l1 : 'a list, l2 : 'b list) : ('a * 'b) list =
  bind (fn a =&gt; bind (fn b =&gt; [(a, b)]) l2) l1
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>887</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006Z</fr:addr><fr:route>150-006Z.xml</fr:route><fr:title>Conditional duplication using <fr:code>bind</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We may choose to send some elements to multiple values in the result list. For example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val f : int list -&gt; int list =
  bind (fn x =&gt; if x &gt;= 2 then [x, x] else [x])
</html:code></fr:pre><fr:p>If we apply this function to the list <fr:code>[1, 2, 3]</fr:code>, then <fr:code>2</fr:code> and <fr:code>3</fr:code> get duplicated in the result list:</fr:p><fr:tex
display="block">\texttt {f [1, 2, 3]} \Longrightarrow  \texttt {[1, 2, 2, 3, 3]}</fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>893</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006O</fr:addr><fr:route>150-006O.xml</fr:route><fr:title>Exact change using <fr:code>bind</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:code>bind</fr:code>, we can figure out how to make exact change using 25¢ (quarter), 10¢ (nickel), and 5¢ (dime) coins. First, we implement a helper function that generates all of the possible ways to use a given coin to shrink the total money needed:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* INVARIANT: &gt;= 0 *)
type money = int

(* INVARIANT: &gt;= 0 *)
type coin = int

(* useCoin : coin -&gt; money -&gt; (int * money) list
 * REQUIRES: true
 * ENSURES: useCoin c total ==&gt; l, where l contains all pairs (n, total') with n,total' &gt;= 0 such that c*n + total' = total
 *)
fun useCoin (c : coin) (total : money) : (int * money) list =
  (0, total) ::
    (if total &lt; c
      then []
      else map (fn (n, total') =&gt; (n + 1, total')) (useCoin c (total - c)))
</html:code></fr:pre><fr:p>First, we can use <fr:code>bind</fr:code> on the result of <fr:code>useCoin</fr:code> to filter the valid results. Assume we only wish to use quarters:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun makeChangeQ (total : int) : int list =
  bind (fn (q, 0) =&gt; [q] | _ =&gt; [])
    (useCoin 25 total)
</html:code></fr:pre><fr:p>Rather than immediately filtering, we can try to use smaller coins instead:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun makeChange (total : int) : (int * int * int) list =
  bind (fn (q, d, n, 0) =&gt; [(q, d, n)] | _ =&gt; []) (
    bind (fn (q, d, total'') =&gt; map (fn (n, total''') =&gt; (q, d, n, total''')) (useCoin 5 total'')) (
      bind (fn (q, total') =&gt; map (fn (d, total'') =&gt; (q, d, total'')) (useCoin 10 total'))
        (useCoin 25 total)
    )
  )
</html:code></fr:pre><fr:p>We can rewrite this in the order operations happen using the <fr:link
href="150-006P.xml"
type="local"
addr="150-006P">pipe function</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun makeChange (total : int) : (int * int * int) list =
  useCoin 25 total
  |&gt; bind (fn (q, total') =&gt; map (fn (d, total'') =&gt; (q, d, total'')) (useCoin 10 total'))
  |&gt; bind (fn (q, d, total'') =&gt; map (fn (n, total''') =&gt; (q, d, n, total''')) (useCoin 5 total''))
  |&gt; bind (fn (q, d, n, 0) =&gt; [(q, d, n)] | _ =&gt; [])
</html:code></fr:pre><fr:p>To avoid constructing the intermediate tuples <fr:code>(q, d, total'')</fr:code> and <fr:code>(q, d, n, total''')</fr:code> just to immediately pattern match on it in the next <fr:code>bind</fr:code>, we can nest the <fr:code>bind</fr:code>s as folllows. In this way, <fr:code>q</fr:code> and <fr:code>d</fr:code> remain in scope for the inner <fr:code>bind</fr:code>s, and we avoid the <fr:code>map</fr:code>s.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun makeChange (total : int) : (int * int * int) list =
  bind (fn (q, total') =&gt;
  bind (fn (d, total'') =&gt;
  bind (fn (n, 0) =&gt; [(q, d, n)] | _ =&gt; [])
    (useCoin 5 total''))
    (useCoin 10 total'))
    (useCoin 25 total)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>895</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006Q</fr:addr><fr:route>150-006Q.xml</fr:route><fr:title>Infix <fr:code>&gt;&gt;=</fr:code> notation for bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Similar to the <fr:link
href="150-006P.xml"
type="local"
addr="150-006P">pipe function</fr:link>, we can reverse the argument order of <fr:link
href="150-006L.xml"
type="local"
addr="150-006L">list bind</fr:link> and view it as an infix function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix 4 &gt;&gt;=

(* op &gt;&gt;= : 'a list * ('a -&gt; 'b list) -&gt; 'b list *)
fun l &gt;&gt;= f = bind f l
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>898</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006U</fr:addr><fr:route>150-006U.xml</fr:route><fr:title>Exact change using <fr:code>&gt;&gt;=</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can rewrite <fr:ref
addr="150-006O"
href="150-006O.xml"
taxon="Example"></fr:ref> using the infix function <fr:code>&gt;&gt;=</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun makeChange (total : int) : (int * int * int) list =
  (useCoin 25 total) &gt;&gt;=
  bind (fn (q, d, n, 0) =&gt; [(q, d, n)] | _ =&gt; []) (
    bind (fn (q, d, total'') =&gt; map (fn (n, total''') =&gt; (q, d, n, total''')) (useCoin 5 total')) (
      bind (fn (q, total') =&gt; map (fn (d, total'') =&gt; (q, d, total'')) (useCoin 10 total'))
    )
  )

fun makeChange (total : int) : (int * int * int) list =
  useCoin 25 total &gt;&gt;= (fn (q, total') =&gt;
  useCoin 10 total' &gt;&gt;= (fn (d, total'') =&gt;
  useCoin 5, total'' &gt;&gt;= (fn (n, total''') =&gt;
  case total''' of
    0 =&gt; [(q, d, n)]
  | _ =&gt; [])))
</html:code></fr:pre><fr:p>Notice that each line is inside a <fr:code>fn</fr:code> started by the previous line.</fr:p><fr:p>You may observe a similarity to imperative programming languages. Informally:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">  (q, total') &lt;- useCoin 25 total;
  (d, total'') &lt;- useCoin 10 total';
  (n, total''') &lt;- useCoin 5 total'';
  match total''':
    case 0:
      return (q, d, n)
    case _:
      error()
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>901</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006R</fr:addr><fr:route>150-006R.xml</fr:route><fr:title>Bind abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-006L.xml"
type="local"
addr="150-006L"><fr:code>bind</fr:code></fr:link>, which takes a function <fr:code>f : 'a -&gt; 'b list</fr:code> and a list <fr:code>'a list</fr:code> and applies the function on each <fr:code>'a</fr:code> to get a resulting flattened <fr:code>'b list</fr:code>.</fr:p><fr:p>This specification can be generalized beyond <fr:code>'a list</fr:code> to arbitrary types <fr:code>'a t</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* bind : ('a -&gt; 'b t) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES: ...
 *)
</html:code></fr:pre><fr:p>The ENSURES should contain some conditions similar to those given for the <fr:link
href="150-006D.xml"
type="local"
addr="150-006D">map abstraction</fr:link>, but we elide them in this class.</fr:p><fr:p>We can always implement the infix <fr:code>&gt;&gt;=</fr:code> using a <fr:code>bind</fr:code> implementation:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (x : 'a t) &gt;&gt;= (f : 'a -&gt; 'b t) : 'b t = bind f x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>903</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006S</fr:addr><fr:route>150-006S.xml</fr:route><fr:title>Option bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement <fr:code>obind</fr:code> to map over the element of an option, if there is one:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* obind : ('a -&gt; 'b option) -&gt; 'a option -&gt; 'b option *)
fun obind f NONE = NONE
  | obind f (SOME a) = f a
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>905</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-006V</fr:addr><fr:route>150-006V.xml</fr:route><fr:title>Checking an in-order traversal using <fr:link
href="150-006S.xml"
type="local"
addr="150-006S">option bind</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-006S.xml"
type="local"
addr="150-006S">option bind</fr:link>, we can propagate failures implicitly.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* tmatch : int list -&gt; int tree -&gt; int list option
 * REQUIRES: true
 * ENSURES: tmatch goal t ==&gt;
 * - SOME remainder, if there exists some l2 such that (inord t @ remainder) = goal
 * - NONE otherwise
 *)
fun tmatch goal Empty = SOME goal
  | tmatch goal (Node (l, x, r)) =
      tmatch goal l &gt;&gt;= (fn remainder =&gt;
      case remainder of
        nil     =&gt; NONE
      | y :: ys =&gt; if x = y then tmatch ys r else NONE)
</html:code></fr:pre><fr:p>If checking <fr:code>l</fr:code> produces <fr:code>NONE</fr:code>, then <fr:code>&gt;&gt;=</fr:code> will guarantee that the entire computation produces <fr:code>NONE</fr:code>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>948</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect11</fr:addr><fr:route>150-lect11.xml</fr:route><fr:title>Lazy programming</fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>18</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>, <fr:link
href="sb21.xml"
type="local"
addr="sb21">Stephen Brookes</fr:link>, and <fr:link
href="greis.xml"
type="local"
addr="greis">Giselle Reis</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>936</fr:anchor><fr:addr>150-0070</fr:addr><fr:route>150-0070.xml</fr:route><fr:title>Programming with streams</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>915</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-0071</fr:addr><fr:route>150-0071.xml</fr:route><fr:title>Infinite lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Lots of data in the world comes "lazily", sometimes even as an "infinite list":</fr:p><fr:ul><fr:li>texts, messages, and emails;</fr:li>
  <fr:li>packets for a video call;</fr:li>
  <fr:li>song bytes;</fr:li>
  <fr:li>digits of <fr:tex>\frac {1}{7}</fr:tex> or <fr:tex>\pi </fr:tex>;</fr:li>
  <fr:li>shipping orders;</fr:li>
  <fr:li>tapped buttons on a keyboard or mobile app;</fr:li>
  <fr:li>...</fr:li></fr:ul><fr:p>You never have all the data at once, but it comes one element at a time.</fr:p><fr:p>What happens if we try to make an infinite list?</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* repeat : 'a -&gt; 'a list *)
fun repeat (x : 'a) : 'a list = x :: repeat x
</html:code></fr:pre><fr:p>This definition does not go by recursion on anything (no parameter shrinks), and an evaluation trace would go on forever:</fr:p><fr:tex
display="block">   \begin {aligned}     &amp;\texttt {repeat x} \\     &amp;\Longrightarrow  \texttt {x :: repeat x} \\     &amp;\Longrightarrow  \texttt {x :: x :: repeat x} \\     &amp;\Longrightarrow  \texttt {x :: x :: x :: repeat x} \\     &amp;\Longrightarrow  \cdots    \end {aligned} </fr:tex><fr:p>What if all of the data wasn't computed immediately, but instead it was <fr:em>available on request</fr:em>?</fr:p><fr:p>Since functions are values, <fr:code>fn () =&gt; repeat x</fr:code> is a value. However, applying it to <fr:code>()</fr:code> still loops.</fr:p><fr:p>What if we could define (informally) <fr:code>repeat x = fn () =&gt; x :: repeat x</fr:code>? This doesn't exactly typecheck, since <fr:code>x : 'a</fr:code> but <fr:code>repeat x : unit -&gt; 'a list</fr:code>, so we cannot use <fr:code>::</fr:code>. But, we can define a different type to make this work.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>916</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0072</fr:addr><fr:route>150-0072.xml</fr:route><fr:title>Suspension</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:code>v : unit -&gt; t</fr:code> is called a <fr:em>suspension</fr:em> (or <fr:em>thunk</fr:em>), since it contains a "suspended", not-yet-evaluated expression of type <fr:code>t</fr:code>.</fr:p><fr:p>We suspend an expression <fr:code>e : t</fr:code> via <fr:code>fn () =&gt; e</fr:code>.</fr:p><fr:p>To compute the result of the expression <fr:code>e</fr:code>, we evaluate <fr:code>v ()</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>920</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0073</fr:addr><fr:route>150-0073.xml</fr:route><fr:title>Stream</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using a <fr:link
href="150-0072.xml"
type="local"
addr="150-0072">suspension</fr:link>, we can define a type of streams as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a stream = Stream of unit -&gt; 'a * 'a stream
</html:code></fr:pre><fr:p>Here, <fr:code>Stream</fr:code> takes the role of <fr:code>::</fr:code>, but storing a suspension of a first element and the remainder of the stream.</fr:p><fr:p>Note that in this formulation, <fr:em>every stream is infinite</fr:em>.</fr:p><fr:p>The following helper function computes the first element of a stream and its tail:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* expose : 'a stream -&gt; 'a * 'a stream *)
fun expose (Stream susp : 'a stream) : 'a * 'a stream = susp ()
</html:code></fr:pre><fr:p>We call the first element of a stream its head, and the remainder its tail.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fst (x, y) = x
fun snd (x, y) = y

fun head (s : 'a stream) : 'a = fst (expose s)
fun tail (s : 'a stream) : 'a stream = snd (expose s)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>923</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0074</fr:addr><fr:route>150-0074.xml</fr:route><fr:title>Infinite stream of a repeated value</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can make <fr:ref
addr="150-0071"
href="150-0071.xml"
taxon="Idea"></fr:ref> into a reality by defining a <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">stream</fr:link> instead of a list:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun repeat (x : 'a) : 'a stream = Stream (fn () =&gt; (x, repeat x))
</html:code></fr:pre><fr:p>We can ask for a few elements from the stream as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val ones : int stream = repeat 1

val (a, ones') = expose ones
val () = Test.int ("first element of ones", 1, a)

val (b, ones'') = expose ones'
val () = Test.int ("second element of ones", 1, b)

val (c, ones''') = expose ones''
val () = Test.int ("third element of ones", 1, c)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>924</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0077</fr:addr><fr:route>150-0077.xml</fr:route><fr:title>Corecursion</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Definitions such as <fr:ref
addr="150-0074"
href="150-0074.xml"
taxon="Example"></fr:ref> do not go by recursion on an input; nothing needs to ever shrink. Instead, they go by <fr:em>corecursion</fr:em>, producing a finite amount of data but offering to produce more if desired.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>925</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-0075</fr:addr><fr:route>150-0075.xml</fr:route><fr:title>Infinite data, finite observation</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Even though a <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">stream</fr:link> represents infinite data, we can only ask to compute finitely much of it.</fr:p><fr:p>Similarly, the function <fr:code>fn n =&gt; n * n</fr:code> stores infinitely much data (<fr:code>0</fr:code>, <fr:code>1</fr:code>, <fr:code>4</fr:code>, <fr:code>9</fr:code>, ...), and we can ask for whatever data we want, but only finitely many times.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>928</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0076</fr:addr><fr:route>150-0076.xml</fr:route><fr:title>Stream of natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>How could we make the stream <fr:code>0, 1, 2, 3, 4, ...</fr:code> of all natural numbers? We might try:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val nats : int stream =
  Stream (fn () =&gt; (0,
  Stream (fn () =&gt; (1,
  Stream (fn () =&gt; (2, ...
  ))))))
</html:code></fr:pre><fr:p>However, we can never finish typing the <fr:code>...</fr:code>. Instead, we compute something more general: all of the natural numbers starting from <fr:code>n</fr:code>. Then, <fr:code>nats</fr:code> is a special case, choosing <fr:code>0</fr:code> for <fr:code>n</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* natsFrom : int -&gt; int stream
 * REQUIRES: true
 * ENSURES: natsFrom n ==&gt; s, where the elements of s are n, (n + 1), (n + 2), (n + 3), ...
 *)
fun natsFrom (n : int) : int stream =
  Stream (fn () =&gt; (n, natsFrom (n + 1)))

val nats : int stream = natsFrom 0
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>930</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0078</fr:addr><fr:route>150-0078.xml</fr:route><fr:title>Finite prefix of a stream</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To get the first <fr:code>n</fr:code> elements of a stream, we can go by <fr:em>recursion</fr:em> on <fr:code>n</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* take : 'a stream * int -&gt; 'a list
 * REQUIRES: n &gt;= 0
 * ENSURES: take (s, n) ==&gt; l, where l is the first n elements of s
 *)
fun take (s, 0) = nil
  | take (s, n) =
      let
        val (a, s') = expose s
      in
        a :: take (s', n - 1)
      end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>934</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0079</fr:addr><fr:route>150-0079.xml</fr:route><fr:title>Stream map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement the <fr:link
href="150-006D.xml"
type="local"
addr="150-006D">map abstraction</fr:link> for streams:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun map (f : 'a -&gt; 'b) (s : 'a stream) : 'b stream =
  Stream (fn () =&gt;
    let
      val (a, s') = expose s
    in
      (f a, map f s')
    end
  )
</html:code></fr:pre><fr:p>To get the stream <fr:code>0, 2, 4, 8, ...</fr:code> of even numbers, we can use <fr:code>map</fr:code> on <fr:code>nats</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val evens : int stream = map (fn x =&gt; 2 * x) nats
</html:code></fr:pre><fr:p>Notice that this function is <fr:em>lazy</fr:em>, only exposing <fr:code>s</fr:code> to get its head when necessary.</fr:p><fr:p>In contrast, the following function is <fr:em>not</fr:em> lazy, <fr:link
href="150-0067.xml"
type="local"
addr="150-0067">staging</fr:link> <fr:code>expose s</fr:code> unnecessarily:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun badMap (f : 'a -&gt; 'b) (s : 'a stream) : 'b stream =
  let
    val (a, s') = expose s
  in
    Stream (fn () =&gt; (f a, badMap f s'))
  end
</html:code></fr:pre><fr:p>It is not desirable to expose <fr:code>s</fr:code> immediately, since we only need <fr:code>a</fr:code> once asked to compute the first element of the result.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>935</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-007A</fr:addr><fr:route>150-007A.xml</fr:route><fr:title>Maximal laziness</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a function on streams is <fr:em>maximally lazy</fr:em> when it exposes as few elements of input streams as possible at any given point in evaluation.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>947</fr:anchor><fr:addr>150-007C</fr:addr><fr:route>150-007C.xml</fr:route><fr:title>Coinduction</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>937</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-007D</fr:addr><fr:route>150-007D.xml</fr:route><fr:title>Extensional equivalence at <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">stream</fr:link> type: coinduction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>t</fr:code> be an arbitrary type, and let <fr:code>s0</fr:code> and <fr:code>s0'</fr:code> be of type <fr:code>t stream</fr:code>. To show that <fr:tex>\texttt {s0} \cong  \texttt {s0'}</fr:tex>:</fr:p><fr:ol><fr:li>Choose a relation <fr:tex>R(-, -)</fr:tex> on pairs of <fr:code>t stream</fr:code>s that relates pairs of streams that you expect to be equivalent.</fr:li>
  <fr:li><fr:strong>Start State:</fr:strong> Show that <fr:tex>R(\texttt {s0}, \texttt {s0'})</fr:tex>, guaranteeing that the streams you care about are related.</fr:li>
  <fr:li><fr:strong>Preservation:</fr:strong> Then, show that for all <fr:code>s</fr:code> and <fr:code>s'</fr:code>, if <fr:tex>R(\texttt {s}, \texttt {s'})</fr:tex>, then:
    <fr:ol><fr:li>the heads are the same, <fr:tex>\texttt {head s} \cong  \texttt {head s'}</fr:tex> (the "co-base case", since no more stream data comes after the head); and</fr:li>
      <fr:li>the tails stay related, <fr:tex>R(\texttt {tail s}, \texttt {tail s'})</fr:tex> (the "coinductive conclusion", dual to the inductive hypothesis).</fr:li></fr:ol></fr:li></fr:ol><fr:p>This proof technique is called <fr:em>coinduction</fr:em>.</fr:p><fr:p>Notice that this definition has some similarities with <fr:link
href="150-000T.xml"
type="local"
addr="150-000T">extensional equivalence at function types</fr:link>: both check that you see equivalent results when you use the expressions in equivalent ways.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>939</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-007G</fr:addr><fr:route>150-007G.xml</fr:route><fr:title>Mapping over a repeated stream</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t1</fr:code> and <fr:code>t2</fr:code> and values <fr:code>f : t1 -&gt; t2</fr:code> and <fr:code>x : t1</fr:code>, we have <fr:tex
display="block">\texttt {map f (repeat x)} \cong  \texttt {repeat (f x)}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>938</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#184</fr:addr><fr:route>unstable-184.xml</fr:route><fr:parent>150-007G</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>f</fr:code> and <fr:code>x</fr:code> be arbitrary.
  We prove that <fr:tex>\texttt {map f (repeat x)} \cong  \texttt {repeat (f x)}</fr:tex> by coinduction.
  <fr:ol><fr:li>Choose <fr:tex>R = \{(\texttt {map f (repeat x)}, \texttt {repeat (f x)})\} \}</fr:tex>. In other words, choose to relate exactly the two sides of the equation.</fr:li>
    <fr:li><fr:strong>Start State:</fr:strong> Clearly, we have <fr:tex>R(\texttt {map f (repeat x)}, \texttt {repeat (f x)})</fr:tex> by construction.</fr:li>
    <fr:li><fr:strong>Preservation:</fr:strong>
      Let <fr:code>s</fr:code> and <fr:code>s'</fr:code> be arbitrary, and assume that <fr:tex>R(\texttt {s}, \texttt {s'})</fr:tex>.
      In other words, we have that <fr:code>s</fr:code> is <fr:code>map f (repeat x)</fr:code> and <fr:code>s'</fr:code> is <fr:code>repeat (f x)</fr:code>.
      <fr:ol><fr:li>
          First, we show that <fr:tex>\texttt {head s} \cong  \texttt {head s'}</fr:tex> (co-base case).
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {head s} \\               &amp;\cong  \texttt {head (map f (repeat x))} \\               &amp;\cong  \texttt {f (head (repeat x))}  &amp;&amp;\text {(def of \texttt {map})} \\               &amp;\cong  \texttt {f x}  &amp;&amp;\text {(def of \texttt {repeat})}             \end {aligned}           </fr:tex>
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {head s'} \\               &amp;\cong  \texttt {head (repeat (f x))} \\               &amp;\cong  \texttt {f x}  &amp;&amp;\text {(def of \texttt {repeat})}             \end {aligned}           </fr:tex>
          Both sides are equivalent, as desired.
        </fr:li>
        <fr:li>
          Then, we show that <fr:tex>R(\texttt {tail s}, \texttt {tail s'})</fr:tex> (coinductive conclusion).
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {tail s} \\               &amp;\cong  \texttt {tail (map f (repeat x))} \\               &amp;\cong  \texttt {map f (tail (repeat x))} &amp;&amp;\text {(def of \texttt {map})} \\               &amp;\cong  \texttt {map f (repeat x)} &amp;&amp;\text {(def of \texttt {repeat})}             \end {aligned}           </fr:tex>
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {tail s'} \\               &amp;\cong  \texttt {tail (repeat (f x))} \\               &amp;\cong  \texttt {repeat (f x)} &amp;&amp;\text {(def of \texttt {repeat})}             \end {aligned}           </fr:tex>
          Both sides are related by <fr:tex>R</fr:tex>, as desired. (In fact, they don't change from where we are now!)
        </fr:li></fr:ol></fr:li></fr:ol>

  This completes the proof.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>942</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-007F</fr:addr><fr:route>150-007F.xml</fr:route><fr:title>Increased <fr:link
href="150-0076.xml"
type="local"
addr="150-0076">stream of natural numbers</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Define the following helper function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun add m x = m + x
</html:code></fr:pre><fr:p>For all <fr:code>m</fr:code> and <fr:code>n</fr:code>, we have <fr:tex>\texttt {map (add m) (natsFrom n)} \cong  \texttt {natsFrom (m + n)}</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>941</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#185</fr:addr><fr:route>unstable-185.xml</fr:route><fr:parent>150-007F</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>m</fr:code> and <fr:code>n</fr:code> be arbitrary.
  We prove that <fr:tex>\texttt {map (add m) (natsFrom n)} \cong  \texttt {natsFrom (m + n)}</fr:tex> by coinduction.
  <fr:ol><fr:li>Choose <fr:tex>R = \{(\texttt {map (add m) (natsFrom n')}, \texttt {natsFrom (m + n')}) \mid  \texttt {n' : int} \}</fr:tex>. In other words, choose to relate both sides of the equation, <fr:em>for all</fr:em> <fr:code>n'</fr:code>, not just the <fr:code>n</fr:code> we have.</fr:li>
    <fr:li><fr:strong>Start State:</fr:strong> Clearly, we have <fr:tex>R(\texttt {map (add m) (natsFrom n)}, \texttt {natsFrom (m + n)})</fr:tex> by construction.</fr:li>
    <fr:li><fr:strong>Preservation:</fr:strong>
      Let <fr:code>s</fr:code> and <fr:code>s'</fr:code> be arbitrary, and assume that <fr:tex>R(\texttt {s}, \texttt {s'})</fr:tex>.
      In other words, we have that <fr:code>s</fr:code> is <fr:code>map (add m) (natsFrom n')</fr:code> and <fr:code>s'</fr:code> is <fr:code>natsFrom (m + n')</fr:code>, for some <fr:code>n'</fr:code>.
      <fr:ol><fr:li>
          First, we show that <fr:tex>\texttt {head s} \cong  \texttt {head s'}</fr:tex> (co-base case).
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {head s} \\               &amp;\cong  \texttt {head (map (add m) (natsFrom n'))} \\               &amp;\cong  \texttt {add m (head (natsFrom n'))}  &amp;&amp;\text {(def of \texttt {map})} \\               &amp;\cong  \texttt {add m n'}  &amp;&amp;\text {(def of \texttt {natsFrom})} \\               &amp;\cong  \texttt {m + n'}             \end {aligned}           </fr:tex>
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {head s'} \\               &amp;\cong  \texttt {head (natsFrom (m + n'))} \\               &amp;\cong  \texttt {m + n'}  &amp;&amp;\text {(def of \texttt {natsFrom})}             \end {aligned}           </fr:tex>
          Both sides are equivalent, as desired.
        </fr:li>
        <fr:li>
          Then, we show that <fr:tex>R(\texttt {tail s}, \texttt {tail s'})</fr:tex> (coinductive conclusion).
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {tail s} \\               &amp;\cong  \texttt {tail (map (add m) (natsFrom n'))} \\               &amp;\cong  \texttt {map (add m) (tail (natsFrom n'))} &amp;&amp;\text {(def of \texttt {map})} \\               &amp;\cong  \texttt {map (add m) (natsFrom (n' + 1))} &amp;&amp;\text {(def of \texttt {natsFrom})}             \end {aligned}           </fr:tex>
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {tail s'} \\               &amp;\cong  \texttt {tail (natsFrom (m + n'))} \\               &amp;\cong  \texttt {natsFrom ((m + n') + 1)} &amp;&amp;\text {(def of \texttt {natsFrom})} \\               &amp;\cong  \texttt {natsFrom (m + (n' + 1))} &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex>
          Both sides are related by <fr:tex>R</fr:tex>, as desired.
        </fr:li></fr:ol></fr:li></fr:ol>

  This completes the proof.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>944</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-007B</fr:addr><fr:route>150-007B.xml</fr:route><fr:title>Stream scan</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement the following stream function to accumulate the results of a function incorporating each element of a stream:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* scanl : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a stream -&gt; 'b stream
 * REQUIRES: true
 * ENSURES: scanl f acc (x0, x1, x2, ...) ==&gt;
 *   (acc, f (x0, acc), f (x1, f (x0, acc)), ...)
 *)
fun scanl (f : 'a * 'b -&gt; 'b) (acc : 'b) (s : 'a stream) : 'b stream =
  Stream (fn () =&gt;
    let
      val (a, s') = expose s
    in
      (acc, scanl f (f (a, acc)) s')
    end
  )
</html:code></fr:pre><fr:p>This function is reminiscent of <fr:link
href="150-0065.xml"
type="local"
addr="150-0065">list <fr:code>foldl</fr:code></fr:link>, but it produces a stream of the results over time rather than a single value.</fr:p><fr:p><fr:strong>Warning:</fr:strong> This implementation is <fr:em>not</fr:em> maximally lazy, since it exposes <fr:code>s</fr:code> even though the first element is not necessary to compute the first element of the result. However, this code will be more straightforward to prove correct.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>946</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-007E</fr:addr><fr:route>150-007E.xml</fr:route><fr:title>Natural numbers using <fr:link
href="150-007B.xml"
type="local"
addr="150-007B">stream scan</fr:link> and <fr:link
href="150-0074.xml"
type="local"
addr="150-0074"><fr:code>repeat</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>n</fr:code>, we have <fr:tex>\texttt {scanl op+ n (repeat 1)} \cong  \texttt {natsFrom n}</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>945</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#186</fr:addr><fr:route>unstable-186.xml</fr:route><fr:parent>150-007E</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>n</fr:code> be arbitrary.
  We prove that <fr:tex>\texttt {scanl op+ n (repeat 1)} \cong  \texttt {natsFrom n}</fr:tex> by coinduction.
  <fr:ol><fr:li>Choose <fr:tex>R = \{(\texttt {scanl op+ n' (repeat 1)}, \texttt {natsFrom n'}) \mid  \texttt {n' : int} \}</fr:tex>.</fr:li>
    <fr:li><fr:strong>Start State:</fr:strong> This clearly holds by construction.</fr:li>
    <fr:li><fr:strong>Preservation:</fr:strong>
      Let <fr:code>s</fr:code> and <fr:code>s'</fr:code> be arbitrary, and assume that <fr:tex>R(\texttt {s}, \texttt {s'})</fr:tex>.
      In other words, <fr:code>s</fr:code> is <fr:code>scanl op+ n' (repeat 1)</fr:code> and <fr:code>s'</fr:code> is <fr:code>natsFrom n'</fr:code>, for some <fr:code>n'</fr:code>.
      <fr:ol><fr:li>
          First, we show that <fr:tex>\texttt {head s} \cong  \texttt {head s'}</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {head s} \\               &amp;\cong  \texttt {head (scanl op+ n' (repeat 1))} \\               &amp;\cong  \texttt {n'}  &amp;&amp;\text {(def of \texttt {scanl})}             \end {aligned}           </fr:tex>
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {head s'} \\               &amp;\cong  \texttt {head (natsFrom n')} \\               &amp;\cong  \texttt {n'}  &amp;&amp;\text {(def of \texttt {natsFrom})}             \end {aligned}           </fr:tex>
          Both sides are equivalent, as desired.
        </fr:li>
        <fr:li>
          Then, we show that <fr:tex>R(\texttt {tail s}, \texttt {tail s'})</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {tail s} \\               &amp;\cong  \texttt {tail (scanl op+ n' (repeat 1))} \\               &amp;\cong  \texttt {scanl op+ (1 + n') (repeat 1)} &amp;&amp;\text {(def of \texttt {scanl})}             \end {aligned}           </fr:tex>
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {tail s'} \\               &amp;\cong  \texttt {tail (natsFrom n')} \\               &amp;\cong  \texttt {natsFrom (n' + 1)}  &amp;&amp;\text {(def of \texttt {natsFrom})} \\               &amp;\cong  \texttt {natsFrom (1 + n')}  &amp;&amp;\text {(math)}             \end {aligned}           </fr:tex>
          Both sides are related by <fr:tex>R</fr:tex>, as desired.
        </fr:li></fr:ol></fr:li></fr:ol>

  This completes the proof.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1018</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect12</fr:addr><fr:route>150-lect12.xml</fr:route><fr:title>Regular expressions I: the inductive approach</fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>25</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>, <fr:link
href="rwh.xml"
type="local"
addr="rwh">Robert Harper</fr:link>, and <fr:link
href="fp.xml"
type="local"
addr="fp">Frank Pfenning</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1006</fr:anchor><fr:addr>150-007H</fr:addr><fr:route>150-007H.xml</fr:route><fr:title>Regular languages</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>955</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-007V</fr:addr><fr:route>150-007V.xml</fr:route><fr:title>Real-world string filter goals</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We hope to easily find strings of various forms. For example:</fr:p><fr:ol><fr:li>Instances of <fr:code>Carnegie Mellon</fr:code> and <fr:code>Carnegie Melon</fr:code>, accounting for typos in a dataset.</fr:li>
  <fr:li>Image files of a certain form, like <fr:code>IMG-&lt;num&gt;.png</fr:code>, where <fr:code>&lt;num&gt;</fr:code> is representing a potentially-many-digit number.</fr:li>
  <fr:li>CMU emails, either <fr:code>@cs</fr:code> or <fr:code>@andrew</fr:code>.</fr:li>
  <fr:li>Usernames containing <fr:code>polly</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>985</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007U</fr:addr><fr:route>150-007U.xml</fr:route><fr:title>Regular expressions</fr:title></fr:frontmatter><fr:mainmatter>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Regex <fr:tex>\texttt {r}</fr:tex></html:th>

  <html:th>Language <fr:tex>\mathcal {L}(\tt r)</fr:tex></html:th>

  <html:th><fr:tex>s \in  \mathcal {L}(r)</fr:tex> when...</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>\text {a}</fr:tex></html:td>

  <html:td><fr:tex>\{\text {a}\}</fr:tex></html:td>

  <html:td><fr:tex>s = \text {a}</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathbf {0}</fr:tex></html:td>

  <html:td><fr:tex>\varnothing </fr:tex></html:td>

  <html:td>never</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>\mathbf {1}</fr:tex></html:td>

  <html:td><fr:tex>\{\texttt {""}\}</fr:tex></html:td>

  <html:td><fr:tex>s</fr:tex> is empty</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>{r_1 + r_2}</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {L}(\tt r_1) \cup  \mathcal {L}(\tt r_2)</fr:tex></html:td>

  <html:td><fr:tex>s</fr:tex> matches <fr:tex>r_1</fr:tex> or <fr:tex>r_2</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>r_1r_2</fr:tex></html:td>

  <html:td><fr:tex>\{s_1s_2 \mid  {s_1 \in  \mathcal {L}(\tt r_1)} \text { and } {s_2 \in  \mathcal {L}(\tt r_2)}\}</fr:tex></html:td>

  <html:td><fr:tex>s = s_1s_2</fr:tex>, where <fr:tex>s_1</fr:tex> matches <fr:tex>r_1</fr:tex> and <fr:tex>s_2</fr:tex> matches <fr:tex>r_2</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>r^\ast </fr:tex></html:td>

  <html:td><fr:tex>\{s_1 \cdots  s_n \mid  {s_i \in  \mathcal {L}(\tt r)} {\text { for all } i}, \text {where } n \ge  0\}</fr:tex></html:td>

  <html:td><fr:tex>s</fr:tex> is empty, or <fr:tex>s = s_1s_2</fr:tex> where <fr:tex>s_1</fr:tex> matches <fr:tex>r</fr:tex> and <fr:tex>s_2</fr:tex> matches <fr:tex>r^\ast </fr:tex></html:td>
</html:tr>

  
</html:table>
<fr:p>In these notes, we conflate strings and character lists, e.g. <fr:code>"ab"</fr:code> with <fr:code>[#"a", #"b"]</fr:code> and <fr:code>""</fr:code> with <fr:code>[]</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>986</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-007W</fr:addr><fr:route>150-007W.xml</fr:route><fr:title>Sample regular expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can represent <fr:link
href="150-007V.xml"
type="local"
addr="150-007V">our goals</fr:link> as regular expressions.</fr:p><fr:p>First, we give the following definitions for matching letters and numbers, treating <fr:tex>\text {0}</fr:tex> and <fr:tex>\text {1}</fr:tex> as characters (vs. regular expression primitives <fr:tex>\mathbf {0}</fr:tex> and <fr:tex>\mathbf {1}</fr:tex>):</fr:p><fr:tex
display="block">   \begin {aligned}     r_{\text {a-z}} &amp;= \text {a} + \text {b} + \cdots  + \text {z} \\     r_{\text {0-9}} &amp;= \text {0} + \text {1} + \cdots  + \text {9}   \end {aligned} </fr:tex><fr:p>Now, we can define regular expressions for our examples.</fr:p><fr:ol><fr:li><fr:tex>\text {Carnegie Mel}(\text {l} + 1)\text {on}</fr:tex>.</fr:li>
  <fr:li><fr:tex>\text {IMG-}r_{\text {0-9}}r_{\text {0-9}}^\ast \text {.png}</fr:tex>, assuming the number should be nonempty.</fr:li>
  <fr:li><fr:tex>r_{\text {a-z}} r_{\text {a-z}}^\ast  r_{\text {0-9}}^\ast \text {@}(\text {andrew} + \text {cs})\text {.cmu.edu}</fr:tex>.</fr:li>
  <fr:li><fr:tex>r_{\text {a-z}}^\ast  \text {polly} r_{\text {a-z}}^\ast </fr:tex>, assuming usernames only have letters.</fr:li></fr:ol><fr:p>There are infinitely many other options for each. For example, the first could alternatively be written as <fr:tex>\text {Carnegie Mellon} + \text {Carnegie Melon}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1003</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-007T</fr:addr><fr:route>150-007T.xml</fr:route><fr:title>Searching for patterns with regular expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Assume for simplicity that we only have two characters, <fr:tex>\text {a}</fr:tex> and <fr:tex>\text {b}</fr:tex>.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Regular Expression <fr:tex>r</fr:tex></html:th>

  <html:th>Language <fr:tex>\mathcal {L}(\tt r)</fr:tex></html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:tex>\text {aa}</fr:tex></html:td>

  <html:td>just <fr:code>"aa"</fr:code></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>(\text {a + b})^\ast </fr:tex></html:td>

  <html:td>all strings</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>(\text {a + b})^\ast \text {aa}(\text {a + b})^\ast </fr:tex></html:td>

  <html:td>all with two consecutive <fr:code>#"a"</fr:code>s</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:tex>(\text {a} + \mathbf {1})(b + ba)^\ast </fr:tex></html:td>

  <html:td>all strings without two consecutive <fr:code>#"a"</fr:code>s</html:td>
</html:tr>

  
</html:table>
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1005</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007K</fr:addr><fr:route>150-007K.xml</fr:route><fr:title><fr:code>regexp</fr:code> datatype</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype regexp
  = Char of char
  | Zero
  | One
  | Plus of regexp * regexp
  | Times of regexp * regexp
  | Star of regexp
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1017</fr:anchor><fr:addr>150-007I</fr:addr><fr:route>150-007I.xml</fr:route><fr:title>The inductive regular expression matcher</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We now try to efficiently determine if a given string matches a regular expression.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1008</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-007M</fr:addr><fr:route>150-007M.xml</fr:route><fr:title>An inefficient attempt at <fr:code>match</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>When we try to implement the <fr:code>match</fr:code> function directly, we notice that the <fr:code>Times</fr:code> and <fr:code>Star</fr:code> cases are very slow:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* match : regexp -&gt; char list -&gt; bool
 * REQUIRES: true
 * ENSURES: match r s ~= true  iff  s in L(r)
 *)
fun match (r : regexp) (s : char list) : bool =
  case r of
    Char a =&gt;
      ( case s of
          nil =&gt; false
        | c :: cs =&gt; a = c andalso List.null cs
      )
  | Zero =&gt; false
  | One =&gt; List.null s
  | Plus (r1, r2) =&gt; match r1 s orelse match r2 s
  | Times (r1, r2) =&gt; (* check all splits of s *)
  | Star r' =&gt; List.null s orelse (* check all splits of s *)

(* accept : regexp -&gt; string -&gt; bool
 * REQUIRES: true
 * ENSURES: accept r s ~= true  iff  s in L(r)
 *)
fun accept (r : regexp) (s : string) : bool = match r (String.explode s)
</html:code></fr:pre><fr:p>These cases have to try all possible splits of the string. For example consider matching the string <fr:code>"hello world"</fr:code> against the regexp <fr:tex>(\texttt {hello})(\texttt {world})</fr:tex>. This algorithm behaves as follows:</fr:p><fr:ol><fr:li>First, try to match <fr:code>"h"</fr:code> against <fr:tex>\texttt {hello}</fr:tex> and <fr:code>"elloworld"</fr:code> against <fr:tex>\texttt {world}</fr:tex>, which fails.</fr:li>
  <fr:li>Then, try to match <fr:code>"he"</fr:code> against <fr:tex>\texttt {hello}</fr:tex> and <fr:code>"lloworld"</fr:code> against <fr:tex>\texttt {world}</fr:tex>, which fails.</fr:li>
  <fr:li>Then, try to match <fr:code>"hel"</fr:code> against <fr:tex>\texttt {hello}</fr:tex> and <fr:code>"loworld"</fr:code> against <fr:tex>\texttt {world}</fr:tex>, which fails.</fr:li>
  <fr:li>Then, try to match <fr:code>"hell"</fr:code> against <fr:tex>\texttt {hello}</fr:tex> and <fr:code>"oworld"</fr:code> against <fr:tex>\texttt {world}</fr:tex>, which fails.</fr:li>
  <fr:li>Then, try to match <fr:code>"hello"</fr:code> against <fr:tex>\texttt {hello}</fr:tex> and <fr:code>"world"</fr:code> against <fr:tex>\texttt {world}</fr:tex>, which (finally!) succeeds.</fr:li></fr:ol><fr:p>We may wish to avoid the first four attempts, though, by being more clever: ideally, we could match whatever string is possible against <fr:tex>\texttt {hello}</fr:tex> (here, <fr:code>hello</fr:code>) and find out that the remainder is <fr:code>"world"</fr:code>, which we can also immediately match.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1011</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-007S</fr:addr><fr:route>150-007S.xml</fr:route><fr:title><fr:code>accept</fr:code> via auxiliary function <fr:code>match</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* match : regexp -&gt; char list -&gt; (char list -&gt; bool) -&gt; bool
 * REQUIRES: true
 * ENSURES:
 *   match r s p ~= true iff there exist x and y with x @ y ~= s and
 *   1. x in L(r) and
 *   2. p y ~= true.
 *)
</html:code></fr:pre><fr:p>Using this stronger function, we can implement <fr:code>accept</fr:code> as desired:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* accept : regexp -&gt; char list -&gt; bool
 * REQUIRES: true
 * ENSURES: accept r s ~= true  iff  s in L(r)
 *)
fun accept (r : regexp) (s : char list) : bool =
  match r s List.null
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1013</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-007L</fr:addr><fr:route>150-007L.xml</fr:route><fr:title>The <fr:code>match</fr:code> algorithm</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We implement <fr:link
href="150-007S.xml"
type="local"
addr="150-007S">this specification</fr:link> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix &lt;&lt;
(* op &lt;&lt; : char list * char list -&gt; bool
 * REQUIRES: s' is a suffix of s
 * ENSURES:
 *   s' &lt;&lt; s ==&gt; true iff s' is a proper suffix of s, and
 *   s' &lt;&lt; s ==&gt; false iff s' = s.
 *)
fun s' &lt;&lt; s = length s' &lt; length s

(* match : regexp -&gt; char list -&gt; (char list -&gt; bool) -&gt; bool
 * REQUIRES: true
 * ENSURES:
 *   match r s p ~= true iff there exist x and y with x @ y ~= s and
 *   1. x in L(r) and
 *   2. p y ~= true.
 *)
fun match (r : regexp) (s : char list) (p : char list -&gt; bool) : bool =
  case r of
    Char a =&gt;
      ( case s of
          nil =&gt; false
        | c :: cs =&gt; a = c andalso p cs
      )
  | Zero =&gt; false
  | One =&gt; p s
  | Plus (r1, r2) =&gt; match r1 s p orelse match r2 s p
  | Times (r1, r2) =&gt; match r1 s (fn s' =&gt; match r2 s' p)
  | Star r' =&gt;
      p s orelse
      match r' s (fn s' =&gt; s' &lt;&lt; s andalso match (Star r') s' p)
</html:code></fr:pre><fr:p>The first four cases are similar to the <fr:link
href="150-007M.xml"
type="local"
addr="150-007M">inefficient implementation</fr:link>, using a predicate <fr:code>p : char list -&gt; bool</fr:code> in place of <fr:code>List.null</fr:code>. The <fr:code>Times</fr:code> and <fr:code>Star</fr:code> cases are more interesting:</fr:p><fr:ol><fr:li>In the <fr:code>Times (r1, r2)</fr:code> case, we <fr:em>recursively change the predicate</fr:em> being used on the tail. We match <fr:code>s</fr:code> against <fr:code>r1</fr:code>, and then we ask that the remainder match <fr:code>r2</fr:code>, which in turn asks that its remainder meets <fr:code>p</fr:code> as needed.</fr:li>
  <fr:li>In the <fr:code>Star r'</fr:code> case, we essentially match for <fr:code>Plus (One, Times (r', Star r'))</fr:code>. First, we check if <fr:code>s</fr:code> is already sufficient. If not, we match <fr:code>s</fr:code> against <fr:code>r</fr:code> once, and ask that the remainder <fr:code>s'</fr:code> match <fr:code>Star r'</fr:code> again.</fr:li></fr:ol><fr:p>In all cases but <fr:code>Star r'</fr:code>, we are going by recursion on the regular expression. In the second branch of the <fr:code>Star r'</fr:code> clause, though, we match against <fr:code>Star r'</fr:code> again. To guarantee termination, we make sure that <fr:code>s'</fr:code> is strictly smaller than <fr:code>s</fr:code>, so this function goes by lexicographic (dictionary-order) recusion on the regular expression <fr:code>r</fr:code> and then the character list <fr:code>s</fr:code>. Either <fr:code>r</fr:code> shrinks, or <fr:code>r</fr:code> stays the same size and <fr:code>s</fr:code> shrinks.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1016</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-007X</fr:addr><fr:route>150-007X.xml</fr:route><fr:title>Correctness of <fr:link
href="150-007L.xml"
type="local"
addr="150-007L"><fr:code>match</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Our implementation of <fr:code>match</fr:code> meets its specification:</fr:p><fr:tex
display="block">   \texttt {match r s p} \cong  \texttt {true} \iff  \exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt r) \text { and } \texttt {p y} \cong  \texttt {true} </fr:tex><fr:p>We prove each direction separately.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1014</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#182</fr:addr><fr:route>unstable-182.xml</fr:route><fr:parent>150-007X</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>We prove <fr:strong>soundness</fr:strong>: if <fr:tex>\texttt {match r s p} \cong  \texttt {true}</fr:tex>, then <fr:tex>\exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt r) \text { and } \texttt {p y} \cong  \texttt {true}</fr:tex>.</fr:p>
  <fr:p>We go by lexicographic induction on <fr:code>r</fr:code> and then <fr:code>s</fr:code>.</fr:p>
  <fr:ol><fr:li>Case <fr:code>One</fr:code>:
      Suppose <fr:tex>\texttt {match One s p} \cong  \texttt {true}</fr:tex>.
      Then:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {p s} \\           &amp;\cong  \texttt {match One s p} &amp;&amp;\text {(\texttt {One} clause of \texttt {match})} \\           &amp;\cong  \texttt {true} &amp;&amp;\text {(assumption)}         \end {aligned}       </fr:tex>
      We have to show that there exist <fr:tex>\texttt {x}</fr:tex> and <fr:tex>\texttt {y}</fr:tex> such that <fr:tex>\texttt {x} \in  \mathcal {L}(\tt One) = \{\texttt {""}\}</fr:tex> and <fr:tex>\texttt {p y} \cong  \texttt {true}</fr:tex>.
      We are forced to choose <fr:tex>\texttt {x} = \texttt {""}</fr:tex>, since that is the only element of <fr:tex>\mathcal {L}(\tt One)</fr:tex>.
      Choosing <fr:code>y = s</fr:code> gets us <fr:tex>\texttt {p s} \cong  \texttt {true}</fr:tex> by the above argument, and we have <fr:tex>\texttt {\texttt {x @ y}} \cong  \texttt {"" @ s} \cong  \texttt {s}</fr:tex></fr:li>
    <fr:li>Case <fr:code>Plus (r1, r2)</fr:code>:
      <fr:p><fr:strong>IH1:</fr:strong> if <fr:tex>\texttt {match r1 s p} \cong  \texttt {true}</fr:tex>, then <fr:tex>\exists  \texttt {x1}, \texttt {y1}.\ \texttt {x1 @ y1} \cong  \texttt {s} \text { and } \texttt {x1} \in  \mathcal {L}(\tt r1) \text { and } \texttt {p y1} \cong  \texttt {true}</fr:tex>.</fr:p>
      <fr:p><fr:strong>IH2:</fr:strong> if <fr:tex>\texttt {match r2 s p} \cong  \texttt {true}</fr:tex>, then <fr:tex>\exists  \texttt {x2}, \texttt {y2}.\ \texttt {x2 @ y2} \cong  \texttt {s} \text { and } \texttt {x2} \in  \mathcal {L}(\tt r2) \text { and } \texttt {p y2} \cong  \texttt {true}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> if <fr:tex>\texttt {match (Plus (r1, r2)) s p} \cong  \texttt {true}</fr:tex>, then <fr:tex>\exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt Plus (r1, r2)) \text { and } \texttt {p y} \cong  \texttt {true}</fr:tex>.</fr:p>

      So, suppose <fr:tex>\texttt {match (Plus (r1, r2)) s p} \cong  \texttt {true}</fr:tex>.
      By definition:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {match (Plus (r1, r2)) s p} \\           &amp;\cong  \texttt {match r1 s p orelse match r2 s p}  &amp;&amp;\text {(\texttt {Plus} clause of \texttt {match})}         \end {aligned}       </fr:tex>
      By the assumption and the definition of <fr:code>orelse</fr:code>, we have that either <fr:tex>\texttt {match r1 s p} \cong  \texttt {true}</fr:tex> or <fr:tex>\texttt {match r2 s p} \cong  \texttt {true}</fr:tex>.
      Without loss of generality, assume it is the former.
      Then, we get some <fr:tex>\texttt {x1}</fr:tex> and <fr:tex>\texttt {y1}</fr:tex> such that <fr:tex>\texttt {x1 @ y1} \cong  \texttt {s}</fr:tex> and <fr:tex>\texttt {x1} \in  \mathcal {L}(\tt r1)</fr:tex> and <fr:tex>\texttt {p y1} \cong  \texttt {true}</fr:tex>.
      Let <fr:tex>\texttt {x} = \texttt {x1}</fr:tex> and <fr:tex>\texttt {y} = \texttt {y1}</fr:tex>.
      Since <fr:tex>\texttt {x1} \in  \mathcal {L}(\tt r1)</fr:tex>, it is also in <fr:tex>\mathcal {L}(\tt Plus (r1, r2)) = \mathcal {L}(\tt r1) \cup  \mathcal {L}(\tt r2)</fr:tex>.
    </fr:li></fr:ol>
  We omit the remaining cases for brevity.
</fr:mainmatter></fr:tree>
 

 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1015</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#183</fr:addr><fr:route>unstable-183.xml</fr:route><fr:parent>150-007X</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>We prove <fr:strong>completeness</fr:strong>: if <fr:tex>\exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt r) \text { and } \texttt {p y} \cong  \texttt {true}</fr:tex>, then <fr:tex>\texttt {match r s p} \cong  \texttt {true}</fr:tex>.</fr:p>
  <fr:p>We go by lexicographic induction on <fr:code>r</fr:code> and then <fr:code>s</fr:code>.</fr:p>
  <fr:ol><fr:li>Case <fr:code>One</fr:code>:
      Suppose <fr:tex>\exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt One) \text { and } \texttt {p y} \cong  \texttt {true}</fr:tex>.
      If <fr:tex>\texttt {x} \in  \mathcal {L}(\tt One)</fr:tex>, then <fr:tex>\texttt {x} = \texttt {""}</fr:tex>, since that is the only element of <fr:tex>\mathcal {L}(\tt One)</fr:tex>.
      Then, since we have <fr:tex>\texttt {x @ y} \cong  \texttt {s}</fr:tex>, we must have <fr:tex>\texttt {y} = \texttt {s}</fr:tex>, and so <fr:tex>\texttt {p s} \cong  \texttt {true}</fr:tex>.
      By the <fr:code>One</fr:code> clause of <fr:code>match</fr:code>, this means that <fr:tex>\texttt {match r s p} \cong  \texttt {true}</fr:tex>, as desired.
    </fr:li>
    <fr:li>Case <fr:code>Plus (r1, r2)</fr:code>:
      <fr:p><fr:strong>IH1:</fr:strong> if <fr:tex>\exists  \texttt {x1}, \texttt {y1}.\ \texttt {x1 @ y1} \cong  \texttt {s} \text { and } \texttt {x1} \in  \mathcal {L}(\tt r1) \text { and } \texttt {p y1} \cong  \texttt {true}</fr:tex>, then <fr:tex>\texttt {match r1 s p} \cong  \texttt {true}</fr:tex>.</fr:p>
      <fr:p><fr:strong>IH2:</fr:strong> if <fr:tex>\exists  \texttt {x2}, \texttt {y2}.\ \texttt {x2 @ y2} \cong  \texttt {s} \text { and } \texttt {x2} \in  \mathcal {L}(\tt r2) \text { and } \texttt {p y2} \cong  \texttt {true}</fr:tex>, then <fr:tex>\texttt {match r2 s p} \cong  \texttt {true}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> if <fr:tex>\exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt Plus (r1, r2)) \text { and } \texttt {p y} \cong  \texttt {true}</fr:tex>, then <fr:tex>\texttt {match (Plus (r1, r2)) s p} \cong  \texttt {true}</fr:tex>.</fr:p>

      So, suppose <fr:tex>\exists  \texttt {x}, \texttt {y}.\ \texttt {x @ y} \cong  \texttt {s} \text { and } \texttt {x} \in  \mathcal {L}(\tt Plus (r1, r2)) \text { and } \texttt {p y} \cong  \texttt {true}</fr:tex>.
      If <fr:tex>\texttt {x} \in  \mathcal {L}(\tt Plus (r1, r2)) = \mathcal {L}(\tt r1) \cup  \mathcal {L}(\tt r2)</fr:tex>, then we must have <fr:tex>\texttt {x} \in  \mathcal {L}(\tt r1)</fr:tex> or <fr:tex>\texttt {x} \in  \mathcal {L}(\tt r2)</fr:tex>.
      Without loss of generality, assume it is the former.
      Then, by IH1, we have <fr:tex>\texttt {match r1 s p} \cong  \texttt {true}</fr:tex>.
      So, <fr:tex>\texttt {match (Plus (r1, r2)) s p} \cong  \texttt {true}</fr:tex>, by the definition of <fr:code>orelse</fr:code>.
    </fr:li></fr:ol>
  We omit the remaining cases for brevity.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1056</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect13</fr:addr><fr:route>150-lect13.xml</fr:route><fr:title>Regular expressions II: the coinductive approach</fr:title><fr:date><fr:year>2024</fr:year><fr:month>6</fr:month><fr:day>27</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1045</fr:anchor><fr:addr>150-007Y</fr:addr><fr:route>150-007Y.xml</fr:route><fr:title>Lazy state machines</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We now use <fr:link
href="150-lect11.xml"
type="local"
addr="150-lect11">lazy programming</fr:link> to implement regular expression matching.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1026</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007Z</fr:addr><fr:route>150-007Z.xml</fr:route><fr:title>Lazy state machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We define state machines (sometimes known as <fr:em>automata</fr:em>) as a lazy datatype like <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">streams</fr:link>, but instead of having a single tail via <fr:code>unit -&gt;</fr:code>, we have one tail per character with <fr:code>char -&gt;</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype machine = Machine of bool * (char -&gt; machine)
</html:code></fr:pre><fr:p>We always expect a current value of type <fr:code>bool</fr:code>, representing whether or not the machine is in an accepting state (i.e., would accept the empty string). We could <fr:link
href="150-0072.xml"
type="local"
addr="150-0072">suspend</fr:link> the <fr:code>bool</fr:code>, but we choose not to for convenience.</fr:p><fr:p>Similar to <fr:link
href="150-0073.xml"
type="local"
addr="150-0073"><fr:code>head</fr:code> and <fr:code>tail</fr:code> for streams</fr:link>, we define the following helpers:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* status : machine -&gt; bool *)
fun status (Machine (b, _)) = b

(* feed : machine -&gt; char -&gt; machine *)
fun feed (Machine (_, f)) c = f c
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1028</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0082</fr:addr><fr:route>150-0082.xml</fr:route><fr:title>Running a matching machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can run a machine <fr:code>m : machine</fr:code> on a string <fr:code>s : char list</fr:code> by recursively traversing <fr:code>s</fr:code>, feeding each character to <fr:code>m</fr:code>'s transition function and reading the status at the end.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* run : machine -&gt; char list -&gt; bool *)
fun run m nil       = status m
  | run m (c :: cs) = run (feed m c) cs
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1029</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0080</fr:addr><fr:route>150-0080.xml</fr:route><fr:title>Accepted language of a machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a string <fr:tex>\texttt {s}</fr:tex> is <fr:em>accepted</fr:em> by a <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">machine</fr:link> <fr:tex>\texttt {m}</fr:tex> when <fr:tex>\texttt {run m s} \cong  \texttt {true}</fr:tex>. We write <fr:tex
display="block">\mathcal {A}(\tt m) = \{\texttt {s : char list} \mid  \texttt {run m s} \cong  \texttt {true}\}</fr:tex> for the set of all strings accepted by machine <fr:tex>\texttt {m}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1032</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0081</fr:addr><fr:route>150-0081.xml</fr:route><fr:title>Always-reject machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a machine that rejects every string:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* zero : unit -&gt; machine
 * REQUIRES: true
 * ENSURES: A(zero ()) is empty
 *)
fun zero () =
  Machine (false, fn _ =&gt; zero ())
</html:code></fr:pre><fr:p>We prove the specification as follows.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1031</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#181</fr:addr><fr:route>unstable-181.xml</fr:route><fr:parent>150-0081</fr:parent></fr:frontmatter><fr:mainmatter>
  We show that <fr:tex>\mathcal {A}(\tt \texttt {zero ()})</fr:tex> is empty.
  To show a set is empty, we give a <fr:link
href="https://math.andrej.com/2010/03/29/proof-of-negation-and-proof-by-contradiction/"
type="external">proof of negation</fr:link>: we show that for all <fr:code>s : char list</fr:code>, if <fr:tex>\texttt {s} \in  \mathcal {A}(\tt \texttt {zero ()})</fr:tex>, then we have a contradiction.
  Equivalently, by the definition of <fr:link
href="150-0080.xml"
type="local"
addr="150-0080">accepted language of a machine</fr:link>, we must show that <fr:tex>\texttt {run (zero ()) s} \cong  \texttt {false}</fr:tex>.
  We prove by structural induction on <fr:code>s</fr:code>.
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {run (zero ()) nil} \\           &amp;\cong  \texttt {false}  &amp;&amp;\text {(clause 1 of \texttt {run})}         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:code>c :: cs</fr:code>:
      <fr:p><fr:strong>IH:</fr:strong> <fr:tex>\texttt {run (zero ()) cs} \cong  \texttt {false}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {run (zero ()) (c :: cs)} \cong  \texttt {false}</fr:tex>.</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {run (zero ()) (c :: cs)} \\           &amp;\cong  \texttt {run (zero ()) cs}  &amp;&amp;\text {(clause 2 of \texttt {run})} \\           &amp;\cong  \texttt {false}  &amp;&amp;\text {(IH)}         \end {aligned}       </fr:tex></fr:li></fr:ol>
  This concludes the proof.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1034</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0083</fr:addr><fr:route>150-0083.xml</fr:route><fr:title>Accept empty string machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a machine that accepts the empty string but rejects everything after that:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* one : unit -&gt; machine
 * REQUIRES: true
 * ENSURES: A(one ()) = {""}
 *)
fun one () =
  Machine (true, fn _ =&gt; zero ())
</html:code></fr:pre><fr:p>The status is <fr:code>true</fr:code>, but no matter what character we receive afterwards, we give back the <fr:link
href="150-0081.xml"
type="local"
addr="150-0081">always-reject machine</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1036</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0084</fr:addr><fr:route>150-0084.xml</fr:route><fr:title>Accept single character machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the <fr:link
href="150-0081.xml"
type="local"
addr="150-0081">always-reject machine</fr:link> and <fr:link
href="150-0083.xml"
type="local"
addr="150-0083">accept empty string machine</fr:link>, we can implement a machine that only accepts the string <fr:code>"a"</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* char : char -&gt; machine
 * REQUIRES: true
 * ENSURES: A(char a) = {"a"}
 *)
fun char a =
  Machine (false, fn c =&gt; if a = c then one () else zero ())
</html:code></fr:pre><fr:p>We do not accept the empty string initially. After receiving character <fr:code>c</fr:code>, we check if it is equal to <fr:code>a</fr:code>. If so, we provide <fr:link
href="150-0083.xml"
type="local"
addr="150-0083">accept empty string machine</fr:link>, accepting the empty string afterwards; if not, we provide <fr:link
href="150-0081.xml"
type="local"
addr="150-0081">always-reject machine</fr:link>, failing to accept.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1038</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0085</fr:addr><fr:route>150-0085.xml</fr:route><fr:title>Union of two machines</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can take the union of two machines, running them in parallel and using <fr:code>orelse</fr:code> to see if either will accept:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* plus : machine * machine -&gt; machine
 * REQUIRES: true
 * ENSURES: A(plus (m1, m2)) = A(m1) union A(m2)
 *)
fun plus (m1, m2) =
  Machine
    ( status m1 orelse status m2
    , fn c =&gt; plus (feed m1 c, feed m2 c)
    )
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1040</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0086</fr:addr><fr:route>150-0086.xml</fr:route><fr:title>Concatenation of two machines</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can concatenate two machines, matching via the first one until an accept state and then matching via the second one in parallel:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* times : machine * machine -&gt; machine
 * REQUIRES: true
 * ENSURES: A(times (m1, m2)) = {s1s2 | s1 in A(m1) and s2 in A(m2)}
 *)
fun times (m1, m2) =
  Machine
    ( status m1 andalso status m2
    , fn c =&gt;
        if status m1
          then plus (feed m2 c, times (feed m1 c, m2))
          else times (feed m1 c, m2)
    )
</html:code></fr:pre><fr:p>We accept the empty string if both machines do. Given a new character <fr:code>c</fr:code>, we consider whether or not the first machine would accept the empty string.</fr:p><fr:ol><fr:li>If so, we start up the second machine <fr:code>f2 c</fr:code>, while <fr:link
href="150-0085.xml"
type="local"
addr="150-0085">simultaneously</fr:link> continuing to feed <fr:code>c</fr:code> to the first machine with <fr:code>times (f1 c, m2)</fr:code>.</fr:li>
  <fr:li>If not, we keep matching <fr:code>c</fr:code> on the first machine with <fr:code>times (f1 c, m2)</fr:code>, waiting to start the second machine.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1042</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0087</fr:addr><fr:route>150-0087.xml</fr:route><fr:title>Iteration of a machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can iterate a machine using the <fr:link
href="150-0086.xml"
type="local"
addr="150-0086">concatenation of two machines</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* star : machine -&gt; machine
 * REQUIRES: true
 * ENSURES: A(star m) = {s1s2...sn | n &gt;= 0, and forall i, si in A(m)}
 *)
fun star m =
  Machine (true, fn c =&gt; times (feed m c, star m))
</html:code></fr:pre><fr:p>We always accept the empty string. Upon receiving a character <fr:code>c</fr:code>, we ask that <fr:code>m</fr:code> match it, and then we match <fr:code>star m</fr:code> again.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1044</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0088</fr:addr><fr:route>150-0088.xml</fr:route><fr:title>Regular expression matching using machines</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can compile every regular expression to a <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">lazy state machine</fr:link>, and then we can use <fr:link
href="150-0082.xml"
type="local"
addr="150-0082"><fr:code>run</fr:code></fr:link> to figure out if a given string is accepted.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* compile : regexp -&gt; machine
 * REQUIRES: true
 * ENSURES: A(compile r) = L(r)
 *)
fun compile (Char a) = char a
  | compile Zero = zero ()
  | compile One = one ()
  | compile (Plus (r1, r2)) = plus (compile r1, compile r2)
  | compile (Times (r1, r2)) = times (compile r1, compile r2)
  | compile (Star r) = star (compile r)

(* accept : regexp -&gt; string -&gt; bool *)
fun accept r s = run (compile r) (String.explode s)
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1055</fr:anchor><fr:addr>150-0089</fr:addr><fr:route>150-0089.xml</fr:route><fr:title>Coinductive proofs of language equivalence</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1046</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008A</fr:addr><fr:route>150-008A.xml</fr:route><fr:title>Extensional equivalence of <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">lazy state machines</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>m0</fr:code> and <fr:code>m0'</fr:code> be of type <fr:code>machine</fr:code>. To show that <fr:tex>\texttt {m0} \cong  \texttt {m0'}</fr:tex>:</fr:p><fr:ol><fr:li>Choose a relation <fr:tex>R(-, -)</fr:tex> on pairs of <fr:code>machine</fr:code>s that relates pairs of machines that you expect to be equivalent.</fr:li>
  <fr:li><fr:strong>Start State:</fr:strong> Show that <fr:tex>R(\texttt {m0}, \texttt {m0'})</fr:tex>, guaranteeing that the streams you care about are related.</fr:li>
  <fr:li><fr:strong>Preservation:</fr:strong> Then, show that for all <fr:code>m</fr:code> and <fr:code>m'</fr:code>, if <fr:tex>R(\texttt {m}, \texttt {m'})</fr:tex>, then:
    <fr:ol><fr:li>the statuses are the same, <fr:tex>\texttt {status m} \cong  \texttt {status m'}</fr:tex> (the "co-base case", since no more characters are read after the status is checked); and</fr:li>
      <fr:li>for all <fr:code>c : char</fr:code>, the feeding the machines <fr:code>c</fr:code> causes them to stay related, <fr:tex>R(\texttt {feed m c}, \texttt {feed m' c})</fr:tex> (the "coinductive conclusion", dual to the inductive hypothesis).</fr:li></fr:ol></fr:li></fr:ol><fr:p>This proof technique is called <fr:em>coinduction</fr:em>.</fr:p><fr:p>This definition is analogous to <fr:link
href="150-007D.xml"
type="local"
addr="150-007D">extensional equivalence of streams</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1047</fr:anchor><fr:taxon>Corollary</fr:taxon><fr:addr>150-008F</fr:addr><fr:route>150-008F.xml</fr:route><fr:title>Extensional equivalence implies equal accepted languages</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If <fr:tex>\texttt {m0} \cong  \texttt {m0'}</fr:tex>, then <fr:tex>\mathcal {A}(\tt \texttt {m0}) = \mathcal {A}(\tt \texttt {m0'})</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1049</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-008B</fr:addr><fr:route>150-008B.xml</fr:route><fr:title><fr:link
href="150-0081.xml"
type="local"
addr="150-0081"><fr:code>zero</fr:code></fr:link> is the right identity for <fr:link
href="150-0085.xml"
type="local"
addr="150-0085"><fr:code>plus</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>m : machine</fr:code>, we have that <fr:tex
display="block">\texttt {plus (m, zero ())} \cong  \texttt {m}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1048</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#180</fr:addr><fr:route>unstable-180.xml</fr:route><fr:parent>150-008B</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>m</fr:code> be arbitrary.
  We prove that <fr:tex>\texttt {plus (m, zero ())} \cong  \texttt {m}</fr:tex> by coinduction.
  <fr:ol><fr:li>Choose <fr:tex>R = \{(\texttt {plus (m', zero ())}, \texttt {m'}) \mid  \texttt {m' : machine}\}</fr:tex>. In other words, choose to relate exactly the two sides of the equation, for all <fr:code>m'</fr:code>.</fr:li>
    <fr:li><fr:strong>Start State:</fr:strong> Clearly, we have <fr:tex>R(\texttt {plus (m, zero ())}, \texttt {m})</fr:tex> by construction.</fr:li>
    <fr:li><fr:strong>Preservation:</fr:strong>
      Let <fr:code>m1</fr:code> be arbitrary, and assume that <fr:tex>R(\texttt {plus (m1, zero ())}, \texttt {m1})</fr:tex>.
      <fr:ol><fr:li>
          First, we show that <fr:tex>\texttt {status (plus (m1, zero ()))} \cong  \texttt {status m1}</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {status (plus (m1, zero ()))} \\               &amp;\cong  \texttt {status m1 orelse status (zero ())}  &amp;&amp;\text {(def of \texttt {plus})} \\               &amp;\cong  \texttt {status m1 orelse false}  &amp;&amp;\text {(def of \texttt {zero})} \\               &amp;\cong  \texttt {status m1}             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Let <fr:code>c</fr:code> be arbitrary.
          We show that <fr:tex>R(\texttt {feed (plus (m1, zero ())) c}, \texttt {feed m1 c})</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {feed (plus (m1, zero ())) c} \\               &amp;\cong  \texttt {plus (feed m1 c, feed (zero ()) c)}  &amp;&amp;\text {(def of \texttt {plus})} \\               &amp;\cong  \texttt {plus (feed m1 c, zero ())}  &amp;&amp;\text {(def of \texttt {zero})}             \end {aligned}           </fr:tex>
          We have that <fr:tex>\texttt {plus (feed m1 c, zero ())}</fr:tex> and <fr:tex>\texttt {feed m1 c}</fr:tex> are <fr:tex>R</fr:tex>-related, as desired.
        </fr:li></fr:ol></fr:li></fr:ol>
  This completes the proof.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1050</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-008C</fr:addr><fr:route>150-008C.xml</fr:route><fr:title><fr:link
href="150-0081.xml"
type="local"
addr="150-0081"><fr:code>zero</fr:code></fr:link> is the left annhilator for <fr:link
href="150-0086.xml"
type="local"
addr="150-0086"><fr:code>times</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>m : machine</fr:code>, we have that <fr:tex
display="block">\texttt {times (zero (), m)} \cong  \texttt {zero ()}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1052</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-008D</fr:addr><fr:route>150-008D.xml</fr:route><fr:title>Proving extensional equivalence instead of relatedness in coinduction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When proving the <fr:code>feed</fr:code> case of preservation for <fr:link
href="150-008A.xml"
type="local"
addr="150-008A">extensional equivalence of <fr:link
href="150-007Z.xml"
type="local"
addr="150-007Z">lazy state machines</fr:link></fr:link>, it is sufficient to show that <fr:tex>\texttt {feed m c} \cong  \texttt {feed m' c}</fr:tex> (rather than showing that the sides are merely related).</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1051</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#179</fr:addr><fr:route>unstable-179.xml</fr:route><fr:parent>150-008D</fr:parent></fr:frontmatter><fr:mainmatter>
  Suppose we have a relation <fr:tex>R'</fr:tex> for coinduction, and suppose <fr:tex>R'(\texttt {m}, \texttt {m'})</fr:tex> implies <fr:tex>\texttt {status m} \cong  \texttt {status m'}</fr:tex> and for all <fr:code>c</fr:code>, <fr:tex>\texttt {feed m c} \cong  \texttt {feed m' c}</fr:tex>.
  Then, we can prove <fr:tex>\texttt {feed m c} \cong  \texttt {feed m' c}</fr:tex> by coinduction.

  <fr:ol><fr:li>Choose <fr:tex>R = R' \cup  \{(\texttt {m}, \texttt {m}) \mid  \texttt {m : matcher}\}</fr:tex>. In other words, relate everything related by <fr:tex>R'</fr:tex>, and relate everything that is extensionally equivalent.</fr:li>
    <fr:li><fr:strong>Start State:</fr:strong> The start states are <fr:tex>R</fr:tex>-related because they are <fr:tex>R'</fr:tex>-related by assumption.</fr:li>
    <fr:li><fr:strong>Preservation:</fr:strong>
      Let <fr:code>m</fr:code> and <fr:code>m'</fr:code> be arbitrary, and assume that <fr:tex>R(\texttt {m}, \texttt {m'})</fr:tex>.
      <fr:ol><fr:li>
          First, we show that <fr:tex>\texttt {status m} \cong  \texttt {status m'}</fr:tex>.
          Since <fr:tex>R(\texttt {m}, \texttt {m'})</fr:tex>, by the definition of <fr:tex>R</fr:tex>, either <fr:tex>R'(\texttt {m}, \texttt {m'})</fr:tex> or <fr:tex>\texttt {m} \cong  \texttt {m'}</fr:tex>.
          If the former, we use the assumed proof; if the latter, the result is immediate.
        </fr:li>
        <fr:li>
          Let <fr:code>c</fr:code> be arbitrary.
          We show that <fr:tex>R(\texttt {feed m c}, \texttt {feed m' c})</fr:tex>.
          Since <fr:tex>R(\texttt {m}, \texttt {m'})</fr:tex>, by the definition of <fr:tex>R</fr:tex>, either <fr:tex>R'(\texttt {m}, \texttt {m'})</fr:tex> or <fr:tex>\texttt {m} \cong  \texttt {m'}</fr:tex>.
          If the former, we use the assumed proof showing extensional equivalence, which is sufficient for <fr:tex>R'</fr:tex>; if the latter, the result is immediate.
        </fr:li></fr:ol></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1054</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-008E</fr:addr><fr:route>150-008E.xml</fr:route><fr:title><fr:link
href="150-0083.xml"
type="local"
addr="150-0083"><fr:code>one</fr:code></fr:link> is the left identity for <fr:link
href="150-0086.xml"
type="local"
addr="150-0086"><fr:code>times</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>m : machine</fr:code>, we have that <fr:tex
display="block">\texttt {times (one (), m)} \cong  \texttt {m}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1053</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#178</fr:addr><fr:route>unstable-178.xml</fr:route><fr:parent>150-008E</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>m</fr:code> be arbitrary.
  We prove that <fr:tex>\texttt {times (one (), m)} \cong  \texttt {m}</fr:tex> by coinduction.
  <fr:ol><fr:li>Choose <fr:tex>R = \{(\texttt {times (one (), m')}, \texttt {m'}) \mid  \texttt {m' : matcher}\}</fr:tex>. In other words, choose to relate exactly the two sides of the equation, for all <fr:code>m'</fr:code>.</fr:li>
    <fr:li><fr:strong>Start State:</fr:strong> Clearly, we have <fr:tex>R(\texttt {times (one (), m)}, \texttt {m})</fr:tex> by construction.</fr:li>
    <fr:li><fr:strong>Preservation:</fr:strong>
      Let <fr:code>m1</fr:code> be arbitrary, and assume that <fr:tex>R(\texttt {times (one (), m1)}, \texttt {m1})</fr:tex>.
      <fr:ol><fr:li>
          First, we show that <fr:tex>\texttt {status (times (one (), m1))} \cong  \texttt {status m1}</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {status (times (one (), m1))} \\               &amp;\cong  \texttt {status (one ()) andalso status m1}  &amp;&amp;\text {(def of \texttt {times})} \\               &amp;\cong  \texttt {true andalso status m1}  &amp;&amp;\text {(def of \texttt {one})} \\               &amp;\cong  \texttt {status m1}             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Let <fr:code>c</fr:code> be arbitrary.
          We show that <fr:tex>R(\texttt {feed (times (one (), m1)) c}, \texttt {feed m1 c})</fr:tex>.
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {feed (times (one (), m1)) c} \\               &amp;\cong  \texttt {if status (one ()) then ... else ...}  &amp;&amp;\text {(def of \texttt {times})} \\               &amp;\cong  \texttt {if true then plus... else ...}  &amp;&amp;\text {(def of \texttt {one})} \\               &amp;\cong  \texttt {plus (feed m1 c, times (feed (one ()) c, m1))} \\               &amp;\cong  \texttt {plus (feed m1 c, times (zero (), m1))}  &amp;&amp;\text {(def of \texttt {one})} \\               &amp;\cong  \texttt {plus (feed m1 c, zero ())}  &amp;&amp;\text {(\texttt {zero} is left annhilator)} \\               &amp;\cong  \texttt {feed m1 c}  &amp;&amp;\text {(\texttt {zero} is right identity)}             \end {aligned}           </fr:tex>
          Here, we used <fr:ref
addr="150-008C"
href="150-008C.xml"
taxon="Theorem"></fr:ref> and <fr:ref
addr="150-008B"
href="150-008B.xml"
taxon="Theorem"></fr:ref>.
          Since we found that both sides were <fr:tex>\texttt {feed m1 c}</fr:tex>, then by <fr:ref
addr="150-008D"
href="150-008D.xml"
taxon="Lemma"></fr:ref>, we are done.
        </fr:li></fr:ol></fr:li></fr:ol>
  This completes the proof.
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1096</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect14</fr:addr><fr:route>150-lect14.xml</fr:route><fr:title>Modules I: signatures and structures</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>2</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1075</fr:anchor><fr:addr>150-008G</fr:addr><fr:route>150-008G.xml</fr:route><fr:title>Structures and signatures</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1063</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-008I</fr:addr><fr:route>150-008I.xml</fr:route><fr:title>Structures as namespaces</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can organize our declarations into namespaces, called <fr:em>structures</fr:em>. For example:</fr:p><fr:ul><fr:li>We have <fr:code>List.map</fr:code>, <fr:code>List.foldr</fr:code>, <fr:code>List.filter</fr:code>, etc. in the <fr:code>List</fr:code> structure.</fr:li>
  <fr:li>We have <fr:code>Int.compare</fr:code> in the <fr:code>Int</fr:code> structure, and <fr:code>String.compare</fr:code> in the <fr:code>String</fr:code> structure.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1065</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008J</fr:addr><fr:route>150-008J.xml</fr:route><fr:title>Structure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can declare a structure using the <fr:code>structure</fr:code> keyword, and we can write a structure using <fr:code>struct ... end</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure MyStructure =
  struct
    (* declarations here *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1066</fr:anchor><fr:taxon>Convention</fr:taxon><fr:addr>150-008L</fr:addr><fr:route>150-008L.xml</fr:route><fr:title>Structure naming</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We usually name structures using <fr:link
href="https://en.wikipedia.org/wiki/Camel_case"
type="external"><fr:code>UpperCamelCase</fr:code></fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1068</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008K</fr:addr><fr:route>150-008K.xml</fr:route><fr:title><fr:code>List</fr:code> structure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>List</fr:code> structure is defined as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure List =
  struct
    datatype 'a list = nil | :: of 'a * 'a list

    val null = fn nil =&gt; true | _ =&gt; false

    fun revAppend (nil    , acc) = acc
      | revAppend (x :: xs, acc) = revAppend (xs, x :: acc)

    fun rev l = revAppend (l, nil)

    fun map f nil       = nil
      | map f (x :: xs) = f x :: map f xs

    (* ...and more... *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1070</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008H</fr:addr><fr:route>150-008H.xml</fr:route><fr:title>Signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>signature</fr:em> is the type of a <fr:link
href="150-008J.xml"
type="local"
addr="150-008J">structure</fr:link>. We say that a structure <fr:em>ascribes</fr:em> to a signature.</fr:p><fr:p>We can declare a signature using the <fr:code>signature</fr:code> keyword, and we can write a signature using <fr:code>sig ... end</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature MY_SIGNATURE =
  sig
    (* signature specification here *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1071</fr:anchor><fr:taxon>Convention</fr:taxon><fr:addr>150-008M</fr:addr><fr:route>150-008M.xml</fr:route><fr:title>Signature naming</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We usually name signatures name using <fr:link
href="https://en.wikipedia.org/wiki/Snake_case"
type="external"><fr:code>SCREAMING_SNAKE_CASE</fr:code></fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1074</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008N</fr:addr><fr:route>150-008N.xml</fr:route><fr:title><fr:link
href="150-0073.xml"
type="local"
addr="150-0073">Stream</fr:link> signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can define a signature for streams:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature STREAM =
  sig
    datatype 'a stream = Stream of unit -&gt; 'a * 'a stream

    val expose : 'a stream -&gt; 'a * 'a stream
    val head : 'a stream -&gt; 'a
    val tail : 'a stream -&gt; 'a stream

    val take : 'a stream * int -&gt; 'a list

    val map : ('a -&gt; 'b) -&gt; 'a stream -&gt; 'b stream
  end
</html:code></fr:pre><fr:p>Then, we can define a structure <fr:code>Stream</fr:code> that ascribes to <fr:code>STREAM</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure Stream : STREAM =
  struct
    datatype 'a stream = Stream of unit -&gt; 'a * 'a stream

    fun expose (Stream susp) = susp ()

    fun fst (x, y) = x
    fun head s = fst (expose s)

    (* ... *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1090</fr:anchor><fr:addr>150-008O</fr:addr><fr:route>150-008O.xml</fr:route><fr:title>Abstract types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In <fr:link
href="150-000V.xml"
type="local"
addr="150-000V">principles of functional programming</fr:link>, we discussed <fr:em>abstraction</fr:em> as a goal: types should guide our program structure. Some types might even be hidden from view, or left <fr:em>abstract</fr:em>, to avoid clouding our thinking.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1076</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008P</fr:addr><fr:route>150-008P.xml</fr:route><fr:title>Transparent and opaque ascription</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When we write <fr:code>MyStruct : MY_SIG</fr:code>, the structure <fr:em>transparently</fr:em> ascribes to <fr:code>MY_SIG</fr:code>: all types in the signature are visible from the outside.</fr:p><fr:p>When we write <fr:code>MyStruct :&gt; MY_SIG</fr:code>, the structure <fr:em>opaquely</fr:em> ascribes to <fr:code>MY_SIG</fr:code>: all <fr:code>type t</fr:code> specifications in the signature are hidden from the outside.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1081</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008Q</fr:addr><fr:route>150-008Q.xml</fr:route><fr:title>Queues as lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can describe a <fr:link
href="https://en.wikipedia.org/wiki/Queue_(abstract_data_type)"
type="external">queue</fr:link> implementation via the following signature:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature QUEUE =
  sig
    type 'a queue  (* abstract *)

    val empty : 'a queue
    val enqueue : 'a queue -&gt; 'a -&gt; 'a queue
    val dequeue : 'a queue -&gt; ('a * 'a queue) option
  end
</html:code></fr:pre><fr:p>We can implement the signature using lists:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ListQueue : QUEUE =
  struct
    type 'a queue = 'a list

    val empty = nil
    fun enqueue (l : 'a queue) (x : 'a) : 'a queue = l @ [x]
    fun dequeue nil = NONE
      | dequeue (x :: xs) = SOME (x, xs)
  end
</html:code></fr:pre><fr:p>Here, since we used <fr:link
href="150-008P.xml"
type="local"
addr="150-008P">transparent ascription</fr:link>, we have that <fr:code>[1, 2, 3] : int ListQueue.queue</fr:code>. To hide the implementation type, we use <fr:link
href="150-008P.xml"
type="local"
addr="150-008P">opaque ascription</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ListQueue :&gt; QUEUE =
</html:code></fr:pre><fr:p>We can use <fr:code>ListQueue</fr:code> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">- structure LQ = ListQueue;
- val q : int LQ.queue = LQ.enqueue (LQ.enqueue LQ.empty 1) 2;
val q = - : int ListQueue.queue
- LQ.dequeue q;
val it = SOME (1,-) : (int * int ListQueue.queue) option
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1083</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008R</fr:addr><fr:route>150-008R.xml</fr:route><fr:title>Batched queue</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement the queues of <fr:link
href="150-008Q.xml"
type="local"
addr="150-008Q">the previous example</fr:link> more efficiently using pairs of lists:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure BatchedQueue :&gt; QUEUE =
  struct
    type 'a queue = 'a list * 'a list

    val empty = (nil, nil)
    fun enqueue (front, back) x = (front, x :: back)
    fun dequeue (x :: front, back) = SOME (x, (front, back))
      | dequeue (nil, back) =
          case List.rev back of
            nil =&gt; NONE
          | x :: front =&gt; SOME (x, (front, nil))
  end
</html:code></fr:pre><fr:p>We represent a queue via a back list and a front list. We enqueue to the back and dequeue from the front. If we try to dequeue from an empty front, we reverse the back and move it to the front.</fr:p><fr:p>The list represented by <fr:code>(front, back)</fr:code> is <fr:code>front @ rev back</fr:code>. For example, the queue <fr:code>1, 2, 3, 4, 5</fr:code> can be represented by <fr:code>([1, 2, 3], [5, 4])</fr:code> or <fr:code>([], [5, 4, 3, 2, 1])</fr:code>.</fr:p><fr:p>Implementing <fr:link
href="150-008Q.xml"
type="local"
addr="150-008Q">queues as lists</fr:link>, each enqueue is <fr:tex>\mathcal {O}(n)</fr:tex> recursive calls. Here, most enqueues and dequeues perform no recursive calls; occasionally, we get an <fr:tex>\mathcal {O}(n)</fr:tex> call to <fr:code>List.rev</fr:code>, but this averages out over time to <fr:tex>\mathcal {O}(1)</fr:tex> per operation (formally, via <fr:link
href="https://en.wikipedia.org/wiki/Amortized_analysis"
type="external">amortized analysis</fr:link>).</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1085</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008S</fr:addr><fr:route>150-008S.xml</fr:route><fr:title>Dictionary signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can define a signature for dictionaries, which are (finite) mappings from keys (here, <fr:code>string</fr:code>s) to values (here, <fr:code>'a</fr:code>):</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature DICT =
  sig
    type key = string  (* concrete *)
    type 'a entry = key * 'a  (* concrete *)
    type 'a dict  (* abstract *)

    val empty : 'a dict
    val find : key -&gt; 'a dict -&gt; 'a option
    val insert : 'a entry -&gt; 'a dict -&gt; 'a dict
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1087</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008W</fr:addr><fr:route>150-008W.xml</fr:route><fr:title>Dictionaries as lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement the <fr:link
href="150-008S.xml"
type="local"
addr="150-008S">dictionary signature</fr:link> using sorted lists:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ListDict :&gt; DICT =
  struct
    type key = string
    type 'a entry = key * 'a

    (* invariant: elements are key-sorted *)
    type 'a dict = 'a entry list

    val empty = nil

    fun find _ nil = NONE
      | find k' ((k, v) :: d) =
          case String.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; NONE
          | GREATER =&gt; find k' d

    fun insert (k', v') nil = [(k', v')]
      | insert (k', v') ((k, v) :: d) =
          case String.compare (k', k) of
            EQUAL   =&gt; (k', v') :: d
          | LESS    =&gt; d
          | GREATER =&gt; (k, v) :: insert (k', v') d
  end
</html:code></fr:pre><fr:p>However, this has the disadvantage that larger keys will be towards the end of the list, leading to slow lookup times.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1089</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008Z</fr:addr><fr:route>150-008Z.xml</fr:route><fr:title>Using the <fr:link
href="150-008S.xml"
type="local"
addr="150-008S">dictionary signature</fr:link> as a client</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the <fr:link
href="150-006P.xml"
type="local"
addr="150-006P">pipe function</fr:link> for readability, we can interact with the implementations as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure D = ListDict

val d : int D.dict =
  D.empty
  |&gt; D.insert ("Polly", 150)
  |&gt; D.insert ("Honk", 122)
  |&gt; D.insert ("Theo", 251)

val answer : int option = D.find "Polly" d
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1095</fr:anchor><fr:addr>150-008T</fr:addr><fr:route>150-008T.xml</fr:route><fr:title>Structure equivalence</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1091</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008V</fr:addr><fr:route>150-008V.xml</fr:route><fr:title>Structure equivalence via representation independence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Two structures <fr:code>M1, M2 : S</fr:code> are equivalent when:</fr:p><fr:ul><fr:li>For each abstract <fr:code>type t</fr:code>, we give a relation <fr:tex>R_\texttt {t}(-, -)</fr:tex> relating <fr:code>M1.t</fr:code> to <fr:code>M2.t</fr:code>.</fr:li>
  <fr:li>All values declared are <fr:tex>\cong </fr:tex>, where <fr:tex>R_\texttt {t}</fr:tex> is taken as the notion of equivalence for <fr:code>type t</fr:code>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1094</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008U</fr:addr><fr:route>150-008U.xml</fr:route><fr:title>Equivalence of queues</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We show that <fr:link
href="150-008Q.xml"
type="local"
addr="150-008Q"><fr:code>ListQueue</fr:code></fr:link> and <fr:link
href="150-008R.xml"
type="local"
addr="150-008R"><fr:code>BatchedQueue</fr:code></fr:link> are equivalent by giving a relation on their types and showing that the relation is preserved.</fr:p><fr:p>Recall the signature <fr:code>QUEUE</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature QUEUE =
  sig
    type 'a queue  (* abstract *)

    val empty : 'a queue
    val enqueue : 'a queue -&gt; 'a -&gt; 'a queue
    val dequeue : 'a queue -&gt; ('a * 'a queue) option
  end
</html:code></fr:pre>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1093</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#177</fr:addr><fr:route>unstable-177.xml</fr:route><fr:parent>150-008U</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:tex>R_\texttt {t}(\texttt {l}, \texttt {(front, back)})</fr:tex> be the relation <fr:tex>\texttt {l} \cong  \texttt {front @ rev back}</fr:tex>.
  We must prove that:
  <fr:ol><fr:li><fr:tex>R_\texttt {t}(\texttt {LQ.empty}, \texttt {BQ.empty})</fr:tex></fr:li>
    <fr:li>If <fr:tex>R_\texttt {t}(\texttt {lq}, \texttt {bq})</fr:tex>, then for all <fr:tex>\texttt {x}</fr:tex>, we have <fr:tex>R_\texttt {t}(\texttt {LQ.enqueue lq x}, \texttt {BQ.enqueue bq x})</fr:tex>.</fr:li>
    <fr:li>If <fr:tex>R_\texttt {t}(\texttt {lq}, \texttt {bq})</fr:tex>, then either:
      <fr:ul><fr:li><fr:tex>\texttt {LQ.dequeue lq} \cong  \texttt {BQ.dequeue lq} \cong  \texttt {NONE}</fr:tex>, or</fr:li>
        <fr:li><fr:tex>\texttt {LQ.dequeue lq} \cong  \texttt {SOME (x, lq')}</fr:tex> and <fr:tex>\texttt {BQ.dequeue bq} \cong  \texttt {SOME (x, bq')}</fr:tex> where <fr:tex>R_\texttt {t}(\texttt {lq'}, \texttt {bq'}).</fr:tex></fr:li></fr:ul></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1157</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect15</fr:addr><fr:route>150-lect15.xml</fr:route><fr:title>Modules II: functors and type classes</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>9</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is heavily inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1109</fr:anchor><fr:addr>150-008Y</fr:addr><fr:route>150-008Y.xml</fr:route><fr:title>Dictionaries revisited</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1103</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008S</fr:addr><fr:route>150-008S.xml</fr:route><fr:title>Dictionary signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can define a signature for dictionaries, which are (finite) mappings from keys (here, <fr:code>string</fr:code>s) to values (here, <fr:code>'a</fr:code>):</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature DICT =
  sig
    type key = string  (* concrete *)
    type 'a entry = key * 'a  (* concrete *)
    type 'a dict  (* abstract *)

    val empty : 'a dict
    val find : key -&gt; 'a dict -&gt; 'a option
    val insert : 'a entry -&gt; 'a dict -&gt; 'a dict
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1105</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008X</fr:addr><fr:route>150-008X.xml</fr:route><fr:title>Dictionaries as trees</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Alternatively, for lower cost, we can implement the <fr:link
href="150-008S.xml"
type="local"
addr="150-008S">dictionary signature</fr:link> using sorted trees (also called <fr:em>binary search trees</fr:em>):</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure TreeDict :&gt; DICT =
  struct
    type key = string
    type 'a entry = key * 'a

    datatype 'a tree = Empty | Node of 'a tree * 'a * 'a tree

    (* invariant: elements are key-sorted *)
    type 'a dict = 'a entry tree

    val empty = Empty

    fun find _ Empty = NONE
      | find k' (Node (l, (k, v), r)) =
          case String.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; find k' l
          | GREATER =&gt; find k' r

    fun insert (k', v') Empty = Node (Empty, (k', v'), Empty)
      | insert (k', v') (Node (l, (k, v), r)) =
          case String.compare (k', k) of
            EQUAL   =&gt; Node (l, (k', v'), r)
          | LESS    =&gt; Node (insert (k', v') l, (k, v), r)
          | GREATER =&gt; Node (l, (k, v), insert (k', v') r)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1108</fr:anchor><fr:taxon>Issue</fr:taxon><fr:addr>150-0096</fr:addr><fr:route>150-0096.xml</fr:route><fr:title>Key-polymorphic dictionaries</fr:title></fr:frontmatter><fr:mainmatter><fr:p>How could we implement the <fr:link
href="150-008S.xml"
type="local"
addr="150-008S">dictionary signature</fr:link> such that we're not committed to the key type being <fr:code>string</fr:code>? In the implementations, we only used the fact that strings can be compared. So, one idea would be as follows, making everything key-polymorphic via a type variable <fr:code>'k</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature DICT =
  sig
    type ('k, 'a) entry = 'k * 'a  (* concrete *)
    type ('k, 'a) dict  (* abstract *)

    val empty : ('k, 'a) dict
    val find : ('k * 'k -&gt; order) -&gt; 'k -&gt; ('k, 'a) dict -&gt; 'a option
    val insert : ('k * 'k -&gt; order) -&gt; ('k, 'a) entry -&gt; ('k, 'a) dict -&gt; ('k, 'a) dict
  end
</html:code></fr:pre><fr:p>We parameterize everything by <fr:code>'k</fr:code>, and we have <fr:code>find</fr:code> and <fr:code>insert</fr:code> take in comparison functions <fr:code>'k * 'k -&gt; order</fr:code>. However, there is a problem: what if a client used different comparison functions for different function calls? For example, adapting <fr:link
href="150-008Z.xml"
type="local"
addr="150-008Z">the previous usage</fr:link> adversarially using the <fr:link
href="150-0060.xml"
type="local"
addr="150-0060"><fr:code>invert : order -&gt; order</fr:code></fr:link> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure D = TreeDict

val d : int D.dict =
  D.empty
  |&gt; D.insert String.compare ("Polly", 150)
  |&gt; D.insert (invert String.compare) ("Honk", 122)

val answer : int option = D.find String.compare "Honk" d  (* NONE *)
</html:code></fr:pre><fr:p>Here, we make a dictionary with <fr:code>"Polly"</fr:code>, and then we add <fr:code>"Honk"</fr:code> to the dictionary using the <fr:em>reversed</fr:em> string comparison function, placing <fr:code>"Honk"</fr:code> to the right of <fr:code>"Polly"</fr:code>. However, when we look for <fr:code>"Honk"</fr:code>, we use the usual string comparison function, resulting in an answer of <fr:code>NONE</fr:code> even though <fr:code>"Honk"</fr:code> was present.</fr:p><fr:p>To improve the situation, we will make sure that the key type is fixed in the functor along with a known comparison function, before a client even has the opportunity to use the <fr:code>find</fr:code> or <fr:code>insert</fr:code> functions.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1124</fr:anchor><fr:addr>150-0090</fr:addr><fr:route>150-0090.xml</fr:route><fr:title>Type classes</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1111</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0091</fr:addr><fr:route>150-0091.xml</fr:route><fr:title>Type class</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>type class</fr:em> is a <fr:link
href="150-008H.xml"
type="local"
addr="150-008H">signature</fr:link> containing a type <fr:em>parameter</fr:em> (meant to be transparent) alongside some operations involving the type.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signtaure MY_TYPE_CLASS =
  sig
    type t  (* parameter *)
    val f1 : (* ...involving t... *)
    val f2 : (* ...involving t... *)
    (* ... *)
  end
</html:code></fr:pre><fr:p>The type should be transparent, since a client is meant to use the operations freely. Type classes do not hide type information; they simply classify types supporting some operations.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1116</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0092</fr:addr><fr:route>150-0092.xml</fr:route><fr:title><fr:code>ORDERED</fr:code> type class</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>ORDERED</fr:code> type class classifies types <fr:code>t</fr:code> whose elements can be compared:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature ORDERED =
  sig
    type t  (* parameter *)
    val compare : t * t -&gt; order
  end
</html:code></fr:pre><fr:p>We can implement this typeclass using integers compared in the usual way:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure IntOrdered : ORDERED =
  struct
    type t = int
    val compare = Int.compare
  end
</html:code></fr:pre><fr:p>Note the use of <fr:link
href="150-008P.xml"
type="local"
addr="150-008P">transparent ascription</fr:link>.</fr:p><fr:p>Alternatively, we can compare integers using the reverse ordering:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure IntOrdered' : ORDERED =
  struct
    type t = int
    fun compare (x, y) = Int.compare (y, x)
  end
</html:code></fr:pre><fr:p>Or, we can compare strings:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure StringOrdered : ORDERED =
  struct
    type t = string
    val compare = String.compare
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1117</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0093</fr:addr><fr:route>150-0093.xml</fr:route><fr:title>Varieties of types in signatures</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Every type in a signature can be annotated to be <fr:em>abstract</fr:em>, <fr:em>parameter</fr:em>, or <fr:em>concrete</fr:em>.</fr:p><fr:ul><fr:li>If the type is unspecified via <fr:code>type t</fr:code>, it can be:
    <fr:ul><fr:li><fr:strong>abstract</fr:strong>, if it is meant to be hidden with opaque ascription; or</fr:li>
      <fr:li><fr:strong>parameter</fr:strong>, if it is meant to be known to clients with transparent ascription.</fr:li></fr:ul></fr:li>
  <fr:li>If type type is specified via <fr:code>type t = ...</fr:code>, it is <fr:strong>concrete</fr:strong>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1118</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0094</fr:addr><fr:route>150-0094.xml</fr:route><fr:title>Partial transparency using <fr:code>where type</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the signature former <fr:code>where type</fr:code>, we can make parts of a signature transparent, even if parts remain opaque. We write <fr:code>MY_SIGATURE where type t = someKnownType</fr:code> to make <fr:code>type t</fr:code> transparently be <fr:code>someKnownType</fr:code>, leaving all other types abstract.</fr:p><fr:p>This feature is commonly used alongside <fr:link
href="150-0091.xml"
type="local"
addr="150-0091">type classes</fr:link> to reveal the definition of some type in a signature.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1123</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0095</fr:addr><fr:route>150-0095.xml</fr:route><fr:title>Dictionary signature with ordered keys</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can update the <fr:link
href="150-008S.xml"
type="local"
addr="150-008S">dictionary signature</fr:link> to include <fr:link
href="150-0092.xml"
type="local"
addr="150-0092">ordered</fr:link> keys that are a parameter:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature DICT =
  sig
    structure Key : ORDERED  (* parameter *)
    type 'a entry = Key.t * 'a  (* concrete *)
    type 'a dict  (* abstract *)

    val empty : 'a dict
    val find : Key.t -&gt; 'a dict -&gt; 'a option
    val insert : 'a entry -&gt; 'a dict -&gt; 'a dict
  end
</html:code></fr:pre><fr:p>Via <fr:link
href="150-0094.xml"
type="local"
addr="150-0094">partial transparency using <fr:code>where type</fr:code></fr:link>, we can reveal <fr:code>Key.t</fr:code> while keeping <fr:code>'a dict</fr:code> hidden:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature STRING_DICT = DICT where type Key.t = string
signature INT_DICT = DICT where type Key.t = int
</html:code></fr:pre><fr:p>When we implement a structure, we must follow the given type specifications. For example, using <fr:code>STRING_DICT</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure StringTreeDict :&gt; STRING_DICT =
  struct
    structure Key = StringOrdered
    type 'a entry = Key.t * 'a
    type 'a dict = 'a entry tree

    (* ... *)
  end
</html:code></fr:pre><fr:p>Often, we will not name signatures like <fr:code>STRING_DICT</fr:code>, using their definitions inline:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure StringTreeDict :&gt; DICT where type Key.t = string =
  (* ... *)
</html:code></fr:pre><fr:p>How could we make an implementation of <fr:code>TreeDict</fr:code> for an arbitrary key <fr:code>Key : ORDERED</fr:code>?</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1156</fr:anchor><fr:addr>150-0097</fr:addr><fr:route>150-0097.xml</fr:route><fr:title>Functors</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1138</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0098</fr:addr><fr:route>150-0098.xml</fr:route><fr:title>Functor</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>functor</fr:em> is a function that takes in a <fr:link
href="150-008J.xml"
type="local"
addr="150-008J">structure</fr:link> and produces another structure. The analogy is:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Expression Level</html:th>

  <html:th>Module Level</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td>type</html:td>

  <html:td>signature</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td>expression</html:td>

  <html:td>structure</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td>function</html:td>

  <html:td>functor</html:td>
</html:tr>

  
</html:table>
<fr:p>(Unfortunately, ideas such as "functors are values", "higher-order functors", and "functor signatures" are not present in Standard ML itself.)</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1141</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0099</fr:addr><fr:route>150-0099.xml</fr:route><fr:title>Parametric tree dictionaries</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can define a functor that takes in a structure <fr:code>K : ORDERED</fr:code> and produces an implementation of dictionaries where the key type is known to be <fr:code>Key.t</fr:code>, realized as signature <fr:code>DICT where type Key.t = Key.t</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor TreeDict (K : ORDERED) :&gt; DICT where type Key.t = K.t =
  struct
    structure Key = K
    type 'a entry = Key.t * 'a

    datatype 'a tree = Empty | Node of 'a tree * 'a * 'a tree

    (* invariant: elements are key-sorted *)
    type 'a dict = 'a entry tree

    val empty = Empty

    fun find _ Empty = NONE
      | find k' (Node (l, (k, v), r)) =
          case Key.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; find k' l
          | GREATER =&gt; find k' r

    fun insert (k', v') Empty = Node (Empty, (k', v'), Empty)
      | insert (k', v') (Node (l, (k, v), r)) =
          case Key.compare (k', k) of
            EQUAL   =&gt; Node (l, (k', v'), r)
          | LESS    =&gt; Node (insert (k', v') l, (k, v), r)
          | GREATER =&gt; Node (l, (k, v), insert (k', v') r)
  end
</html:code></fr:pre><fr:p>The implementation is the same as <fr:link
href="150-008X.xml"
type="local"
addr="150-008X">before</fr:link>, except writing <fr:code>structure Key = K</fr:code>, using <fr:code>Key.t</fr:code> instead of <fr:code>key</fr:code>, and using <fr:code>Key.compare</fr:code> instead of <fr:code>String.compare</fr:code>.</fr:p><fr:p>Now, we can create dictionaries with any comparable key type. For example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure StringTreeDict = TreeDict (StringOrdered)
structure IntTreeDict = TreeDict (IntOrdered)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1143</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009A</fr:addr><fr:route>150-009A.xml</fr:route><fr:title>Freshness of types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If a functor is called multiple times, the opaquely-ascribed types created at each call will be <fr:em>fresh</fr:em>. For example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure D1 = TreeDict (StringOrdered)
structure D2 = TreeDict (StringOrdered)

val d : D1.empty = D2.empty  (* type error: D1.empty is different from D2.empty *)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1148</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-009B</fr:addr><fr:route>150-009B.xml</fr:route><fr:title>Lexicographically ordered pairs</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Suppose we wish to implement a Chess game, where the pieces are stored as values in a dictionary. The key type might be <fr:code>char * int</fr:code>, where the <fr:code>char</fr:code> represents the column and the <fr:code>int</fr:code> represents the row. Suppose we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure CharOrdered : ORDERED =
  struct
    type t = char
    val compare = Char.compare
  end
</html:code></fr:pre><fr:p>How could combine this with <fr:code>IntCompared</fr:code> to get a structure with <fr:code>type t = char * int</fr:code>? We can define the following functor:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor PairOrdered
  ( Arg :
      sig
        structure X : ORDERED
        structure Y : ORDERED
      end
  ) : ORDERED =
  struct
    type t = Arg.X.t * Arg.Y.t
    fun compare ((x1, y1), (x2, y2)) =
      case Arg.X.compare (x1, x2) of
        EQUAL =&gt; Arg.Y.compare (y1, y2)
      | ord   =&gt; ord
  end
</html:code></fr:pre><fr:p>Here, we take in a single structure <fr:code>Arg</fr:code> which contains two sub-structures, <fr:code>X : ORDERED</fr:code> and <fr:code>Y : ORDERED</fr:code>. Like functions, structures only take in a single argument; as functions take in tuples of values, functors can take structures containing multiple structures.</fr:p><fr:p>This functor can be applied as follows, passing in a structure written using <fr:code>struct ... end</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ChessOrdered =
  PairOrdered
    ( struct
        structure X = CharOrdered
        structure Y = IntOrdered
      end
    )
</html:code></fr:pre><fr:p>Then, we can apply the <fr:code>TreeDict</fr:code> functor to get a dictionary for storing data at chess locations:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure Board = TreeDict (ChessOrdered)

(* or, equivalently, inlining the definition of ChessOrdered: *)
structure Board =
  TreeDict
    ( PairOrdered
      ( struct
          structure X = CharOrdered
          structure Y = IntOrdered
        end
      )
    )
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1151</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009C</fr:addr><fr:route>150-009C.xml</fr:route><fr:title>Functor argument syntactic sugar</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When structures take multiple arguments, it is cumbersome to write <fr:code>Arg.</fr:code> before every sub-component. So, Standard ML provides syntactic sugar where the <fr:code>Arg : sig</fr:code> and <fr:code>end</fr:code> can be left off of inputs:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor PairOrdered
  ( structure X : ORDERED
    structure Y : ORDERED
  ) : ORDERED =
  struct
    type t = X.t * Y.t
    fun compare ((x1, y1), (x2, y2)) =
      case X.compare (x1, x2) of
        EQUAL =&gt; Y.compare (y1, y2)
      | ord   =&gt; ord
  end
</html:code></fr:pre><fr:p>This is functionally the same, but it is typically more ergonomic and leads to more readable code.</fr:p><fr:p>Analogous syntactic sugar is available when a functor is applied, allowing the <fr:code>struct</fr:code> and <fr:code>end</fr:code> of an argument to be left off:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ChessOrdered =
  PairOrdered
    ( structure X = CharOrdered
      structure Y = IntOrdered
    )
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1155</fr:anchor><fr:taxon>Warning</fr:taxon><fr:addr>150-009D</fr:addr><fr:route>150-009D.xml</fr:route><fr:title>Single-argument functors</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following pairs are <fr:em>different</fr:em>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor TreeDict1 (K : ORDERED) = (* ... *)
structure StringTreeDict1 = TreeDict1 (StringOrdered)

functor TreeDict2 (structure K : ORDERED) = (* ... *)
structure StringTreeDict2 = TreeDict2 (structure K = StringOrdered)
</html:code></fr:pre><fr:p>Both pairs individually typecheck. However, the second is syntactic sugar for taking in a structure containing a single structure (analogous to a one-element tuple):</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor TreeDict2' (Arg : sig structure K : ORDERED end) = (* ... *)
structure StringTreeDict2' = TreeDict2' (struct structure K = StringOrdered end)
</html:code></fr:pre><fr:p>This version is equivalent to <fr:code>TreeDict2</fr:code>, just expanding out the syntactic sugar.</fr:p><fr:p>In this class, <fr:strong>we will always use the first approach</fr:strong>, choosing not to wrap a single structure argument in a <fr:code>struct ... end</fr:code>.</fr:p><fr:p>Note that in the following, <fr:code>Alternative</fr:code> does not typecheck:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure Alternative = TreeDict2 (structure K' = StringOrdered)
</html:code></fr:pre><fr:p>We only changed <fr:code>K</fr:code> to <fr:code>K'</fr:code> compared to <fr:code>StringTreeDict2</fr:code>. However, since we took in a structure with a single element <fr:code>structure K : ORDERED</fr:code>, passing in <fr:code>structure K' : ORDERED</fr:code> does not meet the criterion (just like if the signature asked for <fr:code>val insert</fr:code>, it would not be sufficient to write <fr:code>val insert'</fr:code>).</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1186</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect16</fr:addr><fr:route>150-lect16.xml</fr:route><fr:title>Modules III: red-black trees</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>11</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link> and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1170</fr:anchor><fr:addr>150-009E</fr:addr><fr:route>150-009E.xml</fr:route><fr:title>Intuition for red-black trees</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1164</fr:anchor><fr:taxon>Goal</fr:taxon><fr:addr>150-009G</fr:addr><fr:route>150-009G.xml</fr:route><fr:title>Self-balancing binary search tree</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Our <fr:link
href="150-0099.xml"
type="local"
addr="150-0099">implementation of dictionaries using trees</fr:link> has a major cost issue: while the operations are efficient (logarithmic time) when the tree is balanced, nothing prevents the tree from getting unbalanced.</fr:p><fr:p>We hope to implement dictionaries using trees with invariants that force them to remain balanced. Recall <fr:link
href="150-003D.xml"
type="local"
addr="150-003D">from earlier</fr:link> that a perfectly balanced tree has depth <fr:tex>\log _2(n + 1)</fr:tex> when there are <fr:tex>n</fr:tex> nodes in the tree.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1165</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009H</fr:addr><fr:route>150-009H.xml</fr:route><fr:title>Red-black invariants</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A full, balanced tree has the same number of nodes on every path from the root to each <fr:code>Empty</fr:code>. However, such trees only can have <fr:tex>2^d - 1</fr:tex> nodes, where <fr:tex>d</fr:tex> is the height (depth) of the tree. In order to maintain a similar invariant, we color some nodes <fr:em>black</fr:em> and some nodes <fr:em>red</fr:em> and only count the <fr:em>black</fr:em> nodes. The <fr:em>red</fr:em> nodes are just to fix "off-by-one" errors, where we want to add more data to a tree but don't want to increase the black height. This leads us to the following pair of invariants.</fr:p><fr:p>The <fr:em>red-black tree invariants</fr:em> require that:
<fr:ol><fr:li>Every path from the root to each <fr:code>Empty</fr:code> have the same number of black nodes, called the <fr:em>black height</fr:em>. (We treat <fr:code>Empty</fr:code> as black with black height zero.)</fr:li>
  <fr:li>There are no two red nodes adjacent to each other (referred to as <fr:em>red-red violations</fr:em>), i.e. every red parent node has two black child nodes.</fr:li></fr:ol>
The first invariant guarantees that the trees are balanced ignoring red nodes, and the second invariant ensures that ther aren't "too many" red nodes in a given tree.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1167</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-009I</fr:addr><fr:route>150-009I.xml</fr:route><fr:title>Red-black balance properties</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Every red-black tree is somewhat balanced: we have <fr:tex
display="block">d \le  2\log _2(n + 1) + 1,</fr:tex> where <fr:tex>d</fr:tex> is the depth of the tree and <fr:tex>n</fr:tex> is the number of nodes.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1166</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#176</fr:addr><fr:route>unstable-176.xml</fr:route><fr:parent>150-009I</fr:parent></fr:frontmatter><fr:mainmatter>
  By the <fr:link
href="150-009H.xml"
type="local"
addr="150-009H">red-black invariants</fr:link>, we have that:
  <fr:ul><fr:li>Every red-black tree <fr:tex>t</fr:tex> has depth <fr:tex>d</fr:tex> between the black height <fr:tex>\text {BH}(t)</fr:tex> (black nodes only) and <fr:tex>2\text {BH}(t) + 1</fr:tex> (black and red alternating): <fr:tex
display="block">\text {BH}(t) \le  d \le  2\text {BH}(t) + 1.</fr:tex></fr:li>
    <fr:li>Every red-black tree <fr:tex>t</fr:tex> has size <fr:tex>n</fr:tex> between <fr:tex>2^{\text {BH}(t)} - 1</fr:tex> and and <fr:tex>2^{2\text {BH}(t) + 1} - 1</fr:tex>: <fr:tex
display="block">2^{\text {BH}(t)} - 1 \le  n \le  2^{2\text {BH}(t) + 1} - 1.</fr:tex> Or, equivalently: <fr:tex
display="block">2^{\text {BH}(t)} \le  n + 1 \le  2^{2\text {BH}(t) + 1}.</fr:tex></fr:li></fr:ul>
  So, therefore:
  <fr:tex
display="block">     \begin {aligned}       d         &amp;\le  2\text {BH}(t) + 1 \\         &amp;= 2\log _2(2^{\text {BH}(t)}) + 1 \\         &amp;\le  2\log _2(n + 1) + 1     \end {aligned}   </fr:tex>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1168</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-009J</fr:addr><fr:route>150-009J.xml</fr:route><fr:title>Sample red-black tree</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following is a valid red-black tree:</fr:p><fr:embedded-tex
hash="ecd5dd70d5ad93d66107d34bd99a0712"><fr:embedded-tex-preamble>
  \usepackage {tikz}
  \usetikzlibrary {arrows}
  \tikzset {
    treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily },
    blacknode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=black, fill=black, text width=1.5em},
    rednode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=red, fill=red, text width=1.5em}
  }
</fr:embedded-tex-preamble><fr:embedded-tex-body>
  \begin {tikzpicture}[-&gt;,&gt;=stealth']
    \node  [blacknode] {2}
      child{ node [blacknode] {1}}
      child{ node [rednode] {7}
        child{ node [blacknode] {4}
          child{ node [rednode] {3}}
          child{ node [rednode] {5}}
        }
        child{ node [blacknode] {8}}
      }
  ;
  \end {tikzpicture}
</fr:embedded-tex-body></fr:embedded-tex><fr:p>Every path from the root to a leaf has two black nodes, so the black-height is <fr:tex>2</fr:tex>. Additionally, there are no two adjacent red nodes.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1169</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-009K</fr:addr><fr:route>150-009K.xml</fr:route><fr:title>Node insertion into <fr:link
href="150-009J.xml"
type="local"
addr="150-009J">sample red-black tree</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To insert into a red-black tree, we find its correct position and add a red node, resolving problems recursively. Recall the <fr:link
href="150-009J.xml"
type="local"
addr="150-009J">sample red-black tree</fr:link>; consider inserting a node with the data <fr:tex>6</fr:tex> to maintain the order of the tree. We add a red node:</fr:p><fr:embedded-tex
hash="8e120ced336b5a60f37d32786250f8a2"><fr:embedded-tex-preamble>
  \usepackage {tikz}
  \usetikzlibrary {arrows}
  \tikzset {
    treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily },
    blacknode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=black, fill=black, text width=1.5em},
    rednode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=red, fill=red, text width=1.5em}
  }
</fr:embedded-tex-preamble><fr:embedded-tex-body>
  \begin {tikzpicture}[-&gt;,&gt;=stealth']
    \node  [blacknode] {2}
      child{ node [blacknode] {1}}
      child{ node [rednode] {7}
        child{ node [blacknode] {4}
          child{ node [rednode] {3}}
          child{ node [rednode] {5}
            child [missing]
            child{ node [rednode] {6}}
          }
        }
        child{ node [blacknode] {8}}
      }
  ;
  \end {tikzpicture}
</fr:embedded-tex-body></fr:embedded-tex><fr:p>This <fr:tex>6</fr:tex> node is not problematic, but adding the <fr:tex>5</fr:tex> node above (at the prior recursive layer) causes a red-red violation. However, since the tree was originally valid, the next node above (<fr:tex>4</fr:tex>) must be black. Therefore, we can "rotate" the nodes <fr:tex>4</fr:tex>, <fr:tex>5</fr:tex>, and <fr:tex>7</fr:tex>, recoloring <fr:tex>6</fr:tex> to remove the red-red violation:</fr:p><fr:embedded-tex
hash="54be1bc2945631fbfae41de82ef01444"><fr:embedded-tex-preamble>
  \usepackage {tikz}
  \usetikzlibrary {arrows}
  \tikzset {
    treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily },
    blacknode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=black, fill=black, text width=1.5em},
    rednode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=red, fill=red, text width=1.5em}
  }
</fr:embedded-tex-preamble><fr:embedded-tex-body>
  \begin {tikzpicture}[-&gt;,&gt;=stealth']
    \node  [blacknode] {2}
      child{ node [blacknode] {1}}
      child{ node [rednode] {7}
        child{ node [rednode] {5}
          child{ node [blacknode] {4}
            child{ node [rednode] {3}}
            child [missing]
          }
          child{ node [blacknode] {6}}
        }
        child{ node [blacknode] {8}}
      }
  ;
  \end {tikzpicture}
</fr:embedded-tex-body></fr:embedded-tex><fr:p>Now, this subtree has root <fr:tex>5</fr:tex> instead of <fr:tex>4</fr:tex> and is a valid red-black tree. However, the new red root <fr:tex>5</fr:tex> clashes with the red <fr:tex>7</fr:tex> above it! So, we perform the same trick with nodes <fr:tex>2</fr:tex>, <fr:tex>5</fr:tex>, and <fr:tex>7</fr:tex>, rotating the tree and recoloring.</fr:p><fr:embedded-tex
hash="d4e87e05dda4d0786b5cbf1df2888b0c"><fr:embedded-tex-preamble>
  \usepackage {tikz}
  \usetikzlibrary {arrows}
  \tikzset {
    treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily },
    blacknode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=black, fill=black, text width=1.5em},
    rednode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=red, fill=red, text width=1.5em}
  }
</fr:embedded-tex-preamble><fr:embedded-tex-body>
  \begin {tikzpicture}[-&gt;,&gt;=stealth',level/.style={sibling distance = 2.5cm/#1}]
    \node  [rednode] {5}
      child{ node [blacknode] {2}
        child{ node [blacknode] {1}}
        child{ node [blacknode] {4}
          child{ node [rednode] {3}}
          child [missing]
        }
      }
      child{ node [blacknode] {7}
        child{ node [blacknode] {6}}
        child{ node [blacknode] {8}}
      }
  ;
  \end {tikzpicture}
</fr:embedded-tex-body></fr:embedded-tex><fr:p>Finally, we have a valid red-black tree, and a very balanced one at that! By inserting <fr:tex>6</fr:tex>, we were forced to reorganize the rest of the nodes, leading to a very balanced tree.</fr:p><fr:p>Notice that at each step, the black height was preserved: even when the tree was invalid, the black height was always <fr:tex>2</fr:tex>.</fr:p><fr:p>Now, we will implement this algorithm.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1185</fr:anchor><fr:addr>150-009F</fr:addr><fr:route>150-009F.xml</fr:route><fr:title>Implementation of red-black trees</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1172</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-009L</fr:addr><fr:route>150-009L.xml</fr:route><fr:title>Red-black tree type and starter code</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To implement the <fr:link
href="150-0095.xml"
type="local"
addr="150-0095">dictionary signature</fr:link>, we write some starter code similar to the <fr:link
href="150-0099.xml"
type="local"
addr="150-0099">parametric tree dictionaries</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor RBTDict (K : ORDERED) :&gt; DICT where type Key.t = K.t =
  struct
    structure Key = K
    type 'a entry = Key.t * 'a

    (* INVARIANTS:
     * 1. number of black nodes on all paths from root to Empty are the same (black height)
     * 2. all Red nodes have black children (no red-red violations)
     *)
    datatype 'a rbt
      = Empty
      | Red of 'a rbt * 'a * 'a rbt
      | Black of 'a rbt * 'a * 'a rbt

    (* INVARIANT: elements are ordered by Key.compare *)
    type 'a dict = 'a entry tree

    val empty = Empty

    fun find _ Empty = NONE
      | find k' (Red (l, (k, v), r)) =
        ( case Key.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; find k' l
          | GREATER =&gt; find k' r
        )
      | find k' (Black (l, (k, v), r)) =
        ( case Key.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; find k' l
          | GREATER =&gt; find k' r
        )

    (* TODO: insert *)
  end
</html:code></fr:pre><fr:p>The <fr:code>'a rbt</fr:code> type comes equipped with the <fr:link
href="150-009H.xml"
type="local"
addr="150-009H">red-black invariants</fr:link>. The implementation of <fr:code>find</fr:code> stays the same, aside from the fact that we must search both <fr:code>Red</fr:code> and <fr:code>Black</fr:code> nodes.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1181</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-009M</fr:addr><fr:route>150-009M.xml</fr:route><fr:title>Insert algorithm for red-black trees</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The goal is to implement the following function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* insert : 'a entry -&gt; 'a dict -&gt; 'a dict
 * REQUIRES: true
 * ENSURES: insert (k, v) t ==&gt; t', which is t with (k, v) inserted
 *)
</html:code></fr:pre><fr:p>We require <fr:code>true</fr:code>, since we assume all dictionaries satisfy the given invariant implicitly due to the <fr:code>(* INVARIANT *)</fr:code> comment. To do this, we will write two helper functions that factor the problem through helper type <fr:code>'a almost</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a almost
  = OK of 'a rbt
  | BadL of ('a rbt * 'a * 'a rbt) * 'a * 'a rbt  (* INVARIANT: all three rbts are black with the same black height *)
  | BadR of 'a rbt * 'a * ('a rbt * 'a * 'a rbt)  (* INVARIANT: all three rbts are black with the same black height *)
</html:code></fr:pre><fr:p>Here, <fr:code>'a almost</fr:code> represents a red-black tree that may have a single red-red violation at the root, based on the issue <fr:link
href="150-009K.xml"
type="local"
addr="150-009K">demonstrated</fr:link>. An <fr:code>'a almost</fr:code> can be:</fr:p><fr:ol><fr:li><fr:code>OK t</fr:code>, where <fr:code>t</fr:code> is a valid red-black tree.</fr:li>
  <fr:li><fr:code>BadL ((t1, x, t2), y, t3)</fr:code>, representing the data associated with a red-red violation on the left:
    <fr:embedded-tex
hash="edc41f945cb0592d9acff72dd120fc92"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily },
        blacknode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=black, fill=black, text width=1.5em},
        rednode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=red, fill=red, text width=1.5em},
        subtree/.style = {text centered, regular polygon, regular polygon sides = 3, inner sep=0pt, white, draw=black, fill=black, text width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;,&gt;=stealth']
        \node  [rednode] {$y$}
          child{ node [rednode] {$x$}
            child{ node [subtree] {$t_1$}}
            child{ node [subtree] {$t_2$}}
          }
          child{ node [subtree] {$t_3$}}
      ;
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li><fr:code>BadR (t1, x, (t2, y, t3))</fr:code>, representing the data associated with a red-red violation on the right:
    <fr:embedded-tex
hash="52c016eafb408a36121311132fb396fc"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        treenode/.style = {align=center, inner sep=0pt, text centered, font=\sffamily },
        blacknode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=black, fill=black, text width=1.5em},
        rednode/.style = {treenode, circle, white, font=\sffamily \bfseries , draw=red, fill=red, text width=1.5em},
        subtree/.style = {text centered, regular polygon, regular polygon sides = 3, inner sep=0pt, white, draw=black, fill=black, text width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;,&gt;=stealth']
        \node  [rednode] {$x$}
          child{ node [subtree] {$t_1$}}
          child{ node [rednode] {$y$}
            child{ node [subtree] {$t_2$}}
            child{ node [subtree] {$t_3$}}
          }
      ;
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol><fr:p>We then will write the following helper functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* ins : 'a entry -&gt; 'a entry rbt -&gt; 'a entry almost
 * REQUIRES: true
 * ENSURES:
 *   1. ins (k, v) t ==&gt; a, representing t with (k, v) inserted
 *   2. BH(a) = BH(t)
 *   3. if t is black, then a is OK
 *)

(* recolor : 'a almost -&gt; 'a rbt
 * REQUIRES: true
 * ENSURES: recolor a ==&gt; t, where inord a = inord t and the BH(t) &lt;= BH(a) + 1
 *)
fun recolor (OK t) = t
  | recolor (BadL (d1, y, t2)) = Black (Red d1, y, t2)
  | recolor (BadR (t1, x, d2)) = Black (t1, x, Red d2)

(* insert : 'a entry -&gt; 'a entry rbt -&gt; 'a entry rbt *)
fun insert (k, v) t = recolor (ins (k, v) t)
</html:code></fr:pre><fr:p>The <fr:code>ins</fr:code> function will recursively insert, preserving black height and producing an <fr:code>almost</fr:code>. The <fr:code>recolor</fr:code> function will do at most one recoloring step (in the case a red-red violation propagates all the way to the top), increasing the black height by at most <fr:tex>1</fr:tex>.</fr:p><fr:p>Now, it remains to implement <fr:code>ins</fr:code>, the central function. The invariants guarantee that the result is correct, the black-height is preserved (a property we noticed in our example), and the fact that black nodes should never immediately cause violations. We begin as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* ins : 'a entry -&gt; 'a entry rbt -&gt; 'a entry almost
 * REQUIRES: true
 * ENSURES:
 *   1. ins (k, v) t ==&gt; a, representing t with (k, v) inserted
 *   2. BH(a) = BH(t)
 *   3. if t is black, then a is OK
 *)
fun ins ((k', v') : 'a entry) (t : 'a entry rbt) : 'a entry almost =
  case t of
    Empty =&gt; OK (Red (Empty, (k', v'), Empty))
</html:code></fr:pre><fr:p>As informally specified, we always start by creating a red node.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">  | Red (l, (k, v), r) =&gt;
      ( case Key.compare (k', k) of
          EQUAL =&gt; OK (Red (l, (k', v'), r))
        | LESS =&gt;
            ( case ins (k', v') l of
                OK (Red data) =&gt; BadL (data, (k, v), r)
              | OK l' =&gt; OK (Red (l', (k, v), r))
              | _ =&gt; raise Fail "impossible by ENSURES"
            )
        | GREATER =&gt;
            ( case ins (k', v') r of
                OK (Red data) =&gt; BadR (l, (k, v), data)
              | OK r' =&gt; OK (Red (l, (k, v), r'))
              | _ =&gt; raise Fail "impossible by ENSURES"
            )
      )
</html:code></fr:pre><fr:p>When we see a red node, we look the key. If the key is at the current node, we simply replace the data. Otherwise, suppose the key is to the left; we recursively insert into <fr:code>l</fr:code>. Since this node is red, we know that <fr:code>l</fr:code> must be black; so by the ENSURES, we know that <fr:code>ins (k', v') l</fr:code> is <fr:code>OK</fr:code>. When forming the node, though, we no longer know the color of <fr:code>ins (k', v') l</fr:code> - it may be either black or red. If the left tree is red, we give back <fr:code>BadL</fr:code> (a red-red violation on the left), or otherwise we create a usual <fr:code>Red</fr:code> node. The other case is symmetric.</fr:p><fr:p>Finally, for the <fr:code>Black</fr:code> case.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">  | Black (l, (k, v), r) =&gt;
      OK
        ( case Key.compare (k', k) of
            EQUAL =&gt; Black (l, (k, v), r)
          | LESS =&gt;
              ( case ins (k', v') l of
                  OK l' =&gt; Black (l', (k, v), r)
                | BadL ((t1, x, t2), y, t3) =&gt;
                    Red (Black (t1, x, t2), y, Black (t3, (k, v), r))
                | BadR (t1, x, (t2, y, t3)) =&gt;
                    Red (Black (t1, x, t2), y, Black (t3, (k, v), r))
              )
          | GREATER =&gt;
              ( case ins (k', v') r of
                  OK r' =&gt; Black (l, (k, v), r')
                | BadL ((t1, x, t2), y, t3) =&gt;
                    Red (Black (l, (k, v), t1), x, Black (t2, y, t3))
                | BadR (t1, x, (t2, y, t3)) =&gt;
                    Red (Black (l, (k, v), t1), x, Black (t2, y, t3))
              )
        )
</html:code></fr:pre><fr:p>To meet the ENSURES, we must always give back <fr:code>OK</fr:code>. If the key is at the current node, we still replace the data. Otherwise, suppose the key is to the left; we recursively insert into <fr:code>l</fr:code>. We find that the insertion was either <fr:code>OK</fr:code> (in which case we rebuild a <fr:code>Black</fr:code> node) or a red-red violation. In the case of a violation, we perform the given tree rotations, which preserve black height and always give back valid red-black trees.</fr:p><fr:p>This completes the implementation! While the details are complex, the interface remains the same: a client can use the red-black dictionary just like any of the other dictionaries and get the same resulting behavior. We include the full code below:</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1180</fr:anchor><fr:taxon>Snippet</fr:taxon><fr:addr>#175</fr:addr><fr:route>unstable-175.xml</fr:route><fr:parent>150-009M</fr:parent></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">functor RBTDict (K : ORDERED) :&gt; DICT where type Key.t = K.t =
  struct
    structure Key = K
    type 'a entry = Key.t * 'a

    (* INVARIANTS:
     * 1. number of black nodes on all paths from root to Empty are the same (black height)
     * 2. all Red nodes have black children (no red-red violations)
     *)
    datatype 'a rbt
      = Empty
      | Red of 'a rbt * 'a * 'a rbt
      | Black of 'a rbt * 'a * 'a rbt

    (* INVARIANT: elements are ordered by Key.compare *)
    type 'a dict = 'a entry rbt

    val empty = Empty

    fun find _ Empty = NONE
      | find k' (Red (l, (k, v), r)) =
        ( case Key.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; find k' l
          | GREATER =&gt; find k' r
        )
      | find k' (Black (l, (k, v), r)) =
        ( case Key.compare (k', k) of
            EQUAL   =&gt; SOME v
          | LESS    =&gt; find k' l
          | GREATER =&gt; find k' r
        )

    local
      datatype 'a almost
        = OK of 'a rbt
        | BadL of ('a rbt * 'a * 'a rbt) * 'a * 'a rbt  (* INVARIANT: all three rbts are black with the same black height *)
        | BadR of 'a rbt * 'a * ('a rbt * 'a * 'a rbt)  (* INVARIANT: all three rbts are black with the same black height *)

        (* ins : 'a entry -&gt; 'a entry rbt -&gt; 'a entry almost
         * REQUIRES: true
         * ENSURES:
         *   1. ins (k, v) t ==&gt; a, representing t with (k, v) inserted
         *   2. BH(a) = BH(t)
         *   3. if t is black, then a is OK
         *)
        fun ins ((k', v') : 'a entry) (t : 'a entry rbt) : 'a entry almost =
          case t of
            Empty =&gt; OK (Red (Empty, (k', v'), Empty))
          | Red (l, (k, v), r) =&gt;
              ( case Key.compare (k', k) of
                  EQUAL =&gt; OK (Red (l, (k', v'), r))
                | LESS =&gt;
                    ( case ins (k', v') l of
                        OK (Red data) =&gt; BadL (data, (k, v), r)
                      | OK l' =&gt; OK (Red (l', (k, v), r))
                      | _ =&gt; raise Fail "impossible by ENSURES"
                    )
                | GREATER =&gt;
                    ( case ins (k', v') r of
                        OK (Red data) =&gt; BadR (l, (k, v), data)
                      | OK r' =&gt; OK (Red (l, (k, v), r'))
                      | _ =&gt; raise Fail "impossible by ENSURES"
                    )
              )
          | Black (l, (k, v), r) =&gt;
              OK
                ( case Key.compare (k', k) of
                    EQUAL =&gt; Black (l, (k, v), r)
                  | LESS =&gt;
                      ( case ins (k', v') l of
                          OK l' =&gt; Black (l', (k, v), r)
                        | BadL ((t1, x, t2), y, t3) =&gt;
                            Red (Black (t1, x, t2), y, Black (t3, (k, v), r))
                        | BadR (t1, x, (t2, y, t3)) =&gt;
                            Red (Black (t1, x, t2), y, Black (t3, (k, v), r))
                      )
                  | GREATER =&gt;
                      ( case ins (k', v') r of
                          OK r' =&gt; Black (l, (k, v), r')
                        | BadL ((t1, x, t2), y, t3) =&gt;
                            Red (Black (l, (k, v), t1), x, Black (t2, y, t3))
                        | BadR (t1, x, (t2, y, t3)) =&gt;
                            Red (Black (l, (k, v), t1), x, Black (t2, y, t3))
                      )
                )

      (* recolor : 'a almost -&gt; 'a rbt
       * REQUIRES: true
       * ENSURES: recolor a ==&gt; t, where inord a = inord t and the BH(t) &lt;= BH(a) + 1
       *)
      fun recolor (OK t) = t
        | recolor (BadL (d1, y, t2)) = Black (Red d1, y, t2)
        | recolor (BadR (t1, x, d2)) = Black (t1, x, Red d2)
    in
      (* insert : 'a entry -&gt; 'a dict -&gt; 'a dict
      * REQUIRES: true
      * ENSURES: insert (k, v) t ==&gt; t', which is t with (k, v) inserted
      *)
      fun insert (k, v) t = recolor (ins (k, v) t)
    end
  end
</html:code></fr:pre></fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1184</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-009N</fr:addr><fr:route>150-009N.xml</fr:route><fr:title>Alternative implementation</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To avoid the <fr:code>raise Fail "impossible by ensures"</fr:code>, we can design our types differently. For <fr:code>rbt</fr:code>, we can give the following mutually-recursive definitions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a rbt = Black of 'a black | Red of 'a red
and 'a black = Empty | Node of 'a rbt * 'a * 'a rbt
withtype 'a red = 'a black * 'a * 'a black
</html:code></fr:pre><fr:p>This defines a <fr:code>datatype 'a rbt</fr:code>, a <fr:code>datatype 'a black</fr:code>, and a <fr:code>type 'a red</fr:code>. We have that an <fr:code>'a rbt</fr:code> is either an <fr:code>'a black</fr:code> or an <fr:code>'a red</fr:code>; an <fr:code>'a black</fr:code> is either <fr:code>Empty</fr:code> or a <fr:code>Node</fr:code> of <fr:code>'a rbt</fr:code>s; and an <fr:code>'a red</fr:code> is always two <fr:code>'a black</fr:code> children. These types guarantee that the color invariant is always met: it is impossible to have a red-red violation in an <fr:code>rbt</fr:code>, by construction.</fr:p><fr:p>Then, we adjust the other definitions as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun find k' (Black b) = findBlack k' b
  | find k' (Red (l, (k, v), r)) =
    ( case Key.compare (k', k) of
        EQUAL   =&gt; SOME v
      | LESS    =&gt; findBlack k' l
      | GREATER =&gt; findBlack k' r
    )
and findBlack k' Empty = NONE
  | findBlack k' (Node (l, (k, v), r)) =
      case Key.compare (k', k) of
        EQUAL   =&gt; SOME v
      | LESS    =&gt; find k' l
      | GREATER =&gt; find k' r

local
  datatype 'a almost
    = OK of 'a rbt
    | BadL of ('a black * 'a * 'a black) * 'a * 'a black
    | BadR of 'a black * 'a * ('a black * 'a * 'a black)

  fun ins ((k', v') : 'a entry) (t : 'a entry rbt) : 'a entry almost =
    case t of
      Black t =&gt; OK (insBlack (k', v') t)
    | Red (l, (k, v), r) =&gt;
        case Key.compare (k', k) of
          EQUAL =&gt; OK (Red (l, (k', v'), r))
        | LESS =&gt;
            ( case insBlack (k', v') l of
                Red data =&gt; BadL (data, (k, v), r)
              | Black l' =&gt; OK (Red (l', (k, v), r))
            )
        | GREATER =&gt;
            ( case insBlack (k', v') r of
                Red data =&gt; BadR (l, (k, v), data)
              | Black r' =&gt; OK (Red (l, (k, v), r'))
            )
  and insBlack ((k', v') : 'a entry) (t : 'a entry black) : 'a entry rbt =
    case t of
      Empty =&gt; Red (Empty, (k', v'), Empty)
    | Node (l, (k, v), r) =&gt;
        case Key.compare (k', k) of
          EQUAL =&gt; Black (Node (l, (k', v'), r))
        | LESS =&gt;
            ( case ins (k', v') l of
                OK l' =&gt; Black (Node (l', (k, v), r))
              | BadL ((t1, x, t2), y, t3) =&gt;
                  Red (Node (Black t1, x, Black t2), y, Node (Black t3, (k, v), r))
              | BadR (t1, x, (t2, y, t3)) =&gt;
                  Red (Node (Black t1, x, Black t2), y, Node (Black t3, (k, v), r))
            )
        | GREATER =&gt;
            ( case ins (k', v') r of
                OK r' =&gt; Black (Node (l, (k, v), r'))
              | BadL ((t1, x, t2), y, t3) =&gt;
                  Red (Node (l, (k, v), Black t1), x, Node (Black t2, y, Black t3))
              | BadR (t1, x, (t2, y, t3)) =&gt;
                  Red (Node (l, (k, v), Black t1), x, Node (Black t2, y, Black t3))
            )

  fun recolor (OK t) = t
    | recolor (BadL (d1, y, t2)) = Black (Node (Red d1, y, Black t2))
    | recolor (BadR (t1, x, d2)) = Black (Node (Black t1, x, Red d2))
in
  fun insert (k, v) t = recolor (ins (k, v) t)
end
</html:code></fr:pre><fr:p>Here, the types tell us what invariants we have about the colors, so we can make <fr:code>insBlack</fr:code> always return an <fr:code>'a rbt</fr:code> (a valid tree) whereas <fr:code>ins</fr:code> returns an <fr:code>'a almost</fr:code> (which may have a violation).</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1275</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect17</fr:addr><fr:route>150-lect17.xml</fr:route><fr:title>Sequences I: introduction</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>16</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link> and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1231</fr:anchor><fr:addr>150-009O</fr:addr><fr:route>150-009O.xml</fr:route><fr:title>Motivation</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1193</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-009P</fr:addr><fr:route>150-009P.xml</fr:route><fr:title>Functional parallelism</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Parallelism and functional programming go hand-in-hand.</fr:p><fr:ul><fr:li>At a low level, parallelism involves scheduling work to processors;</fr:li>
  <fr:li>but at a high level, parallelism involves indicating which expressions can be evaluated in parallel, without baking in a schedule.</fr:li></fr:ul><fr:p><fr:link
href="150-000X.xml"
type="local"
addr="150-000X">Functional programming helps</fr:link>:</fr:p><fr:ul><fr:li>Since there are no effects (like memory updates) available, evaluation order doesn't matter, and race conditions are impossible to even describe in code.</fr:li>
  <fr:li>Higher-order functions and abstract types allow complex parallelism techniques to be implemented under the hood but retain a simple interface.</fr:li>
  <fr:li>Work and span analysis lets us predict the parallel speedup without fixing the number of processors in advance.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1230</fr:anchor><fr:taxon>Goal</fr:taxon><fr:addr>150-009Q</fr:addr><fr:route>150-009Q.xml</fr:route><fr:title>Sequences: parallel lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Lists are a common type to use for solving problems; however, their definition is inherently sequential. What if we could define a type like <fr:code>list</fr:code> that had better parallel cost? We will call such an abstract type a <fr:em>sequence</fr:em>.</fr:p><fr:p>We would want operations like <fr:code>nth</fr:code> (to get an element of the sequence), <fr:code>tabulate</fr:code> (to create a new sequence), and <fr:code>append</fr:code> (to append new sequences, where <fr:code>cons</fr:code> is a special case of appending a singleton).</fr:p><fr:p>There are many ways we could implement these operations on various underlying types, including lists, trees, and arrays. These operations have the following work/span bounds when implemented using each of these:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Operation</html:th>

  <html:th>List (W/S)</html:th>

  <html:th>Tree (W)</html:th>

  <html:th>Tree (S)</html:th>

  <html:th>Array (W)</html:th>

  <html:th>Array (S)</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td><fr:code>nth     </fr:code></html:td>

  <html:td><fr:tex>\mathcal {O}(n)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  n         )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  n         )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(1    )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>tabulate</fr:code></html:td>

  <html:td><fr:tex>\mathcal {O}(n)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(n              )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  n         )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(n    )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>append  </fr:code></html:td>

  <html:td><fr:tex>\mathcal {O}(m)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  m + \log  n)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  m + \log  n)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(m + n)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>cons    </fr:code></html:td>

  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  n         )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(\log  n         )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(n    )</fr:tex></html:td>

  <html:td><fr:tex>\mathcal {O}(1)</fr:tex></html:td>
</html:tr>

  
</html:table>
<fr:p>Lists are entirely sequential and only beat other implementations with the work of append, when <fr:tex>m</fr:tex> is small and <fr:tex>n</fr:tex> is large. Sequentially, trees are a nice middle ground between lists and arrays, always having good work. In parallel, though, arrays are unbeatable. Therefore, in this course, we will analyze the cost of sequences assuming they are implemented by arrays.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1236</fr:anchor><fr:addr>150-009R</fr:addr><fr:route>150-009R.xml</fr:route><fr:title>Cost graphs</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1232</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009S</fr:addr><fr:route>150-009S.xml</fr:route><fr:title>Cost graph</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>cost graph</fr:em> is a visualization technique for parallel processes consisting of a directed acyclic graph with designated start and end nodes. They are defined inductively as follows, where we implicitly treat all edges as top-to-bottom:</fr:p><fr:ol><fr:li>
    Atomic units are variables representing cost of an abstract operation, drawn using a hexagon:
    <fr:embedded-tex
hash="47e3f60755d4d4f26d0f504419e5c6c9"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  [hexagon] {\texttt {f}};
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>
    There is an empty cost graph <fr:tex>0</fr:tex>:
    <fr:embedded-tex
hash="f81f9820b8348f991649a49e01e0eabf"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  {$\bullet $};
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>Two cost graphs <fr:tex>G_1</fr:tex> and <fr:tex>G_2</fr:tex> can be composed in sequence, written <fr:tex>G_1 \triangleright  G_2</fr:tex>, representing data dependency:
    <fr:embedded-tex
hash="528359005d8acb8bc148f28d342173aa"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  (G1) at (0,1) {$G_1$};
        \node  (G2) at (0,0) {$G_2$};
        \path  (G1) edge (G2);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>
    Two cost graphs <fr:tex>G_1</fr:tex> and <fr:tex>G_2</fr:tex> can be composed in parallel, written <fr:tex>G_1 \otimes  G_2</fr:tex>, representing data independence:
    <fr:embedded-tex
hash="8b34a78034ef9eb4849773bd8a1b4d05"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  (G1) at (-1,0) {$G_1$};
        \node  (G2) at (1,0) {$G_2$};
        \node  (start) at (0,1) {$\bullet $};
        \node  (end) at (0,-1) {$\bullet $};
        \path  (start) edge (G1);
        \path  (start) edge (G2);
        \path  (G1) edge (end);
        \path  (G2) edge (end);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1233</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009V</fr:addr><fr:route>150-009V.xml</fr:route><fr:title>Work and span of a cost graph</fr:title></fr:frontmatter><fr:mainmatter><fr:ol><fr:li>The <fr:em>work</fr:em> of a cost graph is the sum of the costs of all hexagonal nodes in the graph.</fr:li>
  <fr:li>The <fr:em>span</fr:em> of a cost graph is the sum of the costs of the hexagonal nodes on the path from the start node to the end node with the highest cost.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1234</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-009T</fr:addr><fr:route>150-009T.xml</fr:route><fr:title>Cost graph of arithmetic expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>
  The cost graph of <fr:code>(1 + 2) * (3 + 4)</fr:code> is <fr:tex>(\texttt {+} \otimes  \texttt {+}) \triangleright  \texttt {*}</fr:tex>, depicted visually as:
  <fr:embedded-tex
hash="51862f6f28c9b5389bbd3dccf5b4b848"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node  (start) at (0, 2) {$\bullet $};
      \node [hexagon] (P1) at (-1, 1) {\texttt {+}};
      \node [hexagon] (P2) at (1, 1) {\texttt {+}};
      \node [hexagon] (T) at (0, 0) {\texttt {*}};

      \path  (start) edge (P1);
      \path  (start) edge (P2);
      \path  (P1) edge (T);
      \path  (P2) edge (T);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex></fr:p><fr:p>Assuming the cost of each arithmetic operation is <fr:tex>1</fr:tex>, the work of this graph is <fr:tex>3</fr:tex> and the span is <fr:tex>2</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1235</fr:anchor><fr:taxon>Assumption</fr:taxon><fr:addr>150-009U</fr:addr><fr:route>150-009U.xml</fr:route><fr:title>Ignoring constants</fr:title></fr:frontmatter><fr:mainmatter><fr:p>At this point in the course, we will ignore constants and cost metrics, instead only counting evaluation steps asymptotically for simplicity. Therefore, we will count all atomic hexagonal nodes as taking constant cost.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1249</fr:anchor><fr:addr>150-009W</fr:addr><fr:route>150-009W.xml</fr:route><fr:title>Sequences: indexed collections</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1239</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009X</fr:addr><fr:route>150-009X.xml</fr:route><fr:title>Limited sequence signature: indexed collection</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The sequence signature includes the following specifications:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    type 'a t  (* abstract *)
    type 'a seq = 'a t  (* concrete *)

    val tabulate : (int -&gt; 'a) -&gt; int -&gt; 'a seq
    val length : 'a seq -&gt; int
    val nth : 'a seq -&gt; int -&gt; 'a

    (* ...more to come... *)
  end
</html:code></fr:pre><fr:p>The abstract type <fr:code>'a t</fr:code> represents a sequence of <fr:code>'a</fr:code>s, where <fr:code>'a seq</fr:code> is an alias for signature readability.</fr:p><fr:p>The implementation of <fr:code>SEQUENCE</fr:code> is called <fr:code>Seq</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure Seq :&gt; SEQUENCE = (* ... *)
</html:code></fr:pre><fr:p>The full signature and documentation is available on <fr:link
href="http://www.cs.cmu.edu/~15150/resources/libraries/sequence.pdf"
type="external">the course website</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1240</fr:anchor><fr:taxon>Notation</fr:taxon><fr:addr>150-009Z</fr:addr><fr:route>150-009Z.xml</fr:route><fr:title>Mathematical representation of sequences</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We denote a sequence using the mathematical notation (<fr:em>not</fr:em> SML syntax) as <fr:tex>\langle x_0, x_1, \cdots , x_{n-1}\rangle </fr:tex> or <fr:code>&lt;x0, x1, ..., x_{n-1}&gt;</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1242</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009Y</fr:addr><fr:route>150-009Y.xml</fr:route><fr:title>Sequence <fr:code>tabulate</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.tabulate</fr:code> creates a new sequence of length <fr:code>n</fr:code>, calling a function on <fr:code>0</fr:code> through <fr:code>n - 1</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.tabulate : (int -&gt; 'a) -&gt; int -&gt; 'a Seq.t
 * REQUIRES: n &gt;= 0
 * ENSURES: Seq.tabulate f n ~= &lt;f 0, f 1, ..., f (n - 1)&gt;
 *)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="0958638bc9fe79a21c5b8adc63da3e96"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node  (start) at (0, 1) {$\bullet $};
      \node [hexagon] (f0) at (-2.5, 0) {\texttt {f}};
      \node [hexagon] (f1) at (-1, 0) {\texttt {f}};
      \node  at (0, 0) {$\cdots $};
      \node [hexagon] (f2) at (1, 0) {\texttt {f}};
      \node [hexagon] (f3) at (2.5, 0) {\texttt {f}};
      \node  (end) at (0, -1) {$\bullet $};

      \path  (start) edge (f0);
      \path  (start) edge (f1);
      \path  (start) edge (f2);
      \path  (start) edge (f3);
      \path  (f0) edge (end);
      \path  (f1) edge (end);
      \path  (f2) edge (end);
      \path  (f3) edge (end);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  Its work and span <fr:em>depend on the cost of <fr:code>f</fr:code></fr:em>, but assuming <fr:code>f</fr:code> is constant-time, then <fr:code>tabulate f n</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(1)</fr:tex>.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1244</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A0</fr:addr><fr:route>150-00A0.xml</fr:route><fr:title>Sequence <fr:code>length</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.length</fr:code> computes the length of a sequence:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.length : 'a Seq.t -&gt; int
 * REQUIRES: true
 * ENSURES: Seq.length &lt;x0, ..., x_{n-1}&gt; ~= n
 *)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as a single node, which by <fr:ref
addr="150-009U"
href="150-009U.xml"
taxon="Assumption"></fr:ref> we assume has constant-time cost:
  <fr:embedded-tex
hash="6ae01abbff0dd11e938ef8bbe940eef6"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node [hexagon] (0, 0) {\small \texttt {length}};
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1246</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A1</fr:addr><fr:route>150-00A1.xml</fr:route><fr:title>Sequence <fr:code>nth</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.nth</fr:code> retrieves an element of a sequence:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.nth : 'a Seq.t -&gt; int -&gt; 'a
 * REQUIRES: 0 &lt;= i &lt; Seq.length S
 * ENSURES: Seq.nth &lt;x0, ..., x_{n-1}&gt; i ~= x_i
 *)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as a single node, which by <fr:ref
addr="150-009U"
href="150-009U.xml"
taxon="Assumption"></fr:ref> we assume has constant-time cost:
  <fr:embedded-tex
hash="d67680d53621114194211ac9c52fd895"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node [hexagon] (0, 0) {\texttt {nth}};
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1248</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A2</fr:addr><fr:route>150-00A2.xml</fr:route><fr:title>Sequence <fr:code>map</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, <fr:link
href="150-00A0.xml"
type="local"
addr="150-00A0">sequence <fr:code>length</fr:code></fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>, we can define a <fr:code>map</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a Seq.t -&gt; 'b Seq.t
 * REQUIRES: true
 * ENSURES: map f &lt;x0, ..., x_{n-1}&gt; ~= &lt;f x0, ..., f x_{n-1}&gt;
 *)
fun map f S = Seq.tabulate (fn i =&gt; f (Seq.nth S i)) (Seq.length S)

(* or equivalently: *)
fun map f S = Seq.tabulate (f o Seq.nth S) (Seq.length S)
</html:code></fr:pre><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="12a829d63d1c06d17213383b7cdf4829"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node [hexagon] (start) at (0, 2) {\small \texttt {length}};

      \node [hexagon] (nth0) at (-2.5, 1) {\texttt {nth}};
      \node [hexagon] (f0) at (-2.5, 0) {\texttt {f}};

      \node [hexagon] (nth1) at (-1, 1) {\texttt {nth}};
      \node [hexagon] (f1) at (-1, 0) {\texttt {f}};

      \node  at (0, 0) {$\cdots $};

      \node [hexagon] (nth2) at (1, 1) {\texttt {nth}};
      \node [hexagon] (f2) at (1, 0) {\texttt {f}};

      \node [hexagon] (nth3) at (2.5, 1) {\texttt {nth}};
      \node [hexagon] (f3) at (2.5, 0) {\texttt {f}};

      \node  (end) at (0, -1) {$\bullet $};

      \path  (start) edge (nth0);
      \path  (start) edge (nth1);
      \path  (start) edge (nth2);
      \path  (start) edge (nth3);
      \path  (nth0) edge (f0);
      \path  (nth1) edge (f1);
      \path  (nth2) edge (f2);
      \path  (nth3) edge (f3);
      \path  (f0) edge (end);
      \path  (f1) edge (end);
      \path  (f2) edge (end);
      \path  (f3) edge (end);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  The work and span of <fr:code>map</fr:code> <fr:em>depend on the cost of <fr:code>f</fr:code></fr:em>, but assuming <fr:code>f</fr:code> is constant-time, then <fr:code>map f S</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(1)</fr:tex>.
</fr:p><fr:p>Although it can be easily implemented as above, this function is included in the <fr:code>SEQUENCE</fr:code> signature for convenience.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1274</fr:anchor><fr:addr>150-00A3</fr:addr><fr:route>150-00A3.xml</fr:route><fr:title>Sequences: the free monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>As given, it is not very easy to combine the data within a sequence: we have to explicitly use recursion, <fr:link
href="150-003M.xml"
type="local"
addr="150-003M">parallel evaluation of tuples</fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>. Here, we view sequences as an inductive tree-like structure, allowing them to come equipped with a <fr:link
href="150-006H.xml"
type="local"
addr="150-006H">fold abstraction</fr:link> akin to <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1251</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00A4</fr:addr><fr:route>150-00A4.xml</fr:route><fr:title>Limited sequence signature: free monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can also view sequences inductively, where every sequence arises as the combination of some singletons:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    (* ...as before... *)

    val singleton : 'a -&gt; 'a seq
    val empty : unit -&gt; 'a seq
    val append : 'a seq * 'a seq -&gt; 'a seq
    val mapreduce : ('a -&gt; 'b) -&gt; 'b -&gt; ('b * 'b -&gt; 'b) -&gt; 'a seq -&gt; 'b

    (* ...more to come... *)
  end
</html:code></fr:pre><fr:p>The functions <fr:code>singleton</fr:code>, <fr:code>empty</fr:code>, and <fr:code>append</fr:code> can be implemented using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>. (Alternatively, they can be viewed as the primitive way to construct sequences, where <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link> is implemented in terms of them; however, when working with an array-based implementation of sequences, this cost bound will be worse.) The <fr:code>mapreduce</fr:code> function is the <fr:link
href="150-006H.xml"
type="local"
addr="150-006H">fold abstraction</fr:link> for sequences built this way.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1253</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AG</fr:addr><fr:route>150-00AG.xml</fr:route><fr:title>Singleton sequence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, we can define a function to create a sequence with one element:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* singleton : 'a -&gt; 'a Seq.t
 * REQUIRES: true
 * ENSURES: singleton a ~= &lt;a&gt;
 *)
fun singleton a = Seq.tabulate (fn _ =&gt; a) 1
</html:code></fr:pre><fr:p>This function has constant work and span.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1255</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AH</fr:addr><fr:route>150-00AH.xml</fr:route><fr:title>Empty sequence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, we can define a function to create an empty sequence:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* empty : unit -&gt; 'a Seq.t
 * REQUIRES: true
 * ENSURES: empty () ~= &lt;&gt;
 *)
fun empty () = Seq.tabulate (fn _ =&gt; raise Fail "impossible") 0
</html:code></fr:pre><fr:p>This function has constant work and span.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1257</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AI</fr:addr><fr:route>150-00AI.xml</fr:route><fr:title>Sequence append</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, <fr:link
href="150-00A0.xml"
type="local"
addr="150-00A0">sequence <fr:code>length</fr:code></fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>, we can define a function to append two sequences:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* append : 'a Seq.t * 'a Seq.t -&gt; 'a Seq.t
 * REQUIRES: true
 * ENSURES: append (&lt;x0, ..., x_{m-1}&gt;, &lt;y0, ..., y_{n-1}&gt;) ~= &lt;x0, ..., x_{m-1}, y0, ..., y_{n-1}&gt;
 *)
fun append (S1, S2) =
  Seq.tabulate
    (fn i =&gt; if i &lt; Seq.length S1 then Seq.nth S1 i else Seq.nth S2 (i - Seq.length S1))
    (Seq.length S1 + Seq.length S2)
</html:code></fr:pre><fr:p>Based on the cost graphs for <fr:link
href="150-009Y.xml"
type="local"
addr="150-009Y">sequence <fr:code>tabulate</fr:code></fr:link>, <fr:link
href="150-00A0.xml"
type="local"
addr="150-00A0">sequence <fr:code>length</fr:code></fr:link>, and <fr:link
href="150-00A1.xml"
type="local"
addr="150-00A1">sequence <fr:code>nth</fr:code></fr:link>, we find that this function has work <fr:tex>\mathcal {O}(m + n)</fr:tex> and span <fr:tex>\mathcal {O}(1)</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1258</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-00A5</fr:addr><fr:route>150-00A5.xml</fr:route><fr:title>Parallel reduction of data</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We might wish to combine data in a sequence in parallel. For example, we might wish to compute:
<fr:tex
display="block">\texttt {sum &lt;1, 2, 3, 4, 5, 6&gt;} \Longrightarrow  \texttt {21}.</fr:tex>
If we extended the <fr:code>SEQUENCE</fr:code> signature with a <fr:code>foldr</fr:code> primitive, though, we would have no better parallelism than lists:
<fr:tex
display="block">   \begin {aligned}     &amp;\texttt {foldr op+ 0 &lt;1, 2, 3, 4, 5, 6&gt;} \\     &amp;\Longrightarrow  \texttt {1 + (2 + (3 + (4 + (5 + (6 + 0)))))}   \end {aligned} </fr:tex>
Instead, we can reparenthesize, pairing numbers up and evaluating the sums in parallel. We call this function <fr:code>reduce</fr:code>:
<fr:tex
display="block">   \begin {aligned}     &amp;\texttt {reduce op+ 0 &lt;1, 2, 3, 4, 5, 6&gt;} \\     &amp;\Longrightarrow  \texttt {((1 + 2) + (3 + 0)) + ((4 + 5) + (6 + 0))}   \end {aligned} </fr:tex></fr:p><fr:p>Here, we use the fact that <fr:code>0</fr:code> is the identity for <fr:code>+</fr:code> to add <fr:code>0</fr:code>s at will, balancing out the computation tree.</fr:p><fr:p>What happens if we did the same thing for subtraction, though?
<fr:tex
display="block">   \begin {aligned}     &amp;\texttt {foldr op- 0 &lt;1, 2, 3, 4, 5, 6&gt;} \\     &amp;\Longrightarrow  \texttt {1 - (2 - (3 - (4 - (5 - (6 - 0)))))} \\     &amp;\Longrightarrow  \texttt {\textasciitilde  3} \\     &amp;\texttt {reduce op- 0 &lt;1, 2, 3, 4, 5, 6&gt;} \\     &amp;\Longrightarrow  \texttt {((1 - 2) - (3 - 0)) - ((4 - 5) - (6 - 0))} \\     &amp;\Longrightarrow  \texttt {3}   \end {aligned} </fr:tex>
The different parenthesizations give different results, <fr:code>~3</fr:code> and <fr:code>3</fr:code>!
To avoid this issue, we restrict the inputs with which we can use <fr:code>reduce</fr:code>.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1259</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A7</fr:addr><fr:route>150-00A7.xml</fr:route><fr:title>Identity element</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>z : t</fr:code> and <fr:code>g : t * t -&gt; t</fr:code>. We say that <fr:code>z</fr:code> is an <fr:em>identity element</fr:em> for <fr:code>g</fr:code> when for all <fr:code>a</fr:code>: <fr:tex
display="block">\texttt {g (a, z)} \cong  \texttt {a} \cong  \texttt {g (z, a)}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1260</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A8</fr:addr><fr:route>150-00A8.xml</fr:route><fr:title>Associative function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>g : t * t -&gt; t</fr:code>. We say that <fr:code>g</fr:code> is a <fr:em>associative</fr:em> when for all <fr:code>a</fr:code>, <fr:code>b</fr:code>, <fr:code>c</fr:code>: <fr:tex
display="block">\texttt {g (g (a, b), c)} \cong  \texttt {g (a, g (b, c))}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1261</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A6</fr:addr><fr:route>150-00A6.xml</fr:route><fr:title>Monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>monoid</fr:em> consists of:</fr:p><fr:ol><fr:li>a type <fr:code>t</fr:code>,</fr:li>
  <fr:li>some <fr:code>z : t</fr:code>,</fr:li>
  <fr:li>and some <fr:code>g : t * t -&gt; t</fr:code> such that</fr:li>
  <fr:li><fr:code>z</fr:code> is an <fr:link
href="150-00A7.xml"
type="local"
addr="150-00A7">identity element</fr:link> for <fr:code>g</fr:code>, and</fr:li>
  <fr:li><fr:code>g</fr:code> is an <fr:link
href="150-00A8.xml"
type="local"
addr="150-00A8">associative function</fr:link>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1262</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00A9</fr:addr><fr:route>150-00A9.xml</fr:route><fr:title>Integer addition monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following data form a monoid:</fr:p><fr:ol><fr:li>type <fr:code>t</fr:code> is <fr:code>int</fr:code>,</fr:li>
  <fr:li><fr:code>z</fr:code> is <fr:code>0</fr:code>,</fr:li>
  <fr:li><fr:code>g</fr:code> is <fr:code>op+</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1263</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AA</fr:addr><fr:route>150-00AA.xml</fr:route><fr:title>String concatenation monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following data form a monoid:</fr:p><fr:ol><fr:li>type <fr:code>t</fr:code> is <fr:code>string</fr:code>,</fr:li>
  <fr:li><fr:code>z</fr:code> is <fr:code>""</fr:code>,</fr:li>
  <fr:li><fr:code>g</fr:code> is <fr:code>op^</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1265</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AB</fr:addr><fr:route>150-00AB.xml</fr:route><fr:title>Sequence <fr:code>reduce</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.reduce</fr:code> combines the data in a sequence using a <fr:link
href="150-00A6.xml"
type="local"
addr="150-00A6">monoid</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.reduce : ('a * 'a -&gt; 'a) -&gt; 'a -&gt; 'a Seq.t -&gt; 'a
 * REQUIRES: g and z form a monoid
 * ENSURES: Seq.reduce g z &lt;x0, x1, ..., x_{n-1}&gt; ~= g (x0, g (x1, ..., g (x_{n-1}, z)))
 *)
</html:code></fr:pre><fr:p>Notice that the behavior of <fr:code>reduce</fr:code> exactly mirrors <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>, and its type is an instance of the type of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>. However, thanks to the assumption that <fr:code>g</fr:code> and <fr:code>z</fr:code> form a monoid, <fr:code>reduce</fr:code> is more efficient than <fr:code>foldr</fr:code> in parallel.</fr:p><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="36269934c8d91cfdda875f6a97a99477"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node  (start) at (0, 1) {$\bullet $};
      \node [hexagon] (g0) at (-2.5, 0) {\texttt {g}};
      \node [hexagon] (g1) at (-1, 0) {\texttt {g}};
      \node  at (0, 0) {$\cdots $};
      \node [hexagon] (g2) at (1, 0) {\texttt {g}};
      \node [hexagon] (g3) at (2.5, 0) {\texttt {g}};
      \node [hexagon] (gg0) at (-1.75, -1) {\texttt {g}};
      \node [hexagon] (gg1) at (1.75, -1) {\texttt {g}};
      \node [hexagon] (ggg) at (0, -2) {\texttt {g}};

      \path  (start) edge (g0);
      \path  (start) edge (g1);
      \path  (start) edge (g2);
      \path  (start) edge (g3);
      \path  (g0) edge (gg0);
      \path  (g1) edge (gg0);
      \path  (g2) edge (gg1);
      \path  (g3) edge (gg1);
      \path  (gg0) edge (ggg);
      \path  (gg1) edge (ggg);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  Its work and span <fr:em>depend on the cost of <fr:code>g</fr:code></fr:em>, but assuming <fr:code>g</fr:code> is constant-time, then <fr:code>reduce g z S</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(\log  n)</fr:tex>.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1267</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AC</fr:addr><fr:route>150-00AC.xml</fr:route><fr:title>Sequence sum</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:link
href="150-00AB.xml"
type="local"
addr="150-00AB">sequence <fr:code>reduce</fr:code></fr:link>, we can sum a sequence as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val sum : int seq -&gt; int = Seq.reduce op+ 0
</html:code></fr:pre><fr:p>The code is analogous to <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list sum</fr:link>, where the call to <fr:code>Seq.reduce</fr:code> is justified by the <fr:link
href="150-00A9.xml"
type="local"
addr="150-00A9">integer addition monoid</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1269</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AD</fr:addr><fr:route>150-00AD.xml</fr:route><fr:title>Sequence <fr:code>filter</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can attempt to implement an analogue to <fr:link
href="150-0062.xml"
type="local"
addr="150-0062">list filter</fr:link> using <fr:link
href="150-00AB.xml"
type="local"
addr="150-00AB">sequence <fr:code>reduce</fr:code></fr:link>, using the <fr:link
href="150-006P.xml"
type="local"
addr="150-006P">pipe function</fr:link> for readability:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun filter p S =
  S                                        (* &lt;1, 2, 3, 4&gt; *)
  |&gt; Seq.map
      (fn i =&gt;
        if p (Seq.nth S i)
          then Seq.singleton (Seq.nth S i)
          else Seq.empty ())               (* &lt;&lt;&gt;, &lt;2&gt;, &lt;&gt;, &lt;4&gt;&gt; *)
  |&gt; Seq.reduce Seq.append (Seq.empty ())  (* &lt;2, 4&gt; *)
</html:code></fr:pre><fr:p>The commented case on the right shows how filtering the even data from a sequence would work.</fr:p><fr:p>Using the cost graphs for <fr:link
href="150-00A2.xml"
type="local"
addr="150-00A2">sequence <fr:code>map</fr:code></fr:link> and <fr:link
href="150-00AB.xml"
type="local"
addr="150-00AB">sequence <fr:code>reduce</fr:code></fr:link>, we find that the work of this implementation (assuming a constant-time predicate <fr:code>p</fr:code>) is <fr:tex>\mathcal {O}(n\log  n)</fr:tex> and the span is <fr:tex>\mathcal {O}(\log  n)</fr:tex>.
In fact, we can modify this implementation to recover an implementation with <fr:tex>\mathcal {O}(n)</fr:tex> work (and the same span); however, while we use the <fr:tex>\mathcal {O}(n)</fr:tex> cost bound in this course, we leave the development of the more efficient algorithm to <fr:link
href="210-notes.xml"
type="local"
addr="210-notes">15-210: Parallel and Sequential Data Structures and Algorithms</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1271</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AE</fr:addr><fr:route>150-00AE.xml</fr:route><fr:title>Sequence <fr:code>mapreduce</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The pattern of <fr:link
href="150-00A2.xml"
type="local"
addr="150-00A2">sequence <fr:code>map</fr:code></fr:link> followed by <fr:link
href="150-00AB.xml"
type="local"
addr="150-00AB">sequence <fr:code>reduce</fr:code></fr:link> is very common. We define a hybrid function <fr:code>mapreduce</fr:code> accordingly:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* mapreduce : ('a -&gt; 'b) -&gt; 'b -&gt; ('b * 'b -&gt; 'b) -&gt; 'a Seq.t -&gt; 'b
 * REQUIRES: g and z form a monoid
 * ENSURES: Seq.mapreduce f z g ~= Seq.reduce g z o Seq.map f
 *)
fun mapreduce f z g = Seq.reduce g z o Seq.map f
</html:code></fr:pre><fr:p>In fact, this function is the <fr:link
href="150-006H.xml"
type="local"
addr="150-006H">fold</fr:link> for sequences defined using <fr:code>singleton</fr:code>, <fr:code>empty</fr:code>, and <fr:code>append</fr:code>:
<fr:tex
display="block">   \begin {aligned}     \texttt {mapreduce f z g (Seq.singleton a)} &amp;\cong  \texttt {f a} \\     \texttt {mapreduce f z g (Seq.empty ())} &amp;\cong  \texttt {z} \\     \texttt {mapreduce f z g (Seq.append (s1, s2))} &amp;\cong  \texttt {g (mr f z g s1, mr f z g s2)}   \end {aligned} </fr:tex>
We abbreviate <fr:code>mapreduce</fr:code> as <fr:code>mr</fr:code> here for brevity.</fr:p><fr:p>The monoid requirements on <fr:code>reduce</fr:code> (and <fr:code>mapreduce</fr:code>) are justified by the behavior of <fr:code>append</fr:code> and <fr:code>empty</fr:code>. For example:
<fr:tex
display="block">   \begin {aligned}     &amp;\texttt {g (z, mapreduce f z g s)} \\     &amp;\cong  \texttt {g (mapreduce f z g (Seq.empty ()), mapreduce f z g s)} \\     &amp;\cong  \texttt {mapreduce f z g (Seq.append (Seq.empty (), s))} \\     &amp;\cong  \texttt {mapreduce f z g s}   \end {aligned} </fr:tex>
Here, since <fr:tex>\texttt {Seq.append (Seq.empty (), s)} \cong  \texttt {s}</fr:tex>, we must have that <fr:code>z</fr:code> is a left identity for <fr:code>g</fr:code>. Similar reasoning justifies that <fr:code>z</fr:code> must be a right identity and <fr:code>g</fr:code> must be associative.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1273</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AF</fr:addr><fr:route>150-00AF.xml</fr:route><fr:title>Matrix sum</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Representing an <fr:tex>m \times  n</fr:tex> matrix as an <fr:tex>m</fr:tex>-length sequence of <fr:tex>n</fr:tex>-length sequences, we can ask for the sum of the elements of a matrix using <fr:link
href="150-00AC.xml"
type="local"
addr="150-00AC">sequence sum</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">type 'a matrix = 'a Seq.t Seq.t

fun msum (S : int Seq.t Seq.t) : int Seq.t =
  S               (* &lt;&lt;1,2&gt;, &lt;3,4&gt;, &lt;5,6&gt;&gt; *)
  |&gt; Seq.map sum  (* &lt;3, 7, 11&gt; *)            (* W: O(mn), S: O(log(n)) *)
  |&gt; sum          (* 21 *)                    (* W: O(m) , S: O(log(m)) *)
</html:code></fr:pre><fr:p>Each line is annotated with cost. Thus, the total work of <fr:code>msum S</fr:code> is <fr:tex>O(mn)</fr:tex>, and the total span is <fr:tex>O(\log  m + \log  n)</fr:tex>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1304</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect18</fr:addr><fr:route>150-lect18.xml</fr:route><fr:title>Sequences II: sorting</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>18</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by a similar lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:p>In the previous lecture, we saw that sequences can be viewed as <fr:link
href="150-009W.xml"
type="local"
addr="150-009W">indexed collections</fr:link> and <fr:link
href="150-00A3.xml"
type="local"
addr="150-00A3">trees</fr:link> (that "self-balance", since they are implemented using arrays). Now, we use the tree-based perspective to implement a divide-and-conquer algorithm we previously implemented on lists: <fr:link
href="150-004H.xml"
type="local"
addr="150-004H">merge sort</fr:link>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1289</fr:anchor><fr:addr>150-00AJ</fr:addr><fr:route>150-00AJ.xml</fr:route><fr:title>Sequence merge</fr:title></fr:frontmatter><fr:mainmatter><fr:p>First, we implement the <fr:link
href="150-004O.xml"
type="local"
addr="150-004O">merge auxiliary function</fr:link>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1282</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-00AK</fr:addr><fr:route>150-00AK.xml</fr:route><fr:title>Parallel merge</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The implementation of the <fr:link
href="150-004O.xml"
type="local"
addr="150-004O">merge auxiliary function</fr:link> on lists was inherently sequential, traversing the lists one-by-one. To parallelize, we hope to divide a sequence in halves before recursively merging both sides.</fr:p><fr:p>Suppose we split both sequences in half naively:</fr:p><fr:tex
display="block">   \begin {aligned}     \langle a, c, d, g, i\rangle  &amp;\mapsto  \langle a, c\rangle , \langle d, g, i\rangle  \\     \langle b, e, f, h\rangle  &amp;\mapsto  \langle b, e\rangle , \langle f, h\rangle    \end {aligned} </fr:tex><fr:p>We could recursively merge both sides to get <fr:tex>\langle a,b,c,e\rangle </fr:tex> and <fr:tex>\langle d,f,g,h,i\rangle </fr:tex>, but it's not immediately clear how to combine these results to get the full sequence <fr:tex>\langle a,b,c,d,e,f,g,h,i\rangle </fr:tex>.</fr:p><fr:p>Instead, what if we split the first sequence in halves, and then split the second sequence to match the split of the first sequence?</fr:p><fr:tex
display="block">   \begin {aligned}     \langle a, c, d, g, i\rangle  &amp;\mapsto  \langle a, c\rangle , d, \langle g, i\rangle  \\     \langle b, e, f, h\rangle  &amp;\mapsto  \langle b\rangle , \langle e, f, h\rangle    \end {aligned} </fr:tex><fr:p>We split the first sequence with midpoint <fr:tex>d</fr:tex>, and then we split the second sequence into elements less than <fr:tex>d</fr:tex> and greater than <fr:tex>d</fr:tex>. Then, we can recursively merge to get <fr:tex>\langle a,b,c\rangle </fr:tex> and <fr:tex>\langle e,f,g,h,i\rangle </fr:tex>, which we can append with <fr:tex>d</fr:tex> in the middle to get the final result. To find the split point of the second sequence, we can use binary search.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1284</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-00AL</fr:addr><fr:route>150-00AL.xml</fr:route><fr:title>Binary search on sequences</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement binary search as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* binarySearch : string Seq.t -&gt; string -&gt; int
 * REQUIRES: S is sorted
 * ENSURES: binarySearch S x ~= i, such that
    - 0 &lt;= i &lt;= Seq.length S and
    - Seq.split S i ~= (Sa, Sb) such that
    - every element of Sa is &lt;= x and
    - every element of Sb is &gt;= x.
 *)
fun binarySearch S x =
  if Seq.null S then 0 else
  let
    val n = Seq.length S div 2
    val (Sa, y, Sb) = (Seq.take S n, Seq.nth S n, Seq.drop S (n + 1))
  in
    case String.compare (x, y) of
      EQUAL =&gt; n
    | LESS =&gt; binarySearch Sa x
    | GREATER =&gt; n + 1 + binarySearch Sb x
  end
</html:code></fr:pre><fr:p>The work and span are <fr:tex>\mathcal {O}(\log  n)</fr:tex>, as all of the sequence functions involved are constant time, and we repeatedly divide <fr:tex>n</fr:tex>, the length of input <fr:code>S</fr:code>, in half.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1286</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-00AM</fr:addr><fr:route>150-00AM.xml</fr:route><fr:title>Sequence merge</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We implement <fr:link
href="150-00AK.xml"
type="local"
addr="150-00AK">parallel merge</fr:link> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* merge : string Seq.t * string Seq.t -&gt; int
 * REQUIRES: S1 and S2 are sorted
 * ENSURES: merge (S1, S2) ~= S, where S is a sorted permutation of Seq.append (S1, S2)
 *)
fun merge (S1, S2) =
  if Seq.null S1 then S2 else  (* O(1) *)
  let
    val n = Seq.length S1 div 2  (* O(1) *)
    val (S1a, x, S1b) = (Seq.take S1 n, Seq.nth S1 n, Seq.drop S1 (n + 1))  (* O(1) *)
    val i = binarySearch S2 x  (* O(log(n)) *)
    val (S2a, S2b) = Seq.split S2 i  (* O(1) *)
    val (Sa, Sb) = (merge (S1a, S2a), merge (S1b, S2b))
  in
    Seq.append (Sa, Seq.append (Seq.singleton x, Sb))  (* W: O(m + n), S: O(1) *)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1287</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AN</fr:addr><fr:route>150-00AN.xml</fr:route><fr:title><fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">Sequence merge</fr:link> work analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the work of <fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">sequence merge</fr:link> using an informal recurrence:</fr:p><fr:tex
display="block">   \begin {aligned}     W(0, n) &amp;= \mathcal {O}(1) \\     W(m, n) &amp;\le  2W(m/2, n) + \mathcal {O}(m + n)   \end {aligned} </fr:tex><fr:p>Since we don't know how the second sequence (of length <fr:tex>n</fr:tex>) will be split, we give an upper bound in the recursive case by assuming that <fr:tex>n</fr:tex> stays fixed, even though it must shrink in at least one of the branches.</fr:p><fr:p>Solving this recurrence, we find that <fr:tex>W(m, n) \in  \mathcal {O}(mn)</fr:tex>.</fr:p><fr:p>Unfortunately, this is severely worse than the <fr:tex>\mathcal {O}(m + n)</fr:tex> cost we achieved for sequential merge! Notice, though, that the dominating cost is that of appending the sequences at the end. Using techniques developed in <fr:link
href="210-notes.xml"
type="local"
addr="210-notes">15-210: Parallel and Sequential Data Structures and Algorithms</fr:link>, we can avoid the cost of the append, recovering a merge algorithm with the more reasonable work <fr:tex>\mathcal {O}(m + n)</fr:tex>. In our further analyses (and the <fr:link
href="http://www.cs.cmu.edu/~15150/resources/libraries/sequence.pdf"
type="external">sequence documentation</fr:link>), we will use this bound instead.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1288</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AO</fr:addr><fr:route>150-00AO.xml</fr:route><fr:title><fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">Sequence merge</fr:link> span analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the span of <fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">sequence merge</fr:link> using an informal recurrence:</fr:p><fr:tex
display="block">   \begin {aligned}     S(0, n) &amp;= \mathcal {O}(1) \\     S(m, n) &amp;\le  S(m/2, n) + \mathcal {O}(\log (n))   \end {aligned} </fr:tex><fr:p>As described in the <fr:link
href="150-00AN.xml"
type="local"
addr="150-00AN"><fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">sequence merge</fr:link> work analysis</fr:link>, we upper bound the recursive call by leaving <fr:tex>n</fr:tex> unchanged. Solving this recurrence, we find that <fr:tex>S(m, n) \in  \mathcal {O}(\log (m)\log (n))</fr:tex>.</fr:p><fr:p>Using techniques developed in <fr:link
href="210-notes.xml"
type="local"
addr="210-notes">15-210: Parallel and Sequential Data Structures and Algorithms</fr:link>, we can improve this bound to <fr:tex>\mathcal {O}(\log (m) + \log (n)) = \mathcal {O}(\log (mn))</fr:tex>. In our further analyses (and the <fr:link
href="http://www.cs.cmu.edu/~15150/resources/libraries/sequence.pdf"
type="external">sequence documentation</fr:link>), we will use this bound instead.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1295</fr:anchor><fr:addr>150-00AP</fr:addr><fr:route>150-00AP.xml</fr:route><fr:title>Sequence merge sort</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1290</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-00AQ</fr:addr><fr:route>150-00AQ.xml</fr:route><fr:title>Parallel merge sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When implementing <fr:link
href="150-004P.xml"
type="local"
addr="150-004P">merge sort</fr:link>, we described essentially the following idea:</fr:p><fr:tex
display="block">   \begin {aligned}     \texttt {msort}~\langle x\rangle  &amp;= \langle x\rangle  \\     \texttt {msort}~\langle \rangle  &amp;= \langle \rangle  \\     \texttt {msort}~(\texttt {append}(S_1, S_2)) &amp;= \texttt {merge}(\texttt {msort}~S_1, \texttt {msort}~S_2)   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1292</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-00AR</fr:addr><fr:route>150-00AR.xml</fr:route><fr:title>Sequence merge sort</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement <fr:link
href="150-00AQ.xml"
type="local"
addr="150-00AQ">parallel merge sort</fr:link> cleanly using <fr:link
href="150-00AE.xml"
type="local"
addr="150-00AE">sequence <fr:code>mapreduce</fr:code></fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* msort : string Seq.t -&gt; string Seq.t
 * REQUIRES: true
 * ENSURES: msort S ~= S', where S' is a sorted permutation of S
 *)
val msort = Seq.mapreduce Seq.singleton (Seq.empty ()) merge
</html:code></fr:pre><fr:p>Observe that <fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM"><fr:code>merge</fr:code></fr:link> and <fr:link
href="150-00AH.xml"
type="local"
addr="150-00AH"><fr:code>Seq.empty ()</fr:code></fr:link> form a <fr:link
href="150-00A6.xml"
type="local"
addr="150-00A6">monoid</fr:link>, meeting the precondition for <fr:link
href="150-00AE.xml"
type="local"
addr="150-00AE"><fr:code>Seq.mapreduce</fr:code></fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1293</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AS</fr:addr><fr:route>150-00AS.xml</fr:route><fr:title><fr:link
href="150-00AR.xml"
type="local"
addr="150-00AR">Sequence merge sort</fr:link> work analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the work of <fr:link
href="150-00AR.xml"
type="local"
addr="150-00AR">sequence merge sort</fr:link> using the cost graphs for <fr:link
href="150-00AE.xml"
type="local"
addr="150-00AE">sequence <fr:code>mapreduce</fr:code></fr:link>, <fr:link
href="150-00AG.xml"
type="local"
addr="150-00AG">singleton sequence</fr:link>, and <fr:link
href="150-00AH.xml"
type="local"
addr="150-00AH">empty sequence</fr:link>. Assuming the work of <fr:code>merge</fr:code> is <fr:tex>\mathcal {O}(m + n)</fr:tex> <fr:link
href="150-00AN.xml"
type="local"
addr="150-00AN">as discussed</fr:link>, we find that the work of <fr:code>msort</fr:code> is <fr:tex>\mathcal {O}(n\log (n))</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1294</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AT</fr:addr><fr:route>150-00AT.xml</fr:route><fr:title><fr:link
href="150-00AR.xml"
type="local"
addr="150-00AR">Sequence merge sort</fr:link> span analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We analyze the span of <fr:link
href="150-00AR.xml"
type="local"
addr="150-00AR">sequence merge sort</fr:link> using the cost graphs for <fr:link
href="150-00AE.xml"
type="local"
addr="150-00AE">sequence <fr:code>mapreduce</fr:code></fr:link>, <fr:link
href="150-00AG.xml"
type="local"
addr="150-00AG">singleton sequence</fr:link>, and <fr:link
href="150-00AH.xml"
type="local"
addr="150-00AH">empty sequence</fr:link>. Assuming the span of <fr:code>merge</fr:code> is <fr:tex>\mathcal {O}(\log (m) + \log (n))</fr:tex> <fr:link
href="150-00AO.xml"
type="local"
addr="150-00AO">as discussed</fr:link>, we find that the work of <fr:code>msort</fr:code> is <fr:tex>\mathcal {O}(\log ^2(n))</fr:tex>.</fr:p><fr:p>This is an improvement over the <fr:link
href="150-004S.xml"
type="local"
addr="150-004S">span found earlier</fr:link>, <fr:tex>\mathcal {O}(n)</fr:tex>, thanks to the use of a parallel merge algorithm.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1303</fr:anchor><fr:addr>150-00AU</fr:addr><fr:route>150-00AU.xml</fr:route><fr:title>Sequence views</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To avoid excessive use of indexing and <fr:code>if Seq.null</fr:code> checks, we can use an idea called <fr:em>views</fr:em> to pattern match on sequences instead, <fr:em>view</fr:em>ing sequences as if they were balanced trees.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1298</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AV</fr:addr><fr:route>150-00AV.xml</fr:route><fr:title>Middle-tree view</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement a view of sequences as trees with data at the nodes as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    (* ...as before... *)

    datatype 'a mview = Bud | Branch of 'a seq * 'a * 'a seq
    val join : 'a seq * 'a * 'a seq -&gt; 'a seq

    val showm : 'a seq -&gt; 'a mview
    val hidem : 'a mview -&gt; 'a seq
  end
</html:code></fr:pre><fr:p>These functions make sequences look like trees, hiding away some indexing:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun join (S1, x, S2) =
  Seq.append (S1, Seq.append (Seq.singleton x, S2))

fun showm (S : 'a Seq.t) : 'a Seq.mview =
  if Seq.null S then Seq.Bud else
    let
      val n = Seq.length S div 2
    in
      Branch (Seq.take S n, Seq.nth S n, Seq.drop S (n + 1))
    end

fun hidem Seq.Bud = Seq.empty ()
  | hidem (Seq.Branch (s1, x, s2)) = join (s1, x, s2)
</html:code></fr:pre><fr:p>Note: while other views (<fr:code>lview</fr:code> and <fr:code>tview</fr:code>) are available in the given sequence signature, this <fr:code>mview</fr:code> is not included by default.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1300</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AW</fr:addr><fr:route>150-00AW.xml</fr:route><fr:title><fr:link
href="150-00AL.xml"
type="local"
addr="150-00AL">Binary search on sequences</fr:link> using <fr:link
href="150-00AV.xml"
type="local"
addr="150-00AV">middle-tree view</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can reimplement <fr:link
href="150-00AL.xml"
type="local"
addr="150-00AL">binary search on sequences</fr:link> without explicit indexing using the <fr:link
href="150-00AV.xml"
type="local"
addr="150-00AV">middle-tree view</fr:link> (which we assume is included in the sequence signature).</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun binarySearch S x =
  case Seq.showm S of
    Seq.Bud =&gt; 0
  | Seq.Branch (Sa, y, Sb) =&gt;
      case String.compare (x, y) of
        EQUAL =&gt; n
      | LESS =&gt; binarySearch Sa x
      | GREATER =&gt; n + 1 + binarySearch Sb x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1302</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00AX</fr:addr><fr:route>150-00AX.xml</fr:route><fr:title><fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">Sequence merge</fr:link> using <fr:link
href="150-00AV.xml"
type="local"
addr="150-00AV">middle-tree view</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can reimplement <fr:link
href="150-00AM.xml"
type="local"
addr="150-00AM">sequence merge</fr:link> without as much explicit indexing using the <fr:link
href="150-00AV.xml"
type="local"
addr="150-00AV">middle-tree view</fr:link> (which we assume is included in the sequence signature).</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun merge (S1, S2) =
  case Seq.showm of
    Seq.Bud =&gt; S2
  | Seq.Branch (S1a, x, S1b) =&gt;
      let
        val (S2a, S2b) = Seq.split S2 (binarySearch S2 x)
      in
        Seq.join (merge (S1a, S2a), x, merge (S1b, S2b))
      end
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1349</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect19</fr:addr><fr:route>150-lect19.xml</fr:route><fr:title>Imperative programming I: effects</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>23</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by lectures by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link> and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1329</fr:anchor><fr:addr>150-00AY</fr:addr><fr:route>150-00AY.xml</fr:route><fr:title>Exceptions</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1311</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AZ</fr:addr><fr:route>150-00AZ.xml</fr:route><fr:title><fr:code>raise</fr:code> expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:code>raise Fail "TODO"</fr:code> has most general type <fr:code>'a</fr:code>, filling in for any type we wish. More generally, <fr:code>raise e</fr:code> has most general type <fr:code>'a</fr:code>, for any exception <fr:code>e</fr:code>.</fr:p><fr:p>Unlike other expressions, it does not evaluate to <fr:em>any</fr:em> value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1313</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00B0</fr:addr><fr:route>150-00B0.xml</fr:route><fr:title><fr:code>exn</fr:code> type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An exception, like <fr:code>Fail "TODO"</fr:code> or <fr:code>Div</fr:code>, has type <fr:code>exn</fr:code>. So, note that <fr:code>Fail : string -&gt; exn</fr:code>. We can write <fr:code>raise e</fr:code> for any <fr:code>e : exn</fr:code>.</fr:p><fr:p>The type <fr:code>exn</fr:code> can be thought of as a datatype with infinitely many constructors:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype exn = Fail of string | Div | ...
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1315</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00B1</fr:addr><fr:route>150-00B1.xml</fr:route><fr:title>Exception declaration</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An exception can be declared as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">exception Constructor1
exception Constructor2 of dataToContain2
</html:code></fr:pre><fr:p>Notice the similarity to <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link>. However, here, we only give one constructor per declaration: since the <fr:link
href="150-00B0.xml"
type="local"
addr="150-00B0"><fr:code>exn</fr:code> type</fr:link> has infinitely many constructors, we only provide one more.</fr:p><fr:p>Like a <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link>, an exception declaration can also go in a signature, requiring that the structure provide a matching exception declaration.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1318</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00B2</fr:addr><fr:route>150-00B2.xml</fr:route><fr:title>Queue with exceptions</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can augment the <fr:link
href="150-008O.xml"
type="local"
addr="150-008O">queue signature</fr:link> to include an exception <fr:code>Empty</fr:code>, to be raised if there is no data remaining when <fr:code>dequeue</fr:code> is used:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature QUEUE =
  sig
    type 'a queue  (* abstract *)

    exception Empty

    val empty : 'a queue
    val enqueue : 'a queue -&gt; 'a -&gt; 'a queue
    val dequeue : 'a queue -&gt; 'a * 'a queue  (* may raise Empty *)
  end
</html:code></fr:pre><fr:p>The structure implementing this <fr:code>QUEUE</fr:code> signature must define a matching <fr:code>exception Empty</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ListQueue :&gt; QUEUE =
  struct
    type 'a queue = 'a list

    exception Empty

    val empty = nil
    fun enqueue (l : 'a queue) (x : 'a) : 'a queue = l @ [x]
    fun dequeue nil = raise Empty
      | dequeue (x :: xs) = (x, xs)
  end
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1320</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00B5</fr:addr><fr:route>150-00B5.xml</fr:route><fr:title><fr:code>handle</fr:code> expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>handle</fr:code> expression has the following structure:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">e handle pat1 =&gt; e1
       | pat2 =&gt; e2
       | ...
       | patn =&gt; en
</html:code></fr:pre><fr:p>Note the similarity to a <fr:link
href="150-001J.xml"
type="local"
addr="150-001J"><fr:code>case</fr:code> expressions</fr:link>. For this to typecheck, we must have that <fr:code>e : t</fr:code> for some type <fr:code>t</fr:code>, and each <fr:code>ei : t</fr:code>, and each <fr:code>pati</fr:code> is a pattern matching the <fr:link
href="150-00B0.xml"
type="local"
addr="150-00B0"><fr:code>exn</fr:code> type</fr:link>. A <fr:code>handle</fr:code> expression will first evaluate <fr:code>e</fr:code>. If it evaluates to a value, that value is provided immediately; or, if it raises an exception, the corresponding handler is evaluated. If no patterns match, the expression is simply re-raised.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1322</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00B6</fr:addr><fr:route>150-00B6.xml</fr:route><fr:title>List average</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using <fr:code>handle</fr:code>, we can choose a default value in case an exception is raised. For example, we may choose that the average of an empty list is <fr:code>0</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun average (l : int list) : int =
  (sum l div length l)
    handle Div =&gt; 0
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1324</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00B7</fr:addr><fr:route>150-00B7.xml</fr:route><fr:title>Safe division with options</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using a handler, we can catch the <fr:code>Div</fr:code> exception, if it is raised, and give back <fr:code>NONE</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun safeDiv (x : int, y : int) : int option =
  SOME (x div y) handle Div =&gt; NONE
</html:code></fr:pre><fr:p>Note that we wrap <fr:code>x div y</fr:code> in <fr:code>SOME</fr:code>, since if it evaluates successfully, we must also return an option.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1326</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00B9</fr:addr><fr:route>150-00B9.xml</fr:route><fr:title>Bypassed handler</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun avert (f : unit -&gt; string) : string =
  f () handle Fail s =&gt; s ^ " averted"
            | ListQueue.Empty =&gt; "empty queue averted"
</html:code></fr:pre><fr:p>When we evaluate the following two expressions, they evaluate to values:</fr:p><fr:tex
display="block">   \begin {aligned}     \texttt {avert (fn () =&gt; "done")} &amp;\hookrightarrow  \texttt {"done"} \\     \texttt {avert (fn () =&gt; raise Fail "explosion")} &amp;\hookrightarrow  \texttt {"explosion averted"}   \end {aligned} </fr:tex><fr:p>However, <fr:code>avert (fn () =&gt; Int.toString (150 div 0))</fr:code> raises <fr:code>Div</fr:code>, since <fr:code>Div</fr:code> is never handled by a clause of the <fr:code>handle</fr:code> expression in <fr:code>avert</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1328</fr:anchor><fr:taxon>Warning</fr:taxon><fr:addr>150-00B8</fr:addr><fr:route>150-00B8.xml</fr:route><fr:title>Handlers and evaluation order</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun puzzle (x : int) : string =
  Int.toString x
  handle Div =&gt; "divided by zero!"
</html:code></fr:pre><fr:p>Since the argument is evaluated first in a <fr:link
href="150-000Z.xml"
type="local"
addr="150-000Z">function application</fr:link>, <fr:code>puzzle (1 div 0)</fr:code> does <fr:em>not</fr:em> evaluate to <fr:code>"divided by zero!"</fr:code>. Instead, it raises <fr:code>Div</fr:code>, never stepping into the definition of <fr:code>puzzle</fr:code>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1348</fr:anchor><fr:addr>150-00BA</fr:addr><fr:route>150-00BA.xml</fr:route><fr:title>Extensional equivalence with effects</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1330</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BB</fr:addr><fr:route>150-00BB.xml</fr:route><fr:title>Effect</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An <fr:em>effect</fr:em> is something the evaluation of a program can do aside from returning a value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1331</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BC</fr:addr><fr:route>150-00BC.xml</fr:route><fr:title>Exception effect</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:link
href="150-00AZ.xml"
type="local"
addr="150-00AZ">Raising</fr:link> an exception is an <fr:link
href="150-00BB.xml"
type="local"
addr="150-00BB">effect</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1333</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BD</fr:addr><fr:route>150-00BD.xml</fr:route><fr:title>Infinite loop</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Typically, we ensure that programs go by well-founded recursion on some input. However, nothing prevents us from writing nonsensical programs such as the following:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun evil n = evil (n - 1)
</html:code></fr:pre><fr:p>Since <fr:code>evil</fr:code> has no base case, evaluating <fr:code>evil n</fr:code> for any <fr:code>n</fr:code> will never terminate. Thus, infinite looping is another <fr:link
href="150-00BB.xml"
type="local"
addr="150-00BB">effect</fr:link>: rather than return a value, one can infinite loop.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1334</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BI</fr:addr><fr:route>150-00BI.xml</fr:route><fr:title><fr:code>print</fr:code> effect</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:code>print : string -&gt; unit</fr:code> function is an <fr:link
href="150-00BB.xml"
type="local"
addr="150-00BB">effect</fr:link>, causing the given string to be displayed in the terminal.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1335</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00B4</fr:addr><fr:route>150-00B4.xml</fr:route><fr:title>Pure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Say that an expression <fr:tex>e</fr:tex> is <fr:em>pure</fr:em> when there exists some value <fr:tex>v</fr:tex> such that <fr:tex>e \hookrightarrow  v</fr:tex> without performing any observable effects.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1336</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00B3</fr:addr><fr:route>150-00B3.xml</fr:route><fr:title>Extensional equivalence with effects</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When considering exceptions, we say that <fr:tex>e_1 \cong  e_2</fr:tex> when both:</fr:p><fr:ol><fr:li><fr:tex>e_1</fr:tex> and <fr:tex>e_2</fr:tex> perform indistinguishable effects; for example, they raise the same exceptions, loop infinitely, or print the same string.</fr:li>
  <fr:li>If <fr:tex>e_1 \hookrightarrow  v_1</fr:tex> and <fr:tex>e_2 \hookrightarrow  v_2</fr:tex>, then <fr:tex>v_1 \cong  v_2</fr:tex> as pure expressions (i.e., as described before).</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1337</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BJ</fr:addr><fr:route>150-00BJ.xml</fr:route><fr:title>Extensional equivalence with handlers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expressions <fr:code>150</fr:code> and <fr:code>1 div 0 handle Div =&gt; 150</fr:code> are extensionally equivalent: even though the latter raises <fr:code>Div</fr:code> initially, the exception is handled, so the result values are ultimately the same.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1338</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BE</fr:addr><fr:route>150-00BE.xml</fr:route><fr:title>Noncommutativity of addition with effects</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In general, it need not be true that <fr:tex>e_1 \texttt { + } e_2 \cong  e_2 \texttt { + } e_1</fr:tex>. For example, if <fr:code>e1 = raise Fail "A"</fr:code> and <fr:code>e2 = raise Fail "B"</fr:code>, then these are distinguishable: the first raises <fr:code>"A"</fr:code>, while the second raises <fr:code>"B"</fr:code>.</fr:p><fr:p>However, if <fr:tex>e_1</fr:tex> and <fr:tex>e_2</fr:tex> are pure, this equivalence does hold.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1339</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00BK</fr:addr><fr:route>150-00BK.xml</fr:route><fr:title>Pattern matching and purity</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the presence of effects, a function defined by pattern matching only says what happens given a pure argument, since in a <fr:link
href="150-000Z.xml"
type="local"
addr="150-000Z">function application</fr:link>, arguments are evaluated first.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1340</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BL</fr:addr><fr:route>150-00BL.xml</fr:route><fr:title>Pattern matching with an effectful argument</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the <fr:link
href="150-0029.xml"
type="local"
addr="150-0029">slow list reverse</fr:link>. Its definition can be interpreted as following two statements:</fr:p><fr:ol><fr:li><fr:tex>\texttt {revSlow nil} \cong  \texttt {nil}</fr:tex>, and</fr:li>
  <fr:li>for all <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> <fr:code>e1</fr:code> and <fr:code>e2</fr:code>, we have <fr:tex>\texttt {revSlow (e1 :: e2)} \cong  \texttt {revSlow e2 @ [e1]}</fr:tex>.</fr:li></fr:ol><fr:p>Notice that the statement for the second clause is not true for general <fr:code>e1</fr:code> and <fr:code>e2</fr:code> with effects. For example, if <fr:code>e1</fr:code> is <fr:code>raise Fail "A"</fr:code> and <fr:code>e2</fr:code> is <fr:code>raise Fail "B"</fr:code>, then the former raises <fr:code>Fail "A"</fr:code> and the latter raises <fr:code>Fail "B"</fr:code>.</fr:p><fr:p>When stepping through <fr:code>revSlow</fr:code> using the second clause, we must justify that our arguments are <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1341</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BF</fr:addr><fr:route>150-00BF.xml</fr:route><fr:title>Total</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:code>f : t1 -&gt; t2</fr:code> is <fr:em>total</fr:em> when for all values <fr:code>x : t1</fr:code>, we have that <fr:code>f x</fr:code> is a <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> expression.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1347</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BG</fr:addr><fr:route>150-00BG.xml</fr:route><fr:title>Totality citation in a proof</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the <fr:link
href="150-0029.xml"
type="local"
addr="150-0029">slow list reverse</fr:link>. Now, consider the following lemmas:</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1342</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-00BM</fr:addr><fr:route>150-00BM.xml</fr:route><fr:title>Totality of <fr:code>revSlow</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>We have that <fr:link
href="150-0029.xml"
type="local"
addr="150-0029"><fr:code>revSlow</fr:code></fr:link> is <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1343</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-00BN</fr:addr><fr:route>150-00BN.xml</fr:route><fr:title><fr:code>map</fr:code> is a monoid homomorphism</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link> functions <fr:code>f</fr:code> and <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> expressions <fr:code>e1</fr:code> and <fr:code>e2</fr:code>, we have that <fr:tex
display="block">\texttt {map f (e1 @ e2)} \cong  \texttt {map f e1 @ map f e2}.</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1344</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-00BO</fr:addr><fr:route>150-00BO.xml</fr:route><fr:title>Totality of <fr:code>map f</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link> functions <fr:code>f</fr:code>, we have that <fr:code>map f</fr:code> is <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:p>We now prove the following theorem.</fr:p>
  
  <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1345</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>#173</fr:addr><fr:route>unstable-173.xml</fr:route><fr:parent>150-00BG</fr:parent></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link> <fr:code>f</fr:code>, <fr:tex
display="block">\texttt {map f (revSlow l)} \cong  \texttt {revSlow (map f l)}.</fr:tex></fr:p></fr:mainmatter></fr:tree>

 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1346</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#174</fr:addr><fr:route>unstable-174.xml</fr:route><fr:parent>150-00BG</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>We use the definitions of <fr:link
href="150-0029.xml"
type="local"
addr="150-0029"><fr:code>revSlow</fr:code></fr:link> and <fr:link
href="150-005X.xml"
type="local"
addr="150-005X"><fr:code>map</fr:code></fr:link>. Let <fr:code>l : int list</fr:code> be an arbitrary value; we prove the theorem statement by induction on <fr:code>l</fr:code>.</fr:p>
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:p>First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {map f (revSlow nil)} \\           &amp;\cong  \texttt {map f nil}  &amp;&amp;\text {(clause 1 of \texttt {revSlow})} \\           &amp;\cong  \texttt {nil}  &amp;&amp;\text {(clause 1 of \texttt {map})}         \end {aligned}       </fr:tex>
      <fr:p>Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revSlow (map f nil)} \\           &amp;\cong  \texttt {revSlow nil} &amp;&amp;\text {(clause 1 of \texttt {map})} \\           &amp;\cong  \texttt {nil} &amp;&amp;\text {(clause 1 of \texttt {revSlow})}         \end {aligned}       </fr:tex>
      <fr:p>Both sides are equivalent, so the case is proven.</fr:p></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:
      <fr:p><fr:strong>IH:</fr:strong> <fr:tex>\texttt {map f (revSlow xs)} \cong  \texttt {revSlow (map f xs)}</fr:tex>.</fr:p>
      <fr:p><fr:strong>WTS:</fr:strong> <fr:tex>\texttt {map f (revSlow (x :: xs))} \cong  \texttt {revSlow (map f (x :: xs))}</fr:tex>.</fr:p>
      <fr:p>First, we reason about the left side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {map f (revSlow (x :: xs))} \\           &amp;\cong  \texttt {map f (revSlow xs @ [x])} &amp;&amp;\text {(clause 2 of \texttt {revSlow})} \\           &amp;\cong  \texttt {map f (revSlow xs) @ map f [x]}  &amp;&amp;(\ast ) \\           &amp;\cong  \texttt {map f (revSlow xs) @ [f x]}  &amp;&amp;\text {(clauses 2 and 1 of \texttt {map})} \\           &amp;\cong  \texttt {revSlow (map f xs) @ [f x]}  &amp;&amp;\text {(IH)}         \end {aligned}       </fr:tex>
      <fr:p>Here, the step <fr:tex>(\ast )</fr:tex> is justified by <fr:ref
addr="150-00BN"
href="150-00BN.xml"
taxon="Lemma"></fr:ref>, since:
      <fr:ul><fr:li><fr:code>f</fr:code> is <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link> by assumption,</fr:li>
        <fr:li><fr:code>revSlow xs</fr:code> is <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> by <fr:link
href="150-00BM.xml"
type="local"
addr="150-00BM">totality of <fr:code>revSlow</fr:code></fr:link>, and</fr:li>
        <fr:li><fr:code>[x]</fr:code> is <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> since it is a value.</fr:li></fr:ul></fr:p>
      <fr:p>Then, we reason about the right side:</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revSlow (map f (x :: xs))} \\           &amp;\cong  \texttt {revSlow (f x :: map f xs)}  &amp;&amp;\text {(clause 2 of \texttt {map})} \\           &amp;\cong  \texttt {revSlow (map f xs) @ [f x]} &amp;&amp;(\ast \ast )         \end {aligned}       </fr:tex>
      <fr:p>Here, the step <fr:tex>(\ast \ast )</fr:tex> is justified by <fr:link
href="150-00BL.xml"
type="local"
addr="150-00BL">clause 2 of <fr:code>revSlow</fr:code></fr:link>, since:
      <fr:ul><fr:li><fr:code>f x</fr:code> is <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> since <fr:code>f</fr:code> is <fr:link
href="150-00BF.xml"
type="local"
addr="150-00BF">total</fr:link> by assumption and</fr:li>
        <fr:li><fr:code>map f xs</fr:code> is <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> by <fr:link
href="150-00BO.xml"
type="local"
addr="150-00BO">totality of <fr:code>map f</fr:code></fr:link>.</fr:li></fr:ul></fr:p>
      <fr:p>Both sides are then equivalent, so the case is proven.</fr:p></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1381</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect20</fr:addr><fr:route>150-lect20.xml</fr:route><fr:title>Imperative programming II: mutable state</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>25</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by a similar lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1372</fr:anchor><fr:addr>150-00BH</fr:addr><fr:route>150-00BH.xml</fr:route><fr:title>Reference cells</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Standard ML supports mutable reference cells. However, this feature does not "infect" the purely functional code we have written before: mutation is isolated to select points in the code using types.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1357</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BP</fr:addr><fr:route>150-00BP.xml</fr:route><fr:title>Reference primitives</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The standard library includes the following signature:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature REF =
  sig
    type 'a ref

    val ref : 'a -&gt; 'a ref
    val !   : 'a ref -&gt; 'a
    val :=  : 'a ref * 'a -&gt; unit  (* infix *)

    (* ...some helper functions... *)
  end
</html:code></fr:pre><fr:ol><fr:li>The type <fr:code>t ref</fr:code> represents mutable reference cells that store a value of type <fr:code>t</fr:code>.</fr:li>
  <fr:li>The function <fr:code>ref</fr:code> allocates a new reference cell, where the starting value of the cell is the input.</fr:li>
  <fr:li>The function <fr:code>!</fr:code> accesses the current value of the reference cell given.</fr:li>
  <fr:li>The infix function <fr:code>op :=</fr:code> takes a reference cell (of type <fr:code>t ref</fr:code>) and a compatible value (of type <fr:code>t</fr:code>) and replaces the data in the reference cell with the given value.</fr:li></fr:ol><fr:p>All of these definitions are available at the top level. The use of references is considered an <fr:link
href="150-00BB.xml"
type="local"
addr="150-00BB">effect</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1358</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00BT</fr:addr><fr:route>150-00BT.xml</fr:route><fr:title>Equality of reference cells</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Reference cells can be compared for equality using <fr:code>op = : 'a ref * 'a ref -&gt; bool</fr:code>. This compares the "addresses", not the contained data. Every reference cell created (using <fr:code>ref</fr:code>) is fresh and not equal to any previously-defined reference cells.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1361</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BS</fr:addr><fr:route>150-00BS.xml</fr:route><fr:title>Puzzles with <fr:code>ref</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val r1 : int ref = ref 0
val r2 : int ref = ref 0
val () = r1 := 1
val result : int * int * bool = (!r1, !r2, r1 = r2)
</html:code></fr:pre><fr:p>The value bound to <fr:code>result</fr:code> is <fr:code>(1, 0, false)</fr:code>. Alternatively, we could set <fr:code>r2</fr:code> to be an alias for <fr:code>r1</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val r1 : int ref = ref 0
val r2 : int ref = r1
val () = r1 := 1
val result : int * int * bool = (!r1, !r2, r1 = r2)
</html:code></fr:pre><fr:p>The value bound to <fr:code>result</fr:code> is <fr:code>(1, 1, true)</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1364</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BU</fr:addr><fr:route>150-00BU.xml</fr:route><fr:title>Puzzles with nested <fr:code>ref</fr:code>s</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following example:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val r1 : int ref = ref 0
val r2 : int ref = ref 0
val () = r1 := 1
val r3 : int ref ref = ref r1
val () = !r3 := 2
val () = r3 := r2
val () = !r3 := 3
val result = (!r1, !r2)
</html:code></fr:pre><fr:p>Here, <fr:code>r3</fr:code> is a reference cell containing a reference cell. The value bound to <fr:code>result</fr:code> is <fr:code>(2, 3)</fr:code>. Alternatively, we could set <fr:code>r2</fr:code> to be an alias for <fr:code>r1</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val r1 : int ref = ref 0
val r2 : int ref = r1
val () = r1 := 1
val r3 : int ref ref = ref r1
val () = !r3 := 2
val () = r3 := r2
val () = !r3 := 3
val result = (!r1, !r2)
</html:code></fr:pre><fr:p>The value bound to <fr:code>result</fr:code> is <fr:code>(3, 3)</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1365</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BQ</fr:addr><fr:route>150-00BQ.xml</fr:route><fr:title>Semicolon expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:code>e1 ; e2</fr:code> is syntactic sugar for the expression <fr:code>let val _ = e1 in e2 end</fr:code>. In other words, it evaluates <fr:code>e1</fr:code> (running any effects but ignoring any returned value) and then evaluates <fr:code>e2</fr:code> (keeping the effects and return value).</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1367</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BR</fr:addr><fr:route>150-00BR.xml</fr:route><fr:title>Auxiliary standard library functions for imperative programming</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following functions are sometimes useful when writing imperative code:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix 0 before
fun (x : 'a) before () : 'a = x

fun ignore (_ : 'a) : unit = ()

(* Ref.modify : ('a -&gt; 'a) -&gt; 'a ref -&gt; unit *)
fun modify f r = r := f (!r)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1371</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BV</fr:addr><fr:route>150-00BV.xml</fr:route><fr:title>Imperative factorial algorithm</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement the <fr:link
href="150-0017.xml"
type="local"
addr="150-0017">factorial function</fr:link> using imperative programming. A first attempt might look like this:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val acc = ref 1

fun fact 0 = !acc
  | fact n =
      ( store := n * !store
      ; fact (n - 1)
      )

val example1 = fact 5
val example2 = fact 0
</html:code></fr:pre><fr:p>However, this code contains a bug: <fr:code>acc</fr:code> is never reset, so <fr:code>120</fr:code> would be bound to <fr:code>example2</fr:code>, not <fr:code>1</fr:code>. There are two ways to fix this problem. First, we can reset the reference cell after each call:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val acc = ref 1

fun fact 0 = !acc before acc := 1
  | fact n =
      ( acc := n * !acc
      ; fact (n - 1)
      )
</html:code></fr:pre><fr:p>Alternatively, we can allocate a fresh <fr:code>ref</fr:code> cell for each call to <fr:code>fact</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fact n =
  let
    val acc = ref 1

    fun loop 0 = !acc
      | loop n =
          ( acc := n * !acc
          ; loop (n - 1)
          )
  in
    loop n
  end
</html:code></fr:pre><fr:p>Every time we call <fr:code>fact</fr:code>, we allocate a new reference cell and run a small "loop" to update it repeatedly.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1380</fr:anchor><fr:addr>150-00BW</fr:addr><fr:route>150-00BW.xml</fr:route><fr:title>Mutable data structures</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1374</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BX</fr:addr><fr:route>150-00BX.xml</fr:route><fr:title>Imperative queue signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can augment <fr:link
href="150-008O.xml"
type="local"
addr="150-008O">the <fr:code>QUEUE</fr:code> signature</fr:link> to give a signature for imperative queues:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature IQUEUE =
  sig
    type 'a t  (* abstract *)

    val empty : unit -&gt; 'a t
    val enqueue : 'a queue -&gt; 'a -&gt; unit
    val dequeue : 'a queue -&gt; 'a option
  end
</html:code></fr:pre><fr:p>Unlike in <fr:code>QUEUE</fr:code>, the operations in <fr:code>IQUEUE</fr:code> do not return an updated queue; they mutate the given queue.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1376</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BY</fr:addr><fr:route>150-00BY.xml</fr:route><fr:title>Imperative queues using lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can implement the <fr:link
href="150-00BX.xml"
type="local"
addr="150-00BX">imperative queue signature</fr:link> using lists, adapting our implementation of <fr:link
href="150-008O.xml"
type="local"
addr="150-008O">abstract types</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure ListIQueue :&gt; IQUEUE =
  struct
    type 'a queue = 'a list ref

    fun empty () = ref nil

    fun enqueue r x = r := !r @ [x]

    fun dequeue r =
      case !r of
        nil =&gt; NONE
      | x :: xs =&gt; SOME x before r := xs
  end
</html:code></fr:pre><fr:p>The cost is the same as before, but now implemented using mutable state.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1379</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BZ</fr:addr><fr:route>150-00BZ.xml</fr:route><fr:title>Imperative queues using linked lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For constant-time efficiency, we can implement queues using linked lists. A linked list is defined as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a front = Nil | Cons of 'a * 'a front ref
type 'a llist = 'a front ref
</html:code></fr:pre><fr:p>In other words, a linked list is a reference cell containing either <fr:code>Nil</fr:code> or <fr:code>Cons</fr:code>, where the tail in the <fr:code>Cons</fr:code> case is also a reference cell.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure LinkedIQueue :&gt; IQUEUE =
  struct
    datatype 'a front = Nil | Cons of 'a * 'a front ref
    type 'a llist = 'a front ref

    (* INVARIANTs: for (front, back), we have that
     * 1. !(!back) = Nil, and
     * 2. !back is at the end of !front.
     *)
    type 'a queue = 'a llist ref * 'a llist ref

    fun empty () : 'a queue =
      let
        val r : 'a llist = ref Nil
      in
        (ref r, ref r)
      end

    fun enqueue (_, back : 'a llist ref) (x : 'a) : unit =
      let
        val r = ref Nil
      in
        !back := Cons (x, r);
        back := r
      end

    fun dequeue (front, _) =
      case !(!front) of
        Nil =&gt; NONE
      | Cons (x, r) =&gt; SOME x before front := r
  end
</html:code></fr:pre><fr:p>The operations work as follows.</fr:p><fr:ol><fr:li>To make an empty queue, we make an empty linked list, <fr:code>ref Nil</fr:code>, and create two pointers that both point to this same linked list.</fr:li>
  <fr:li>To enqueue, we create a new empty linked list <fr:code>r</fr:code>, we mutate the back of the linked list to be <fr:code>Cons (x, r)</fr:code> instead of <fr:code>Nil</fr:code>, and then we update the <fr:code>back</fr:code> pointer to the new back, <fr:code>r</fr:code>.</fr:li>
  <fr:li>To dequeue, we look at the data contained at the front of the queue, and we case to see if it is <fr:code>Nil</fr:code> or <fr:code>Cons (x, r)</fr:code>. In the former case, the queue has no data remaining. In the latter case, we give back <fr:code>SOME x</fr:code>, and we change the front to point to the tail, <fr:code>r</fr:code>.</fr:li></fr:ol><fr:p>All three operations are implemented to have constant time. However, since we use mutation, they are not safe for use in parallel: different processes enqueueing and dequeueing in parallel could lead to race conditions.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1408</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect21</fr:addr><fr:route>150-lect21.xml</fr:route><fr:title>Amortized analysis</fr:title><fr:date><fr:year>2024</fr:year><fr:month>7</fr:month><fr:day>30</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>In this lecture, we will explore amortized analysis <fr:link
href="https://arxiv.org/abs/2404.03641"
type="external">viewed through structure-preserving maps</fr:link>, using an asymmetric analogue of <fr:link
href="150-008V.xml"
type="local"
addr="150-008V">representation independence</fr:link>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1399</fr:anchor><fr:addr>150-00C0</fr:addr><fr:route>150-00C0.xml</fr:route><fr:title>Homomorphisms: structure-preserving transformations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We consider what a structure-preserving transformation between <fr:link
href="150-008J.xml"
type="local"
addr="150-008J">structures</fr:link> of the same <fr:link
href="150-008H.xml"
type="local"
addr="150-008H">signature</fr:link>.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1388</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00C1</fr:addr><fr:route>150-00C1.xml</fr:route><fr:title>Type transformation</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following simple signature:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature S =
  sig
    type t
  end
</html:code></fr:pre><fr:p>A transformation from <fr:code>M1 : S</fr:code> to <fr:code>M2 : S</fr:code> is a function <fr:code>M1.t -&gt; M2.t</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1391</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00C2</fr:addr><fr:route>150-00C2.xml</fr:route><fr:title><fr:link
href="150-0092.xml"
type="local"
addr="150-0092"><fr:code>ORDERED</fr:code> type class</fr:link> transformation</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Recall the <fr:link
href="150-0092.xml"
type="local"
addr="150-0092"><fr:code>ORDERED</fr:code> type class</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature ORDERED =
  sig
    type t
    val compare : t * t -&gt; order
  end
</html:code></fr:pre><fr:p>Consider the following implementations:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure NatOrdered : ORDERED =
  struct
    type t = int  (* INVARIANT: non-negative *)
    val compare = Int.compare
  end

structure StringOrdered : ORDERED =
  struct
    type t = string
    val compare = String.compare
  end
</html:code></fr:pre><fr:p>A structure-preserving transformation from <fr:code>NatOrdered</fr:code> to <fr:code>StringOrdered</fr:code> should consist of:</fr:p><fr:ol><fr:li>A function <fr:code>f : NatOrdered.t -&gt; StringOrdered.t</fr:code>, i.e. a function <fr:code>f : int -&gt; string</fr:code>, such that</fr:li>
  <fr:li>for all <fr:code>i1</fr:code> and <fr:code>i2</fr:code>, we have <fr:tex>\texttt {Int.compare (i1, i2)} \cong  \texttt {String.compare (f i1, f i2)}</fr:tex>, also visualized as the following <fr:link
href="https://en.wikipedia.org/wiki/Commutative_diagram"
type="external">commutative diagram</fr:link>, where <fr:code>f *** g</fr:code> is defined as <fr:code>fn (x, y) =&gt; (f x, g y)</fr:code>:
    <fr:embedded-tex
hash="7cf95aec9c944029ba9c7a9063d9845c"><fr:embedded-tex-preamble>
      \usepackage {tikz,tikz-cd}
      \usetikzlibrary {arrows}
      \usetikzlibrary {backgrounds,fit,positioning,calc,shapes}
      \tikzset {
        diagram/.style = {
          on grid,
          node distance=4cm,
          commutative diagrams/every diagram,
          line width = .5pt,
          every node/.append style = {
            commutative diagrams/every cell,
          }
        }
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[diagram]
        \node  (nw) {$\texttt {int * int}$};
        \node [below = of nw] (ne) {$\texttt {string * string}$};
        \node [right = of ne] (se) {$\texttt {order}$};
        \draw [-&gt;] (nw) to node[sloped,above] {$\texttt {Int.compare}$} (se);
        \draw [-&gt;] (ne) to node[below] {$\texttt {String.compare}$} (se);
        \draw [-&gt;] (nw) to node[left] {$\texttt {f *** f}$} (ne);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol><fr:p>Some examples of such functions <fr:code>f</fr:code> would be:</fr:p><fr:ul><fr:li><fr:code>fn i =&gt; repeat #"a" i</fr:code>,</fr:li>
  <fr:li><fr:code>fn i =&gt; "b" ^ repeat #"a" i</fr:code>, and</fr:li>
  <fr:li><fr:code>fn i =&gt; repeat #"a" (log10 i) ^ Int.toString i</fr:code>.</fr:li></fr:ul><fr:p>Some non-examples would be:</fr:p><fr:ul><fr:li><fr:code>Int.toString</fr:code> and</fr:li>
  <fr:li><fr:code>fn _ =&gt; ""</fr:code>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1393</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00C3</fr:addr><fr:route>150-00C3.xml</fr:route><fr:title><fr:code>SCALE</fr:code> transformation</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following signature, <fr:code>SCALE</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SCALE =
  sig
    type t
    val scale : int -&gt; t -&gt; t
  end
</html:code></fr:pre><fr:p>A structure-preserving transformation from <fr:code>M1 : SCALE</fr:code> to <fr:code>M2 : SCALE</fr:code> should consist of:</fr:p><fr:ol><fr:li>A function <fr:code>f : M1.t -&gt; M2.t</fr:code> such that</fr:li>
  <fr:li>for all <fr:code>i : int</fr:code>, we have <fr:tex>\texttt {f o M1.scale i} \cong  \texttt {M2.scale i o f}</fr:tex>, also visualized as the following <fr:link
href="https://en.wikipedia.org/wiki/Commutative_diagram"
type="external">commutative diagram</fr:link>:
    <fr:embedded-tex
hash="1af6bfdd5b84a79b3f44bc15d93c3bc3"><fr:embedded-tex-preamble>
      \usepackage {tikz,tikz-cd}
      \usetikzlibrary {arrows}
      \usetikzlibrary {backgrounds,fit,positioning,calc,shapes}
      \tikzset {
        diagram/.style = {
          on grid,
          node distance=4cm,
          commutative diagrams/every diagram,
          line width = .5pt,
          every node/.append style = {
            commutative diagrams/every cell,
          }
        }
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[diagram]
        \node  (nw) {$\texttt {M1.t}$};
        \node [right = of nw] (ne) {$\texttt {M1.t}$};
        \node [below = of nw] (sw) {$\texttt {M2.t}$};
        \node [below = of ne] (se) {$\texttt {M2.t}$};
        \draw [-&gt;] (nw) to node[above] {$\texttt {M1.scale i}$} (ne);
        \draw [-&gt;] (sw) to node[above] {$\texttt {M2.scale i}$} (se);
        \draw [-&gt;] (nw) to node[right] {$\texttt {f}$} (sw);
        \draw [-&gt;] (ne) to node[right] {$\texttt {f}$} (se);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1397</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00C4</fr:addr><fr:route>150-00C4.xml</fr:route><fr:title><fr:code>QUEUE</fr:code> transformation</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following simplification of <fr:link
href="150-008O.xml"
type="local"
addr="150-008O">the <fr:code>QUEUE</fr:code> signtaure</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature QUEUE =
  sig
    type queue

    val empty : queue
    val enqueue : int -&gt; queue -&gt; queue
    val dequeue : queue -&gt; int * queue
  end
</html:code></fr:pre><fr:p>We fix the element type to be <fr:code>int</fr:code>. Also, we avoid options in the <fr:code>dequeue</fr:code> output; when the queue is empty, we always dequeue <fr:code>0</fr:code>. As before, we can implement queues using <fr:link
href="150-008O.xml"
type="local"
addr="150-008O">lists</fr:link> or <fr:link
href="150-008R.xml"
type="local"
addr="150-008R">pairs of lists</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure LQ : QUEUE =
  struct
    type queue = int list

    val empty = nil
    fun enqueue x l = l @ [x]
    fun dequeue nil = (0, nil)
      | dequeue (x :: xs) = (x, xs)
  end

structure BQ : QUEUE =
  struct
    type queue = int list * int list

    val empty = (nil, nil)
    fun enqueue x (front, back) = (front, x :: back)
    fun dequeue (x :: front, back) = (x, (front, back))
      | dequeue (nil, back) =
          case List.rev back of
            nil =&gt; (0, (nil, nil))
          | x :: front =&gt; (x, (front, nil))
  end
</html:code></fr:pre><fr:p>Note: although we typically use opaque ascription for the <fr:code>QUEUE</fr:code> signature, we will only use transparent ascription in this lecture.</fr:p><fr:p>A structure-preserving transformation from <fr:code>BQ : QUEUE</fr:code> to <fr:code>LQ : QUEUE</fr:code> should consist of:</fr:p><fr:ol><fr:li>A function <fr:code>f : BQ.t -&gt; LQ.t</fr:code>, i.e. a function <fr:code>f : int list * int list -&gt; int list</fr:code>, such that</fr:li>
  <fr:li><fr:tex>\texttt {f BQ.empty} \cong  \texttt {LQ.empty}</fr:tex>,</fr:li>
  <fr:li>for all <fr:code>i : int</fr:code>, we have <fr:tex
display="block">\texttt {f o BQ.enqueue i} \cong  \texttt {LQ.enqueue i o f},</fr:tex> also visualized as the following <fr:link
href="https://en.wikipedia.org/wiki/Commutative_diagram"
type="external">commutative diagram</fr:link>:
    <fr:embedded-tex
hash="87705056bc3f768ae78753a295fc88c1"><fr:embedded-tex-preamble>
      \usepackage {tikz,tikz-cd}
      \usetikzlibrary {arrows}
      \usetikzlibrary {backgrounds,fit,positioning,calc,shapes}
      \tikzset {
        diagram/.style = {
          on grid,
          node distance=6cm,
          commutative diagrams/every diagram,
          line width = .5pt,
          every node/.append style = {
            commutative diagrams/every cell,
          }
        }
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[diagram]
        \node  (nw) {$\texttt {int list * int list}$};
        \node [right = of nw] (ne) {$\texttt {int list * int list}$};
        \node [below = of nw] (sw) {$\texttt {int list}$};
        \node [below = of ne] (se) {$\texttt {int list}$};
        \draw [-&gt;] (nw) to node[above] {$\texttt {BQ.enqueue i}$} (ne);
        \draw [-&gt;] (sw) to node[above] {$\texttt {LQ.enqueue i}$} (se);
        \draw [-&gt;] (nw) to node[right] {$\texttt {f}$} (sw);
        \draw [-&gt;] (ne) to node[right] {$\texttt {f}$} (se);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>we have <fr:tex
display="block">\texttt {(Fn.id *** f) o BQ.dequeue} \cong  \texttt {LQ.dequeue o f},</fr:tex> also visualized as the following <fr:link
href="https://en.wikipedia.org/wiki/Commutative_diagram"
type="external">commutative diagram</fr:link>:
    <fr:embedded-tex
hash="4f468ab051d0c612bcb39f577f1e42f6"><fr:embedded-tex-preamble>
      \usepackage {tikz,tikz-cd}
      \usetikzlibrary {arrows}
      \usetikzlibrary {backgrounds,fit,positioning,calc,shapes}
      \tikzset {
        diagram/.style = {
          on grid,
          node distance=6cm,
          commutative diagrams/every diagram,
          line width = .5pt,
          every node/.append style = {
            commutative diagrams/every cell,
          }
        }
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[diagram]
        \node  (nw) {$\texttt {int list * int list}$};
        \node [right = of nw] (ne) {$\texttt {int * (int list * int list)}$};
        \node [below = of nw] (sw) {$\texttt {int list}$};
        \node [below = of ne] (se) {$\texttt {int * int list}$};
        \draw [-&gt;] (nw) to node[above] {$\texttt {BQ.dequeue}$} (ne);
        \draw [-&gt;] (sw) to node[above] {$\texttt {LQ.dequeue}$} (se);
        \draw [-&gt;] (nw) to node[right] {$\texttt {f}$} (sw);
        \draw [-&gt;] (ne) to node[right] {$\texttt {Fn.id *** f}$} (se);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol><fr:p>The classic example of such a function <fr:code>f</fr:code> is:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f ((front, back) : int list * int list) : int list =
  front @ List.rev back
</html:code></fr:pre><fr:p>Notice the close parallels to the representation independence proof of the <fr:link
href="150-008U.xml"
type="local"
addr="150-008U">equivalence of queues</fr:link>! If we replace the function <fr:code>f</fr:code> with a relation <fr:tex>R</fr:tex>, we recover the representation independence conditions and proof exactly.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1398</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-00C5</fr:addr><fr:route>150-00C5.xml</fr:route><fr:title>Stacked commutative squares</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Notice that the commutative squares of <fr:ref
addr="150-00C4"
href="150-00C4.xml"
taxon="Example"></fr:ref> can be stacked next to each other. For example:</fr:p><fr:embedded-tex
hash="cb4a07b088692c025f3cb93a730b0b8a"><fr:embedded-tex-preamble>
  \usepackage {tikz,tikz-cd}
  \usetikzlibrary {arrows}
  \usetikzlibrary {backgrounds,fit,positioning,calc,shapes}
  \tikzset {
    diagram/.style = {
      on grid,
      node distance=6cm,
      commutative diagrams/every diagram,
      line width = .5pt,
      every node/.append style = {
        commutative diagrams/every cell,
      }
    }
  }
</fr:embedded-tex-preamble><fr:embedded-tex-body>
  \begin {tikzpicture}[diagram]
    \node  (nw) {$\texttt {int list * int list}$};
    \node [right = of nw] (ne) {$\texttt {int * (int list * int list)}$};
    \node [below = of nw] (sw) {$\texttt {int list}$};
    \node [below = of ne] (se) {$\texttt {int * int list}$};
    \node [left = of nw] (nww) {$\texttt {int list * int list}$};
    \node [left = of sw] (sww) {$\texttt {int list}$};
    \node [left = of nww] (nwww) {$\texttt {int list * int list}$};
    \node [left = of sww] (swww) {$\texttt {int list}$};
    \draw [-&gt;] (nw) to node[above] {$\texttt {BQ.dequeue}$} (ne);
    \draw [-&gt;] (sw) to node[above] {$\texttt {LQ.dequeue}$} (se);
    \draw [-&gt;] (nw) to node[right] {$\texttt {f}$} (sw);
    \draw [-&gt;] (ne) to node[right] {$\texttt {Fn.id *** f}$} (se);
    \draw [-&gt;] (nww) to node[above] {$\texttt {BQ.enqueue i}$} (nw);
    \draw [-&gt;] (sww) to node[above] {$\texttt {LQ.enqueue i}$} (sw);
    \draw [-&gt;] (nww) to node[right] {$\texttt {f}$} (sww);
    \draw [-&gt;] (nwww) to node[above] {$\texttt {BQ.enqueue i}$} (nww);
    \draw [-&gt;] (swww) to node[above] {$\texttt {LQ.enqueue i}$} (sww);
    \draw [-&gt;] (nwww) to node[right] {$\texttt {f}$} (swww);
  \end {tikzpicture}
</fr:embedded-tex-body></fr:embedded-tex></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1407</fr:anchor><fr:addr>150-00C6</fr:addr><fr:route>150-00C6.xml</fr:route><fr:title>Amortized analysis via homomorphisms</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1400</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-00C7</fr:addr><fr:route>150-00C7.xml</fr:route><fr:title>Amortized analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:em>Amortized analysis</fr:em> formalizes the idea that an expensive operation can occur infrequently enough that the high cost "averages out" over time.</fr:p><fr:p>For example, if you pay $300 of rent at the end of each month (30 days), you can fictionally imagine that you pay $10 per day. While reality and fiction do not line up exactly, they do at a large scale: at the end of a 30-day period, both reality and fiction agree that $300 must be the total paid during the month.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1401</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00C8</fr:addr><fr:route>150-00C8.xml</fr:route><fr:title>Visualizing cost with the <fr:link
href="150-00BI.xml"
type="local"
addr="150-00BI"><fr:code>print</fr:code> effect</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To visualize the cost of a program, we can run <fr:code>print "$"</fr:code> every time our <fr:link
href="150-0031.xml"
type="local"
addr="150-0031">cost model</fr:link> says we used one abstract unit of cost.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1403</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00C9</fr:addr><fr:route>150-00C9.xml</fr:route><fr:title>Cost-annotated queues</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can adapt our <fr:link
href="150-00C4.xml"
type="local"
addr="150-00C4"><fr:code>QUEUE</fr:code> implementations</fr:link> to <fr:link
href="150-00C8.xml"
type="local"
addr="150-00C8">visualize cost</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure BQ : QUEUE =
  struct
    type queue = int list * int list

    val empty = (nil, nil)
    fun enqueue x (front, back) = (front, x :: back)
    fun dequeue (x :: front, back) = (x, (front, back))
      | dequeue (nil, back) =
          case (print (repeat #"$" (List.length back)); List.rev back) of
            nil =&gt; (0, (nil, nil))
          | x :: front =&gt; (x, (front, nil))
  end

structure LQ : QUEUE =
  struct
    type queue = int list

    val empty = nil
    fun enqueue x l = (print "$"; l @ [x])
    fun dequeue nil = (0, nil)
      | dequeue (x :: xs) = (x, xs)
  end
</html:code></fr:pre><fr:p>The <fr:code>BQ</fr:code> annotation is realistic, tracking the number of recursive calls. The <fr:code>LQ</fr:code> annotation, on the other hand, is entirely fictional: we will only read <fr:code>LQ</fr:code> as a specification of what <fr:code>BQ</fr:code> is intended to cost, up to amortization.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1406</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00CA</fr:addr><fr:route>150-00CA.xml</fr:route><fr:title>Transformation for cost-visualized queues</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In <fr:ref
addr="150-00C4"
href="150-00C4.xml"
taxon="Example"></fr:ref>, we gave a function that transformed <fr:code>BQ</fr:code> to <fr:code>LQ</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f ((front, back) : int list * int list) : int list =
  front @ List.rev back
</html:code></fr:pre><fr:p>Given our <fr:link
href="150-00C9.xml"
type="local"
addr="150-00C9">cost-annotated queues</fr:link>, is this still a transformation between the <fr:code>QUEUE</fr:code> implementations? While some of the squares commute, such as the <fr:link
href="150-00C5.xml"
type="local"
addr="150-00C5">stacked commutative squares</fr:link> shown, <fr:link
href="150-00C4.xml"
type="local"
addr="150-00C4">the requisite conditions</fr:link> do not all hold.</fr:p><fr:p>To fix this, we can make <fr:code>f</fr:code> itself <fr:link
href="150-00BI.xml"
type="local"
addr="150-00BI">visualize some fictional cost</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f ((front, back) : int list * int list) : int list =
  ( print (repeat "$" (List.length back));
  ; front @ List.rev back
  )
</html:code></fr:pre><fr:p>This causes all of the necessary conditions to hold. The number of <fr:code>$</fr:code>s printed by <fr:code>f</fr:code> represents the amount of <fr:code>$</fr:code>s that <fr:code>LQ</fr:code> has pretended we printed even though <fr:code>BQ</fr:code> hasn't gotten around to it yet. Traditionally, this quantity is called the <fr:em>potential</fr:em> of a data structure state (here, <fr:code>(front, back)</fr:code>).</fr:p><fr:p>This function <fr:code>f</fr:code>, along with the proof that it satisfies the conditions, justifies that the operations for purely-functional batched queues have amortized constant cost: the same as <fr:link
href="150-00BZ.xml"
type="local"
addr="150-00BZ">imperative queues using linked lists</fr:link>.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1511</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-lect22</fr:addr><fr:route>150-lect22.xml</fr:route><fr:title>Review</fr:title><fr:date><fr:year>2024</fr:year><fr:month>8</fr:month><fr:day>1</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:p>This lecture is inspired by an analogous lecture by <fr:link
href="me51.xml"
type="local"
addr="me51">Michael Erdmann</fr:link> and <fr:link
href="bjwu.xml"
type="local"
addr="bjwu">Brandon Wu</fr:link>.</fr:p>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1424</fr:anchor><fr:addr>150-00CB</fr:addr><fr:route>150-00CB.xml</fr:route><fr:title>Imperative programming</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> mutability is not so bad, as long as it's contained.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1416</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-00BX</fr:addr><fr:route>150-00BX.xml</fr:route><fr:title>Imperative queue signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can augment <fr:link
href="150-008O.xml"
type="local"
addr="150-008O">the <fr:code>QUEUE</fr:code> signature</fr:link> to give a signature for imperative queues:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature IQUEUE =
  sig
    type 'a t  (* abstract *)

    val empty : unit -&gt; 'a t
    val enqueue : 'a queue -&gt; 'a -&gt; unit
    val dequeue : 'a queue -&gt; 'a option
  end
</html:code></fr:pre><fr:p>Unlike in <fr:code>QUEUE</fr:code>, the operations in <fr:code>IQUEUE</fr:code> do not return an updated queue; they mutate the given queue.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1417</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BP</fr:addr><fr:route>150-00BP.xml</fr:route><fr:title>Reference primitives</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The standard library includes the following signature:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature REF =
  sig
    type 'a ref

    val ref : 'a -&gt; 'a ref
    val !   : 'a ref -&gt; 'a
    val :=  : 'a ref * 'a -&gt; unit  (* infix *)

    (* ...some helper functions... *)
  end
</html:code></fr:pre><fr:ol><fr:li>The type <fr:code>t ref</fr:code> represents mutable reference cells that store a value of type <fr:code>t</fr:code>.</fr:li>
  <fr:li>The function <fr:code>ref</fr:code> allocates a new reference cell, where the starting value of the cell is the input.</fr:li>
  <fr:li>The function <fr:code>!</fr:code> accesses the current value of the reference cell given.</fr:li>
  <fr:li>The infix function <fr:code>op :=</fr:code> takes a reference cell (of type <fr:code>t ref</fr:code>) and a compatible value (of type <fr:code>t</fr:code>) and replaces the data in the reference cell with the given value.</fr:li></fr:ol><fr:p>All of these definitions are available at the top level. The use of references is considered an <fr:link
href="150-00BB.xml"
type="local"
addr="150-00BB">effect</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1418</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BF</fr:addr><fr:route>150-00BF.xml</fr:route><fr:title>Total</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:code>f : t1 -&gt; t2</fr:code> is <fr:em>total</fr:em> when for all values <fr:code>x : t1</fr:code>, we have that <fr:code>f x</fr:code> is a <fr:link
href="150-00B4.xml"
type="local"
addr="150-00B4">pure</fr:link> expression.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1419</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00BK</fr:addr><fr:route>150-00BK.xml</fr:route><fr:title>Pattern matching and purity</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the presence of effects, a function defined by pattern matching only says what happens given a pure argument, since in a <fr:link
href="150-000Z.xml"
type="local"
addr="150-000Z">function application</fr:link>, arguments are evaluated first.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1420</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00B3</fr:addr><fr:route>150-00B3.xml</fr:route><fr:title>Extensional equivalence with effects</fr:title></fr:frontmatter><fr:mainmatter><fr:p>When considering exceptions, we say that <fr:tex>e_1 \cong  e_2</fr:tex> when both:</fr:p><fr:ol><fr:li><fr:tex>e_1</fr:tex> and <fr:tex>e_2</fr:tex> perform indistinguishable effects; for example, they raise the same exceptions, loop infinitely, or print the same string.</fr:li>
  <fr:li>If <fr:tex>e_1 \hookrightarrow  v_1</fr:tex> and <fr:tex>e_2 \hookrightarrow  v_2</fr:tex>, then <fr:tex>v_1 \cong  v_2</fr:tex> as pure expressions (i.e., as described before).</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1421</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00B4</fr:addr><fr:route>150-00B4.xml</fr:route><fr:title>Pure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Say that an expression <fr:tex>e</fr:tex> is <fr:em>pure</fr:em> when there exists some value <fr:tex>v</fr:tex> such that <fr:tex>e \hookrightarrow  v</fr:tex> without performing any observable effects.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1422</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00BB</fr:addr><fr:route>150-00BB.xml</fr:route><fr:title>Effect</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An <fr:em>effect</fr:em> is something the evaluation of a program can do aside from returning a value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1423</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-00AZ</fr:addr><fr:route>150-00AZ.xml</fr:route><fr:title><fr:code>raise</fr:code> expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The expression <fr:code>raise Fail "TODO"</fr:code> has most general type <fr:code>'a</fr:code>, filling in for any type we wish. More generally, <fr:code>raise e</fr:code> has most general type <fr:code>'a</fr:code>, for any exception <fr:code>e</fr:code>.</fr:p><fr:p>Unlike other expressions, it does not evaluate to <fr:em>any</fr:em> value.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1432</fr:anchor><fr:addr>150-00CC</fr:addr><fr:route>150-00CC.xml</fr:route><fr:title>Sequences</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> functional programming and mathematical reasoning provide elegant primitives for parallelism.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1426</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00AB</fr:addr><fr:route>150-00AB.xml</fr:route><fr:title>Sequence <fr:code>reduce</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>Seq.reduce</fr:code> combines the data in a sequence using a <fr:link
href="150-00A6.xml"
type="local"
addr="150-00A6">monoid</fr:link>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* Seq.reduce : ('a * 'a -&gt; 'a) -&gt; 'a -&gt; 'a Seq.t -&gt; 'a
 * REQUIRES: g and z form a monoid
 * ENSURES: Seq.reduce g z &lt;x0, x1, ..., x_{n-1}&gt; ~= g (x0, g (x1, ..., g (x_{n-1}, z)))
 *)
</html:code></fr:pre><fr:p>Notice that the behavior of <fr:code>reduce</fr:code> exactly mirrors <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>, and its type is an instance of the type of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link>. However, thanks to the assumption that <fr:code>g</fr:code> and <fr:code>z</fr:code> form a monoid, <fr:code>reduce</fr:code> is more efficient than <fr:code>foldr</fr:code> in parallel.</fr:p><fr:p>
  Its cost graph is depicted as follows:
  <fr:embedded-tex
hash="36269934c8d91cfdda875f6a97a99477"><fr:embedded-tex-preamble>
    \usepackage {tikz}
    \usetikzlibrary {arrows,shapes.geometric}
    \tikzset {
      hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
    }
  </fr:embedded-tex-preamble><fr:embedded-tex-body>
    \begin {tikzpicture}[-&gt;]
      \node  (start) at (0, 1) {$\bullet $};
      \node [hexagon] (g0) at (-2.5, 0) {\texttt {g}};
      \node [hexagon] (g1) at (-1, 0) {\texttt {g}};
      \node  at (0, 0) {$\cdots $};
      \node [hexagon] (g2) at (1, 0) {\texttt {g}};
      \node [hexagon] (g3) at (2.5, 0) {\texttt {g}};
      \node [hexagon] (gg0) at (-1.75, -1) {\texttt {g}};
      \node [hexagon] (gg1) at (1.75, -1) {\texttt {g}};
      \node [hexagon] (ggg) at (0, -2) {\texttt {g}};

      \path  (start) edge (g0);
      \path  (start) edge (g1);
      \path  (start) edge (g2);
      \path  (start) edge (g3);
      \path  (g0) edge (gg0);
      \path  (g1) edge (gg0);
      \path  (g2) edge (gg1);
      \path  (g3) edge (gg1);
      \path  (gg0) edge (ggg);
      \path  (gg1) edge (ggg);
    \end {tikzpicture}
  </fr:embedded-tex-body></fr:embedded-tex>
  Its work and span <fr:em>depend on the cost of <fr:code>g</fr:code></fr:em>, but assuming <fr:code>g</fr:code> is constant-time, then <fr:code>reduce g z S</fr:code> has work <fr:tex>\mathcal {O}(n)</fr:tex> and span <fr:tex>\mathcal {O}(\log  n)</fr:tex>.
</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1427</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-00A6</fr:addr><fr:route>150-00A6.xml</fr:route><fr:title>Monoid</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>monoid</fr:em> consists of:</fr:p><fr:ol><fr:li>a type <fr:code>t</fr:code>,</fr:li>
  <fr:li>some <fr:code>z : t</fr:code>,</fr:li>
  <fr:li>and some <fr:code>g : t * t -&gt; t</fr:code> such that</fr:li>
  <fr:li><fr:code>z</fr:code> is an <fr:link
href="150-00A7.xml"
type="local"
addr="150-00A7">identity element</fr:link> for <fr:code>g</fr:code>, and</fr:li>
  <fr:li><fr:code>g</fr:code> is an <fr:link
href="150-00A8.xml"
type="local"
addr="150-00A8">associative function</fr:link>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1428</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-009X</fr:addr><fr:route>150-009X.xml</fr:route><fr:title>Limited sequence signature: indexed collection</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The sequence signature includes the following specifications:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature SEQUENCE =
  sig
    type 'a t  (* abstract *)
    type 'a seq = 'a t  (* concrete *)

    val tabulate : (int -&gt; 'a) -&gt; int -&gt; 'a seq
    val length : 'a seq -&gt; int
    val nth : 'a seq -&gt; int -&gt; 'a

    (* ...more to come... *)
  end
</html:code></fr:pre><fr:p>The abstract type <fr:code>'a t</fr:code> represents a sequence of <fr:code>'a</fr:code>s, where <fr:code>'a seq</fr:code> is an alias for signature readability.</fr:p><fr:p>The implementation of <fr:code>SEQUENCE</fr:code> is called <fr:code>Seq</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">structure Seq :&gt; SEQUENCE = (* ... *)
</html:code></fr:pre><fr:p>The full signature and documentation is available on <fr:link
href="http://www.cs.cmu.edu/~15150/resources/libraries/sequence.pdf"
type="external">the course website</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1429</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009V</fr:addr><fr:route>150-009V.xml</fr:route><fr:title>Work and span of a cost graph</fr:title></fr:frontmatter><fr:mainmatter><fr:ol><fr:li>The <fr:em>work</fr:em> of a cost graph is the sum of the costs of all hexagonal nodes in the graph.</fr:li>
  <fr:li>The <fr:em>span</fr:em> of a cost graph is the sum of the costs of the hexagonal nodes on the path from the start node to the end node with the highest cost.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1430</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009S</fr:addr><fr:route>150-009S.xml</fr:route><fr:title>Cost graph</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>cost graph</fr:em> is a visualization technique for parallel processes consisting of a directed acyclic graph with designated start and end nodes. They are defined inductively as follows, where we implicitly treat all edges as top-to-bottom:</fr:p><fr:ol><fr:li>
    Atomic units are variables representing cost of an abstract operation, drawn using a hexagon:
    <fr:embedded-tex
hash="47e3f60755d4d4f26d0f504419e5c6c9"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  [hexagon] {\texttt {f}};
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>
    There is an empty cost graph <fr:tex>0</fr:tex>:
    <fr:embedded-tex
hash="f81f9820b8348f991649a49e01e0eabf"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  {$\bullet $};
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>Two cost graphs <fr:tex>G_1</fr:tex> and <fr:tex>G_2</fr:tex> can be composed in sequence, written <fr:tex>G_1 \triangleright  G_2</fr:tex>, representing data dependency:
    <fr:embedded-tex
hash="528359005d8acb8bc148f28d342173aa"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  (G1) at (0,1) {$G_1$};
        \node  (G2) at (0,0) {$G_2$};
        \path  (G1) edge (G2);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li>
  <fr:li>
    Two cost graphs <fr:tex>G_1</fr:tex> and <fr:tex>G_2</fr:tex> can be composed in parallel, written <fr:tex>G_1 \otimes  G_2</fr:tex>, representing data independence:
    <fr:embedded-tex
hash="8b34a78034ef9eb4849773bd8a1b4d05"><fr:embedded-tex-preamble>
      \usepackage {tikz}
      \usetikzlibrary {arrows,shapes.geometric}
      \tikzset {
        hexagon/.style = {text centered, regular polygon, regular polygon sides = 6, inner sep=0pt, draw=black, minimum width=1.5em}
      }
    </fr:embedded-tex-preamble><fr:embedded-tex-body>
      \begin {tikzpicture}[-&gt;]
        \node  (G1) at (-1,0) {$G_1$};
        \node  (G2) at (1,0) {$G_2$};
        \node  (start) at (0,1) {$\bullet $};
        \node  (end) at (0,-1) {$\bullet $};
        \path  (start) edge (G1);
        \path  (start) edge (G2);
        \path  (G1) edge (end);
        \path  (G2) edge (end);
      \end {tikzpicture}
    </fr:embedded-tex-body></fr:embedded-tex></fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1431</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-009P</fr:addr><fr:route>150-009P.xml</fr:route><fr:title>Functional parallelism</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Parallelism and functional programming go hand-in-hand.</fr:p><fr:ul><fr:li>At a low level, parallelism involves scheduling work to processors;</fr:li>
  <fr:li>but at a high level, parallelism involves indicating which expressions can be evaluated in parallel, without baking in a schedule.</fr:li></fr:ul><fr:p><fr:link
href="150-000X.xml"
type="local"
addr="150-000X">Functional programming helps</fr:link>:</fr:p><fr:ul><fr:li>Since there are no effects (like memory updates) available, evaluation order doesn't matter, and race conditions are impossible to even describe in code.</fr:li>
  <fr:li>Higher-order functions and abstract types allow complex parallelism techniques to be implemented under the hood but retain a simple interface.</fr:li>
  <fr:li>Work and span analysis lets us predict the parallel speedup without fixing the number of processors in advance.</fr:li></fr:ul></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1441</fr:anchor><fr:addr>150-00CD</fr:addr><fr:route>150-00CD.xml</fr:route><fr:title>Modules</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> code should be organized around its interface, hiding irrelevant implementation details and maintaining internal invariants as desired.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1434</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-009H</fr:addr><fr:route>150-009H.xml</fr:route><fr:title>Red-black invariants</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A full, balanced tree has the same number of nodes on every path from the root to each <fr:code>Empty</fr:code>. However, such trees only can have <fr:tex>2^d - 1</fr:tex> nodes, where <fr:tex>d</fr:tex> is the height (depth) of the tree. In order to maintain a similar invariant, we color some nodes <fr:em>black</fr:em> and some nodes <fr:em>red</fr:em> and only count the <fr:em>black</fr:em> nodes. The <fr:em>red</fr:em> nodes are just to fix "off-by-one" errors, where we want to add more data to a tree but don't want to increase the black height. This leads us to the following pair of invariants.</fr:p><fr:p>The <fr:em>red-black tree invariants</fr:em> require that:
<fr:ol><fr:li>Every path from the root to each <fr:code>Empty</fr:code> have the same number of black nodes, called the <fr:em>black height</fr:em>. (We treat <fr:code>Empty</fr:code> as black with black height zero.)</fr:li>
  <fr:li>There are no two red nodes adjacent to each other (referred to as <fr:em>red-red violations</fr:em>), i.e. every red parent node has two black child nodes.</fr:li></fr:ol>
The first invariant guarantees that the trees are balanced ignoring red nodes, and the second invariant ensures that ther aren't "too many" red nodes in a given tree.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1435</fr:anchor><fr:taxon>Goal</fr:taxon><fr:addr>150-009G</fr:addr><fr:route>150-009G.xml</fr:route><fr:title>Self-balancing binary search tree</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Our <fr:link
href="150-0099.xml"
type="local"
addr="150-0099">implementation of dictionaries using trees</fr:link> has a major cost issue: while the operations are efficient (logarithmic time) when the tree is balanced, nothing prevents the tree from getting unbalanced.</fr:p><fr:p>We hope to implement dictionaries using trees with invariants that force them to remain balanced. Recall <fr:link
href="150-003D.xml"
type="local"
addr="150-003D">from earlier</fr:link> that a perfectly balanced tree has depth <fr:tex>\log _2(n + 1)</fr:tex> when there are <fr:tex>n</fr:tex> nodes in the tree.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1436</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0098</fr:addr><fr:route>150-0098.xml</fr:route><fr:title>Functor</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>functor</fr:em> is a function that takes in a <fr:link
href="150-008J.xml"
type="local"
addr="150-008J">structure</fr:link> and produces another structure. The analogy is:</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
  <html:tr>
  <html:th>Expression Level</html:th>

  <html:th>Module Level</html:th>
</html:tr>

  
    
  <html:tr>
  <html:td>type</html:td>

  <html:td>signature</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td>expression</html:td>

  <html:td>structure</html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td>function</html:td>

  <html:td>functor</html:td>
</html:tr>

  
</html:table>
<fr:p>(Unfortunately, ideas such as "functors are values", "higher-order functors", and "functor signatures" are not present in Standard ML itself.)</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1437</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0093</fr:addr><fr:route>150-0093.xml</fr:route><fr:title>Varieties of types in signatures</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Every type in a signature can be annotated to be <fr:em>abstract</fr:em>, <fr:em>parameter</fr:em>, or <fr:em>concrete</fr:em>.</fr:p><fr:ul><fr:li>If the type is unspecified via <fr:code>type t</fr:code>, it can be:
    <fr:ul><fr:li><fr:strong>abstract</fr:strong>, if it is meant to be hidden with opaque ascription; or</fr:li>
      <fr:li><fr:strong>parameter</fr:strong>, if it is meant to be known to clients with transparent ascription.</fr:li></fr:ul></fr:li>
  <fr:li>If type type is specified via <fr:code>type t = ...</fr:code>, it is <fr:strong>concrete</fr:strong>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1438</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0091</fr:addr><fr:route>150-0091.xml</fr:route><fr:title>Type class</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>type class</fr:em> is a <fr:link
href="150-008H.xml"
type="local"
addr="150-008H">signature</fr:link> containing a type <fr:em>parameter</fr:em> (meant to be transparent) alongside some operations involving the type.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signtaure MY_TYPE_CLASS =
  sig
    type t  (* parameter *)
    val f1 : (* ...involving t... *)
    val f2 : (* ...involving t... *)
    (* ... *)
  end
</html:code></fr:pre><fr:p>The type should be transparent, since a client is meant to use the operations freely. Type classes do not hide type information; they simply classify types supporting some operations.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1439</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-008V</fr:addr><fr:route>150-008V.xml</fr:route><fr:title>Structure equivalence via representation independence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Two structures <fr:code>M1, M2 : S</fr:code> are equivalent when:</fr:p><fr:ul><fr:li>For each abstract <fr:code>type t</fr:code>, we give a relation <fr:tex>R_\texttt {t}(-, -)</fr:tex> relating <fr:code>M1.t</fr:code> to <fr:code>M2.t</fr:code>.</fr:li>
  <fr:li>All values declared are <fr:tex>\cong </fr:tex>, where <fr:tex>R_\texttt {t}</fr:tex> is taken as the notion of equivalence for <fr:code>type t</fr:code>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1440</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-008S</fr:addr><fr:route>150-008S.xml</fr:route><fr:title>Dictionary signature</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can define a signature for dictionaries, which are (finite) mappings from keys (here, <fr:code>string</fr:code>s) to values (here, <fr:code>'a</fr:code>):</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">signature DICT =
  sig
    type key = string  (* concrete *)
    type 'a entry = key * 'a  (* concrete *)
    type 'a dict  (* abstract *)

    val empty : 'a dict
    val find : key -&gt; 'a dict -&gt; 'a option
    val insert : 'a entry -&gt; 'a dict -&gt; 'a dict
  end
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1449</fr:anchor><fr:addr>150-00CE</fr:addr><fr:route>150-00CE.xml</fr:route><fr:title>Regular expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> specification drives implementation, especially with complex code.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1443</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0085</fr:addr><fr:route>150-0085.xml</fr:route><fr:title>Union of two machines</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We can take the union of two machines, running them in parallel and using <fr:code>orelse</fr:code> to see if either will accept:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* plus : machine * machine -&gt; machine
 * REQUIRES: true
 * ENSURES: A(plus (m1, m2)) = A(m1) union A(m2)
 *)
fun plus (m1, m2) =
  Machine
    ( status m1 orelse status m2
    , fn c =&gt; plus (feed m1 c, feed m2 c)
    )
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1444</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0084</fr:addr><fr:route>150-0084.xml</fr:route><fr:title>Accept single character machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using the <fr:link
href="150-0081.xml"
type="local"
addr="150-0081">always-reject machine</fr:link> and <fr:link
href="150-0083.xml"
type="local"
addr="150-0083">accept empty string machine</fr:link>, we can implement a machine that only accepts the string <fr:code>"a"</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* char : char -&gt; machine
 * REQUIRES: true
 * ENSURES: A(char a) = {"a"}
 *)
fun char a =
  Machine (false, fn c =&gt; if a = c then one () else zero ())
</html:code></fr:pre><fr:p>We do not accept the empty string initially. After receiving character <fr:code>c</fr:code>, we check if it is equal to <fr:code>a</fr:code>. If so, we provide <fr:link
href="150-0083.xml"
type="local"
addr="150-0083">accept empty string machine</fr:link>, accepting the empty string afterwards; if not, we provide <fr:link
href="150-0081.xml"
type="local"
addr="150-0081">always-reject machine</fr:link>, failing to accept.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1445</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007Z</fr:addr><fr:route>150-007Z.xml</fr:route><fr:title>Lazy state machine</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We define state machines (sometimes known as <fr:em>automata</fr:em>) as a lazy datatype like <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">streams</fr:link>, but instead of having a single tail via <fr:code>unit -&gt;</fr:code>, we have one tail per character with <fr:code>char -&gt;</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype machine = Machine of bool * (char -&gt; machine)
</html:code></fr:pre><fr:p>We always expect a current value of type <fr:code>bool</fr:code>, representing whether or not the machine is in an accepting state (i.e., would accept the empty string). We could <fr:link
href="150-0072.xml"
type="local"
addr="150-0072">suspend</fr:link> the <fr:code>bool</fr:code>, but we choose not to for convenience.</fr:p><fr:p>Similar to <fr:link
href="150-0073.xml"
type="local"
addr="150-0073"><fr:code>head</fr:code> and <fr:code>tail</fr:code> for streams</fr:link>, we define the following helpers:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* status : machine -&gt; bool *)
fun status (Machine (b, _)) = b

(* feed : machine -&gt; char -&gt; machine *)
fun feed (Machine (_, f)) c = f c
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1446</fr:anchor><fr:taxon>Algorithm</fr:taxon><fr:addr>150-007L</fr:addr><fr:route>150-007L.xml</fr:route><fr:title>The <fr:code>match</fr:code> algorithm</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We implement <fr:link
href="150-007S.xml"
type="local"
addr="150-007S">this specification</fr:link> as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix &lt;&lt;
(* op &lt;&lt; : char list * char list -&gt; bool
 * REQUIRES: s' is a suffix of s
 * ENSURES:
 *   s' &lt;&lt; s ==&gt; true iff s' is a proper suffix of s, and
 *   s' &lt;&lt; s ==&gt; false iff s' = s.
 *)
fun s' &lt;&lt; s = length s' &lt; length s

(* match : regexp -&gt; char list -&gt; (char list -&gt; bool) -&gt; bool
 * REQUIRES: true
 * ENSURES:
 *   match r s p ~= true iff there exist x and y with x @ y ~= s and
 *   1. x in L(r) and
 *   2. p y ~= true.
 *)
fun match (r : regexp) (s : char list) (p : char list -&gt; bool) : bool =
  case r of
    Char a =&gt;
      ( case s of
          nil =&gt; false
        | c :: cs =&gt; a = c andalso p cs
      )
  | Zero =&gt; false
  | One =&gt; p s
  | Plus (r1, r2) =&gt; match r1 s p orelse match r2 s p
  | Times (r1, r2) =&gt; match r1 s (fn s' =&gt; match r2 s' p)
  | Star r' =&gt;
      p s orelse
      match r' s (fn s' =&gt; s' &lt;&lt; s andalso match (Star r') s' p)
</html:code></fr:pre><fr:p>The first four cases are similar to the <fr:link
href="150-007M.xml"
type="local"
addr="150-007M">inefficient implementation</fr:link>, using a predicate <fr:code>p : char list -&gt; bool</fr:code> in place of <fr:code>List.null</fr:code>. The <fr:code>Times</fr:code> and <fr:code>Star</fr:code> cases are more interesting:</fr:p><fr:ol><fr:li>In the <fr:code>Times (r1, r2)</fr:code> case, we <fr:em>recursively change the predicate</fr:em> being used on the tail. We match <fr:code>s</fr:code> against <fr:code>r1</fr:code>, and then we ask that the remainder match <fr:code>r2</fr:code>, which in turn asks that its remainder meets <fr:code>p</fr:code> as needed.</fr:li>
  <fr:li>In the <fr:code>Star r'</fr:code> case, we essentially match for <fr:code>Plus (One, Times (r', Star r'))</fr:code>. First, we check if <fr:code>s</fr:code> is already sufficient. If not, we match <fr:code>s</fr:code> against <fr:code>r</fr:code> once, and ask that the remainder <fr:code>s'</fr:code> match <fr:code>Star r'</fr:code> again.</fr:li></fr:ol><fr:p>In all cases but <fr:code>Star r'</fr:code>, we are going by recursion on the regular expression. In the second branch of the <fr:code>Star r'</fr:code> clause, though, we match against <fr:code>Star r'</fr:code> again. To guarantee termination, we make sure that <fr:code>s'</fr:code> is strictly smaller than <fr:code>s</fr:code>, so this function goes by lexicographic (dictionary-order) recusion on the regular expression <fr:code>r</fr:code> and then the character list <fr:code>s</fr:code>. Either <fr:code>r</fr:code> shrinks, or <fr:code>r</fr:code> stays the same size and <fr:code>s</fr:code> shrinks.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1447</fr:anchor><fr:taxon>Idea</fr:taxon><fr:addr>150-007S</fr:addr><fr:route>150-007S.xml</fr:route><fr:title><fr:code>accept</fr:code> via auxiliary function <fr:code>match</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* match : regexp -&gt; char list -&gt; (char list -&gt; bool) -&gt; bool
 * REQUIRES: true
 * ENSURES:
 *   match r s p ~= true iff there exist x and y with x @ y ~= s and
 *   1. x in L(r) and
 *   2. p y ~= true.
 *)
</html:code></fr:pre><fr:p>Using this stronger function, we can implement <fr:code>accept</fr:code> as desired:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* accept : regexp -&gt; char list -&gt; bool
 * REQUIRES: true
 * ENSURES: accept r s ~= true  iff  s in L(r)
 *)
fun accept (r : regexp) (s : char list) : bool =
  match r s List.null
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1448</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-007K</fr:addr><fr:route>150-007K.xml</fr:route><fr:title><fr:code>regexp</fr:code> datatype</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype regexp
  = Char of char
  | Zero
  | One
  | Plus of regexp * regexp
  | Times of regexp * regexp
  | Star of regexp
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1455</fr:anchor><fr:addr>150-00CF</fr:addr><fr:route>150-00CF.xml</fr:route><fr:title>Lazy programming</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> some data (inductive) is always available, while some data (coinductive) is only available on demand.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1451</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-007D</fr:addr><fr:route>150-007D.xml</fr:route><fr:title>Extensional equivalence at <fr:link
href="150-0073.xml"
type="local"
addr="150-0073">stream</fr:link> type: coinduction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Let <fr:code>t</fr:code> be an arbitrary type, and let <fr:code>s0</fr:code> and <fr:code>s0'</fr:code> be of type <fr:code>t stream</fr:code>. To show that <fr:tex>\texttt {s0} \cong  \texttt {s0'}</fr:tex>:</fr:p><fr:ol><fr:li>Choose a relation <fr:tex>R(-, -)</fr:tex> on pairs of <fr:code>t stream</fr:code>s that relates pairs of streams that you expect to be equivalent.</fr:li>
  <fr:li><fr:strong>Start State:</fr:strong> Show that <fr:tex>R(\texttt {s0}, \texttt {s0'})</fr:tex>, guaranteeing that the streams you care about are related.</fr:li>
  <fr:li><fr:strong>Preservation:</fr:strong> Then, show that for all <fr:code>s</fr:code> and <fr:code>s'</fr:code>, if <fr:tex>R(\texttt {s}, \texttt {s'})</fr:tex>, then:
    <fr:ol><fr:li>the heads are the same, <fr:tex>\texttt {head s} \cong  \texttt {head s'}</fr:tex> (the "co-base case", since no more stream data comes after the head); and</fr:li>
      <fr:li>the tails stay related, <fr:tex>R(\texttt {tail s}, \texttt {tail s'})</fr:tex> (the "coinductive conclusion", dual to the inductive hypothesis).</fr:li></fr:ol></fr:li></fr:ol><fr:p>This proof technique is called <fr:em>coinduction</fr:em>.</fr:p><fr:p>Notice that this definition has some similarities with <fr:link
href="150-000T.xml"
type="local"
addr="150-000T">extensional equivalence at function types</fr:link>: both check that you see equivalent results when you use the expressions in equivalent ways.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1452</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0076</fr:addr><fr:route>150-0076.xml</fr:route><fr:title>Stream of natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>How could we make the stream <fr:code>0, 1, 2, 3, 4, ...</fr:code> of all natural numbers? We might try:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val nats : int stream =
  Stream (fn () =&gt; (0,
  Stream (fn () =&gt; (1,
  Stream (fn () =&gt; (2, ...
  ))))))
</html:code></fr:pre><fr:p>However, we can never finish typing the <fr:code>...</fr:code>. Instead, we compute something more general: all of the natural numbers starting from <fr:code>n</fr:code>. Then, <fr:code>nats</fr:code> is a special case, choosing <fr:code>0</fr:code> for <fr:code>n</fr:code>.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* natsFrom : int -&gt; int stream
 * REQUIRES: true
 * ENSURES: natsFrom n ==&gt; s, where the elements of s are n, (n + 1), (n + 2), (n + 3), ...
 *)
fun natsFrom (n : int) : int stream =
  Stream (fn () =&gt; (n, natsFrom (n + 1)))

val nats : int stream = natsFrom 0
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1453</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0077</fr:addr><fr:route>150-0077.xml</fr:route><fr:title>Corecursion</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Definitions such as <fr:ref
addr="150-0074"
href="150-0074.xml"
taxon="Example"></fr:ref> do not go by recursion on an input; nothing needs to ever shrink. Instead, they go by <fr:em>corecursion</fr:em>, producing a finite amount of data but offering to produce more if desired.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1454</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-0073</fr:addr><fr:route>150-0073.xml</fr:route><fr:title>Stream</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Using a <fr:link
href="150-0072.xml"
type="local"
addr="150-0072">suspension</fr:link>, we can define a type of streams as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a stream = Stream of unit -&gt; 'a * 'a stream
</html:code></fr:pre><fr:p>Here, <fr:code>Stream</fr:code> takes the role of <fr:code>::</fr:code>, but storing a suspension of a first element and the remainder of the stream.</fr:p><fr:p>Note that in this formulation, <fr:em>every stream is infinite</fr:em>.</fr:p><fr:p>The following helper function computes the first element of a stream and its tail:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* expose : 'a stream -&gt; 'a * 'a stream *)
fun expose (Stream susp : 'a stream) : 'a * 'a stream = susp ()
</html:code></fr:pre><fr:p>We call the first element of a stream its head, and the remainder its tail.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun fst (x, y) = x
fun snd (x, y) = y

fun head (s : 'a stream) : 'a = fst (expose s)
fun tail (s : 'a stream) : 'a stream = snd (expose s)
</html:code></fr:pre></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1468</fr:anchor><fr:addr>150-00CG</fr:addr><fr:route>150-00CG.xml</fr:route><fr:title>Higher-order functions</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> functions are data, and recurring patterns justify abstraction.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1457</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006R</fr:addr><fr:route>150-006R.xml</fr:route><fr:title>Bind abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-006L.xml"
type="local"
addr="150-006L"><fr:code>bind</fr:code></fr:link>, which takes a function <fr:code>f : 'a -&gt; 'b list</fr:code> and a list <fr:code>'a list</fr:code> and applies the function on each <fr:code>'a</fr:code> to get a resulting flattened <fr:code>'b list</fr:code>.</fr:p><fr:p>This specification can be generalized beyond <fr:code>'a list</fr:code> to arbitrary types <fr:code>'a t</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* bind : ('a -&gt; 'b t) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES: ...
 *)
</html:code></fr:pre><fr:p>The ENSURES should contain some conditions similar to those given for the <fr:link
href="150-006D.xml"
type="local"
addr="150-006D">map abstraction</fr:link>, but we elide them in this class.</fr:p><fr:p>We can always implement the infix <fr:code>&gt;&gt;=</fr:code> using a <fr:code>bind</fr:code> implementation:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (x : 'a t) &gt;&gt;= (f : 'a -&gt; 'b t) : 'b t = bind f x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1458</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006L</fr:addr><fr:route>150-006L.xml</fr:route><fr:title>List bind</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The function <fr:code>bind</fr:code> takes in a function <fr:code>f : 'a -&gt; 'b list</fr:code> that produces as many <fr:code>'b</fr:code>s as it wishes; we accumulate all of them in a list.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* bind : ('a -&gt; 'b list) -&gt; 'a list -&gt; 'b list *)
fun bind f nil       = nil
  | bind f (x :: xs) = f x @ bind f xs
</html:code></fr:pre><fr:p>It generalizes <fr:link
href="150-005X.xml"
type="local"
addr="150-005X">list map</fr:link>, whose function input must always produce exactly one <fr:code>'b</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1459</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006H</fr:addr><fr:route>150-006H.xml</fr:route><fr:title>Fold abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-0063.xml"
type="local"
addr="150-0063"><fr:code>foldr</fr:code></fr:link>. Crucially, it sent <fr:code>[x1, x2, ..., xn]</fr:code>, i.e., <fr:blockquote><fr:code>op:: (x1, op:: (x2, ..., op:: (xn, nil)))</fr:code></fr:blockquote> to <fr:blockquote><fr:code>f (x1, f (x2, ..., f (xn, init)))</fr:code></fr:blockquote> by replacing <fr:code>op::</fr:code> with <fr:code>f</fr:code> and <fr:code>nil</fr:code> with <fr:code>init</fr:code>.</fr:p><fr:p>If we rewrite the list datatype as follows:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a list = Cons of 'a * 'a list | Nil
</html:code></fr:pre><fr:p>We might as well write <fr:code>foldr</fr:code> as:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldr : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b *)
fun foldr (cons : 'a * 'b -&gt; 'b) (nil : 'b) (l : 'a list) : 'b =
  case l of
    Cons (x, xs) =&gt; cons (x, foldr cons nil xs)
  | Nil          =&gt; nil
</html:code></fr:pre><fr:p>The type of each argument matches the type of the constructor, swapping <fr:code>'a list</fr:code> for <fr:code>'b</fr:code>. Here, <fr:code>cons</fr:code> is just a function (not a constructor!) to replace every <fr:code>Cons</fr:code> with, and <fr:code>nil</fr:code> is just a value to replace every <fr:code>Nil</fr:code> with.</fr:p><fr:p>The general recipe is as follows:</fr:p><fr:ol><fr:li>For each constructor, replace the name of the type with <fr:code>'b</fr:code>, including recursive uses.</fr:li>
  <fr:li>Take in each of these functions/values meant to replace the constructor as arguments.</fr:li>
  <fr:li>In the implementation, replace each constructor with its function, performing recursive calls on substructures if there are any.</fr:li></fr:ol><fr:p>For example:</fr:p><fr:ol><fr:li>We have <fr:code>Cons : 'a * 'a list -&gt; 'a list</fr:code> and <fr:code>Nil : 'a list</fr:code>, so we get <fr:code>cons : 'a * 'b -&gt; 'b</fr:code> and <fr:code>nil : 'b</fr:code>.</fr:li>
  <fr:li>We take in <fr:code>cons</fr:code> and <fr:code>nil</fr:code> as arguments.</fr:li>
  <fr:li>The implementation is as above.</fr:li></fr:ol><fr:p>This perspective justifies the <fr:link
href="150-0064.xml"
type="local"
addr="150-0064">universality of <fr:link
href="150-0063.xml"
type="local"
addr="150-0063">list <fr:code>foldr</fr:code></fr:link></fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1460</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006D</fr:addr><fr:route>150-006D.xml</fr:route><fr:title>Map abstraction</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We previously saw <fr:link
href="150-005X.xml"
type="local"
addr="150-005X"><fr:code>map</fr:code></fr:link>, which takes a function <fr:code>f : 'a -&gt; 'b</fr:code> and a list <fr:code>'a list</fr:code> and applies the function on each <fr:code>'a</fr:code> to get a resulting <fr:code>'b list</fr:code>.</fr:p><fr:p>This specification can be generalized beyond <fr:code>'a list</fr:code> to arbitrary types <fr:code>'a t</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a t -&gt; 'b t
 * REQUIRES: true
 * ENSURES:
 * - map id = id, ie map id s = s
 * - map (f o g) = map f o map g, ie map f (map g s) = map (f o g) s
 *)
</html:code></fr:pre><fr:p>In other words, the ENSURES guarantees that <fr:code>map</fr:code> is structure-preserving.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1461</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-006P</fr:addr><fr:route>150-006P.xml</fr:route><fr:title>Pipe function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following function, pronounced "pipe", is useful for building data pipelines:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">infix 4 |&gt;

(* op |&gt; : 'a * ('a -&gt; 'b) -&gt; 'b *)
fun x |&gt; f = f x
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1462</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0063</fr:addr><fr:route>150-0063.xml</fr:route><fr:title>List <fr:code>foldr</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* sum : int list -&gt; int
 * REQUIRES: true
 * ENSURES: sum [x1, ..., xn] = x1 + (x2 + (... + (xn + 0)))
 *)
fun sum nil       = 0
  | sum (x :: xs) = x + sum xs

(* concat : 'a list list -&gt; 'a list
 * REQUIRES: true
 * ENSURES: concat [x1, ..., xn] = x1 @ (x2 @ (... @ (xn @ nil)))
 *)
fun concat nil       = nil
  | concat (x :: xs) = x @ concat xs

(* commas : string list -&gt; string
 * REQUIRES: true
 * ENSURES: commas [x1, ..., xn] = (x1 ^ ", ") ^ ((x2 ^ ", ") ^ (... ^ ((xn ^ ", ") ^ ".")))
 *)
fun commas nil       = "."
  | commas (x :: xs) = (x ^ ", ") ^ commas xs

(* rebuild : 'a list -&gt; 'a list *)
fun rebuild nil       = nil
  | rebuild (x :: xs) = x :: rebuild xs

(* isort : int list -&gt; int list *)
fun isort nil       = nil
  | isort (x :: xs) = insert (x, isort xs)
</html:code></fr:pre><fr:p>All three share a common structure, combining <fr:code>x</fr:code> into the recursive call on <fr:code>xs</fr:code>. For a base case <fr:code>init : t2</fr:code> and a recursive case <fr:code>f : t1 * t2 -&gt; t2</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* combine : t1 list -&gt; t2
 * REQUIRES: true
 * ENSURES: combine [x1, ..., xn] = f (x1, f (x2, ... f (xn, init)))
 *)
fun combine nil       = init
  | combine (x :: xs) = f (x, combine xs)
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>foldr</fr:code>, that takes in such an initial value <fr:code>init</fr:code> and a combining function <fr:code>f</fr:code> and produces the corresponding <fr:code>combine</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* foldr : ('a * 'b -&gt; 'b) -&gt; 'b -&gt; 'a list -&gt; 'b
 * REQUIRES: true
 * ENSURES: foldr f init [x1, ..., xn] = f (x1, f (x2, ... f (xn, init)))
 *)
fun foldr f init nil       = init
  | foldr f init (x :: xs) = f (x, foldr f init xs)
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val sum = foldr (op +) 0
val concat = foldr (op @) nil
val commas = foldr (fn (x, y) =&gt; x ^ ", " ^ y) "."
val rebuild = foldr (op ::) nil
val isort = foldr insert nil
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1463</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005X</fr:addr><fr:route>150-005X.xml</fr:route><fr:title>List map</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Consider the following functions:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* incAll : int list -&gt; int list
 * REQUIRES: true
 * ENSURES: incAll [x1, ..., xn] = [x1 + 1, ..., xn + 1]
 *)
fun incAll nil       = nil
  | incAll (x :: xs) = (x + 1) :: incAll xs

(* stringAll : int list -&gt; string list
 * REQUIRES: true
 * ENSURES: stringAll [x1, ..., xn] = [Int.toString x1, ..., Int.toString xn]
 *)
fun stringAll nil       = nil
  | stringAll (x :: xs) = Int.toString x :: stringAll xs

(* bool list -&gt; bool list
 * REQUIRES: true
 * ENSURES: flipAll [x1, ..., xn] = [not x1, ..., not xn]
 *)
fun flipAll nil       = nil
  | flipAll (x :: xs) = not x :: flipAll xs
</html:code></fr:pre><fr:p>All share a common structure, applying a function to each element of the input list. For a function <fr:code>f : t1 -&gt; t2</fr:code>, we have:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* fAll : t1 list -&gt; t2 list
 * REQUIRES: true
 * ENSURES: fAll [x1, ..., xn] = [f x1, ..., f xn]
 *)
fun fAll nil       = nil
  | fAll (x :: xs) = f x :: fAll xs
</html:code></fr:pre><fr:p>So, we can define a higher-order function, <fr:code>map</fr:code>, that takes in such a function <fr:code>f</fr:code> and produces the corresponding <fr:code>fAll</fr:code> function:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* map : ('a -&gt; 'b) -&gt; 'a list -&gt; 'b list
 * REQUIRES: true
 * ENSURES: map f [x1, ..., xn] = [f x1, ..., f xn]
 *)
fun map f nil       = nil
  | map f (x :: xs) = f x :: map f xs
</html:code></fr:pre><fr:p>Then, we can define the other functions very simply:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val incAll = map (fn x =&gt; x + 1)
val stringAll = map Int.toString
val flipAll = map not
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1464</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0067</fr:addr><fr:route>150-0067.xml</fr:route><fr:title>Staging</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:link
href="150-0068.xml"
type="local"
addr="150-0068">Curried functions</fr:link> can perform some intermediate computation before receiving all of their arguments.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1465</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005Z</fr:addr><fr:route>150-005Z.xml</fr:route><fr:title>Function composition</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To compose two functions <fr:code>f : 'a -&gt; 'b</fr:code> and <fr:code>g : 'b -&gt; 'c</fr:code>, we can define <fr:code>(g o f) : 'a -&gt; 'c</fr:code>:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun (op o) (g : 'b -&gt; 'c, f : 'a -&gt; 'b) : 'a -&gt; 'c = fn (x : 'a) =&gt; g (f x)
</html:code></fr:pre><fr:p>We can equivalently define composition in the following ways:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun g o f = fn x =&gt; g (f x)
fun (g o f) x = g (f x)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1466</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0068</fr:addr><fr:route>150-0068.xml</fr:route><fr:title>Currying</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We say that a function is <fr:em>curried</fr:em>, named for mathematician <fr:link
href="https://en.wikipedia.org/wiki/Haskell_Curry"
type="external">Haskell Curry</fr:link>, when it takes in multiple arguments one at a time, producing a function accepting the rest of the arguments.</fr:p><fr:p>For example, the type <fr:code>t1 -&gt; t2 -&gt; t3</fr:code> is curried, but the type <fr:code>t1 * t2 -&gt; t3</fr:code> is not (sometimes called "uncurried").</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1467</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-005P</fr:addr><fr:route>150-005P.xml</fr:route><fr:title>Higher-order function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:em>higher-order function</fr:em> is a function that takes a function as input or produces a function as output.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1480</fr:anchor><fr:addr>150-00CH</fr:addr><fr:route>150-00CH.xml</fr:route><fr:title>Datatypes</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> types guide structure and describe the shape of data.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1470</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005I</fr:addr><fr:route>150-005I.xml</fr:route><fr:title>Comparison function</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In the implementation of the <fr:link
href="150-004J.xml"
type="local"
addr="150-004J">insert auxiliary function</fr:link>, we used <fr:code>Int.compare : int * int -&gt; order</fr:code>. To sort a list of <fr:code>'a</fr:code>s, we need a function of type <fr:code>'a * 'a -&gt; order</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1471</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-005G</fr:addr><fr:route>150-005G.xml</fr:route><fr:title>Unit type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The type <fr:code>unit</fr:code> has a single value, <fr:code>() : unit</fr:code>, the empty tuple.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1472</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005E</fr:addr><fr:route>150-005E.xml</fr:route><fr:title>Polymorphic trees</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Generalizing <fr:link
href="150-002N.xml"
type="local"
addr="150-002N">binary tree with <fr:code>int</fr:code>s at the nodes</fr:link>, we may have a tree storing any element type we wish:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a tree
  = Empty
  | Node of 'a tree * 'a * 'a tree
</html:code></fr:pre><fr:p>To recover the trees of integers, we use <fr:code>int tree</fr:code>. Now, though, we may have <fr:code>string tree</fr:code>, <fr:code>int option tree</fr:code>, <fr:code>int list tree</fr:code>, <fr:code>int tree tree</fr:code>, and more!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1473</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-005D</fr:addr><fr:route>150-005D.xml</fr:route><fr:title>Built-in polymorphic datatypes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Generalizing <fr:link
href="150-002I.xml"
type="local"
addr="150-002I">existing types as <fr:code>datatype</fr:code> declarations</fr:link>, we may include parameters:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype 'a option
  = NONE
  | SOME of 'a

datatype 'a list
  = nil
  | :: of 'a * 'a list
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1474</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0057</fr:addr><fr:route>150-0057.xml</fr:route><fr:title>Most general type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The <fr:em>most general type</fr:em> of an expression <fr:code>e</fr:code> is the type <fr:code>t</fr:code> such that all other types <fr:code>t'</fr:code> that could be assigned to <fr:code>e</fr:code> can be achieved by plugging in for type variables in <fr:code>t</fr:code>.</fr:p><fr:p>We say that these other types <fr:code>t'</fr:code> are <fr:em>instances of</fr:em> type <fr:code>t</fr:code>.</fr:p><fr:p>When we say that "<fr:code>e</fr:code> has type <fr:code>t</fr:code>", we implicitly mean that <fr:code>e</fr:code> has most general type <fr:code>t</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1475</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004V</fr:addr><fr:route>150-004V.xml</fr:route><fr:title>Contradiction in type inference</fr:title></fr:frontmatter><fr:mainmatter><fr:p>If a variable is used in such a way that it has two incompatible types, a type error will be produced.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1476</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-004E</fr:addr><fr:route>150-004E.xml</fr:route><fr:title><fr:code>order</fr:code> datatype</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following datatype is built into the standard library of Standard ML:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype order = LESS | EQUAL | GREATER
</html:code></fr:pre><fr:p>As the constructor names indicate, these constructors indicate the result of a comparison of elements in a <fr:link
href="https://en.wikipedia.org/wiki/Law_of_trichotomy"
type="external">trichotomous relation</fr:link>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1477</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0031</fr:addr><fr:route>150-0031.xml</fr:route><fr:title>Cost analysis</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:em>Goal:</fr:em> understand the cost of programs. Some choices:</fr:p><fr:ul><fr:li>Time each execution. However, this is machine-dependent.</fr:li>
  <fr:li>Count a given metric (recursive calls; additions; evaluation steps; etc.). This is abstract enough to be proved, and it corresponds to real time.</fr:li></fr:ul><fr:p>First, we choose a <fr:em>cost metric</fr:em> and <fr:em>size metrics</fr:em> for inputs. Then, we:</fr:p><fr:ol><fr:li>Write a recurrence following the structure of the code, computing cost from input sizes.</fr:li>
  <fr:li>Solve for a closed form.</fr:li>
  <fr:li>Give a simple asymptotic (big-<fr:tex>\mathcal {O}</fr:tex>) solution.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1478</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002T</fr:addr><fr:route>150-002T.xml</fr:route><fr:title>Structural induction on <fr:link
href="150-002N.xml"
type="local"
addr="150-002N"><fr:code>tree</fr:code></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all tree values <fr:code>t : tree</fr:code>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:code>Empty</fr:code>.</fr:li>
  <fr:li>Inductive Case: Prove that for all <fr:code>x : int</fr:code> and <fr:code>l, r : tree</fr:code>, if the property holds on both <fr:code>l</fr:code> and <fr:code>r</fr:code> (inductive hypotheses), then the property holds on <fr:code>Node (l, x, r)</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1479</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-002N</fr:addr><fr:route>150-002N.xml</fr:route><fr:title>Binary tree with <fr:code>int</fr:code>s at the nodes</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We define the following <fr:link
href="150-002H.xml"
type="local"
addr="150-002H">datatype declaration</fr:link> to represent binary trees:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">datatype tree
  = Empty
  | Node of tree * int * tree
</html:code></fr:pre><fr:p>Note that <fr:code>tree</fr:code> is used recursively.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1486</fr:anchor><fr:addr>150-00CI</fr:addr><fr:route>150-00CI.xml</fr:route><fr:title>Induction</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> big problems can be broken down into smaller ones.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1482</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0027</fr:addr><fr:route>150-0027.xml</fr:route><fr:title>Structural induction on <fr:code>int list</fr:code></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all list values <fr:code>l : int list</fr:code>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:code>nil</fr:code>.</fr:li>
  <fr:li>Inductive Case: Prove that for all <fr:code>x : int</fr:code> and <fr:code>xs : int list</fr:code>, if the property holds on <fr:code>xs</fr:code>, then the property holds on <fr:code>x :: xs</fr:code>.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1483</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0022</fr:addr><fr:route>150-0022.xml</fr:route><fr:title>Lists</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all types <fr:code>t</fr:code>, the type <fr:code>t list</fr:code> represents ordered lists of values of type <fr:code>t</fr:code>.</fr:p><fr:p>The values of type <fr:code>t list</fr:code> are:</fr:p><fr:ol><fr:li><fr:code>nil</fr:code>, the empty list</fr:li>
  <fr:li><fr:code>v1 :: v2</fr:code> (pronounced "cons"), where <fr:code>v1 : t</fr:code> is an element and <fr:code>v2 : t list</fr:code> is the remainder of the list</fr:li></fr:ol><fr:p>Syntactic sugar <fr:code>[v1, v2, ..., vn]</fr:code> is equivalent to <fr:code>v1 :: v2 :: ... :: vn</fr:code>, i.e. <fr:code>v1 :: (v2 :: (... :: (vn :: nil)))</fr:code>.</fr:p><fr:p>There are corresponding expressions that evaluate left-to-right.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1484</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-001V</fr:addr><fr:route>150-001V.xml</fr:route><fr:title>Proof structure mirrors program structure</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The structure of a <fr:em>proof</fr:em> should mirror the structure of the <fr:em>program</fr:em>.</fr:p><fr:ol><fr:li>If the program uses recursion on a natural number <fr:code>n</fr:code>, the proof should use induction on <fr:code>n</fr:code>.</fr:li>
  <fr:li>If the program uses recursion with cases <fr:code>0</fr:code>, <fr:code>1</fr:code>, and <fr:code>n</fr:code>, the proof should use induction with base cases for <fr:code>0</fr:code> and <fr:code>1</fr:code> and an inductive case for <fr:code>n</fr:code>.</fr:li>
  <fr:li>If the program cases on <fr:code>b : bool</fr:code>, the proof should case in the same way.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1485</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001T</fr:addr><fr:route>150-001T.xml</fr:route><fr:title>Simple induction on natural numbers</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To prove that a property holds on all natural numbers <fr:tex>n \in  \{0, 1, 2, 3, \cdots \}</fr:tex>:</fr:p><fr:ol><fr:li>Base Case: Prove that the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>Inductive Case: Prove that if the property holds on <fr:tex>n</fr:tex>, then the property holds on <fr:tex>n + 1</fr:tex>.</fr:li></fr:ol><fr:p>Then:</fr:p><fr:ul><fr:li>The property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>1 = 0 + 1</fr:tex>, since the property holds on <fr:tex>0</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>2 = 1 + 1</fr:tex>, since the property holds on <fr:tex>1</fr:tex>.</fr:li>
  <fr:li>The property holds on <fr:tex>3 = 2 + 1</fr:tex>, since the property holds on <fr:tex>2</fr:tex>.</fr:li>
  <fr:li>...and so on.</fr:li></fr:ul></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1504</fr:anchor><fr:addr>150-00CJ</fr:addr><fr:route>150-00CJ.xml</fr:route><fr:title>Basics</fr:title></fr:frontmatter><fr:mainmatter><fr:p><html:mark
xmlns:html="http://www.w3.org/1999/xhtml">Lesson:</html:mark> choose a foundation that scales, and carefully distinguish ideas.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1488</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001J</fr:addr><fr:route>150-001J.xml</fr:route><fr:title><fr:code>case</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">case e of
  pat1 =&gt; e1
| pat2 =&gt; e2
  ...
| patn =&gt; en
</html:code></fr:pre><fr:p>To evaluate a <fr:code>case</fr:code> expression:</fr:p><fr:ol><fr:li>Evaluate <fr:code>e</fr:code> to a value.</fr:li>
  <fr:li>Then, evaluate the first branch matching the value.</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1489</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001E</fr:addr><fr:route>150-001E.xml</fr:route><fr:title>Pattern inputs in <fr:code>fun</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun f &lt;pattern&gt; : t2 = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1490</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001A</fr:addr><fr:route>150-001A.xml</fr:route><fr:title>Tuple pattern matching</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val name_and_age : string * int = ("Polly", 5)

val (name, age) : string * int = name_and_age
(* OR: *)
val (name : string, age : int) = name_and_age
(* OR: *)
val (name, age) = name_and_age

val age' : int =
  let
    val (_, age) = name_and_age
  in
    age + 1
  end

val ((a : string, b : int), (c : string, d : int)) =
  (name_and_age, name_and_age)
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1491</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-001C</fr:addr><fr:route>150-001C.xml</fr:route><fr:title>Wildcard pattern</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun onefifty (_ : int) : int = 150
</html:code></fr:pre><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">λ&gt; fun onefifty (x : int) : int = 150;
stdIn:2.5-2.35 Warning: variable x is defined but not used
val onefifty = fn : int -&gt; int
λ&gt; fun onefifty (_ : int) : int = 150;
val onefifty = fn : int -&gt; int
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1492</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0013</fr:addr><fr:route>150-0013.xml</fr:route><fr:title>Function specifications</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">(* f : t1 -&gt; t2
 * REQUIRES: ...some assumptions about x...
 * ENSURES: ...some guarantees about (f x)...
 *)
fun f (x : t1) : t2 = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1493</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000T</fr:addr><fr:route>150-000T.xml</fr:route><fr:title>Extensional equivalence at function types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Suppose <fr:code>f</fr:code> and <fr:code>f'</fr:code> are both of type <fr:code>t1 -&gt; t2</fr:code>. Then, <fr:tex>\texttt {f} \cong  \texttt {f'}</fr:tex> when for all values <fr:code>x</fr:code> and <fr:code>x'</fr:code> of type <fr:code>t1</fr:code>, <fr:tex>\texttt {x} \cong  \texttt {x'}</fr:tex> implies <fr:tex>\texttt {f x} \cong  \texttt {f' x'}</fr:tex>.</fr:p><fr:p>When <fr:code>t1</fr:code> is a <fr:link
href="150-000Q.xml"
type="local"
addr="150-000Q">base type</fr:link>, this is equivalent to: for all values <fr:code>x : t1</fr:code>, <fr:tex>\texttt {f x} \cong  \texttt {f' x}</fr:tex>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1494</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-001L</fr:addr><fr:route>150-001L.xml</fr:route><fr:title>Functions are values</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Functions <fr:em>are</fr:em> values: they do not evaluate further.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1495</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000L</fr:addr><fr:route>150-000L.xml</fr:route><fr:title>Function types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In math, we talk about functions <fr:tex
display="block">f : X \to  Y</fr:tex> between sets <fr:tex>X</fr:tex> and <fr:tex>Y</fr:tex>. In SML, we do the same, but where <fr:tex>X</fr:tex> and <fr:tex>Y</fr:tex> are types.</fr:p><fr:p>If <fr:code>t1</fr:code> and <fr:code>t2</fr:code> are types, then <fr:code>t1 -&gt; t2</fr:code> is the type of functions that take a value of type <fr:code>t1</fr:code> as input and produce a value of type <fr:code>t2</fr:code> as an output.</fr:p>
  <html:table
xmlns:html="http://www.w3.org/1999/xhtml">
  

  
    
  <html:tr>
  <html:td><fr:strong>Type</fr:strong></html:td>

  <html:td><fr:strong>Values</fr:strong></html:td>
</html:tr>

  
  
    
  <html:tr>
  <html:td><fr:code>t1 -&gt; t2</fr:code></html:td>

  <html:td><fr:code>fn (x : t1) =&gt; e</fr:code></html:td>
</html:tr>

  
</html:table>
<fr:p>If assuming that <fr:code>x : t1</fr:code> makes <fr:code>e : t2</fr:code>, then <fr:code>(fn (x : t1) =&gt; e) : t1 -&gt; t2</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1496</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000P</fr:addr><fr:route>150-000P.xml</fr:route><fr:title><fr:code>local</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">local
  val b : int = 15
  val c : int = b + 150
in
  val a : int = b * c + 1
end

(* ERROR: b not in scope *)
val d : int = a + b
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1497</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000O</fr:addr><fr:route>150-000O.xml</fr:route><fr:title><fr:code>let</fr:code> expressions</fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val a : int =
  let
    val b : int = 15
    val c : int = b + 150
  in
    b * c
  end + 1

(* ERROR: b not in scope *)
val d : int = a + b
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1498</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-000M</fr:addr><fr:route>150-000M.xml</fr:route><fr:title><fr:code>val</fr:code> declarations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A <fr:code>val</fr:code> declaration gives a variable name to the result of an expression evaluation.</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">val x : t = e
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1499</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-000H</fr:addr><fr:route>150-000H.xml</fr:route><fr:title>Example pairs</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:code>(3 + 4, true) : int * bool</fr:code></fr:li>
  <fr:li><fr:code>(1.0, ~6.28) : real * real</fr:code></fr:li>
  <fr:li><fr:code>(1, 50, false, "hi") : int * int * bool * string</fr:code></fr:li>
  <fr:li><fr:code>(1, (50, false), "hi") : int * (int * bool) * string</fr:code></fr:li></fr:ul><fr:p>Notice in the last example that parentheses matter!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1500</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-000Q</fr:addr><fr:route>150-000Q.xml</fr:route><fr:title>Extensional equivalence at base types</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Two expressions <fr:tex>e</fr:tex> and <fr:tex>e'</fr:tex> (that evaluate to values) are <fr:em>extensionally equivalent</fr:em>, written <fr:tex>e \cong  e'</fr:tex>, when they evaluate to the same value.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1501</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0004</fr:addr><fr:route>150-0004.xml</fr:route><fr:title>Type</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A type is a <fr:em>prediction</fr:em> about the kind of value an expression will evaluate to. When an expression <fr:tex>e</fr:tex> has type <fr:tex>t</fr:tex>, we write <fr:tex>e : t</fr:tex>.</fr:p><fr:p>An expression is <fr:em>well-typed</fr:em> if it has a type and <fr:em>ill-typed</fr:em> otherwise.</fr:p><fr:p>Type-checking happens <fr:em>prior</fr:em> to evaluation: only well-typed programs are evaluated.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1502</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0005</fr:addr><fr:route>150-0005.xml</fr:route><fr:title>Expression</fr:title></fr:frontmatter><fr:mainmatter><fr:p>An expression <fr:tex>e</fr:tex> is a program that can be evaluated.</fr:p><fr:ul><fr:li>Every value is also an expression.</fr:li>
  <fr:li>Until the end of the course, we make the blanket assumption that all expressions <fr:tex>e</fr:tex> evaluate to some value <fr:tex>v</fr:tex>.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1503</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0006</fr:addr><fr:route>150-0006.xml</fr:route><fr:title>Value</fr:title></fr:frontmatter><fr:mainmatter><fr:p>A value <fr:tex>v</fr:tex> is a <fr:em>final answer</fr:em> that cannot be simplified further.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1510</fr:anchor><fr:addr>150-00CK</fr:addr><fr:route>150-00CK.xml</fr:route><fr:title>Closing thoughts</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1505</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000V</fr:addr><fr:route>150-000V.xml</fr:route><fr:title>Principles of functional programming</fr:title></fr:frontmatter><fr:mainmatter><fr:ul><fr:li><fr:strong>Simplicity:</fr:strong> pure, functional code is easy to reason about, test, and parallelize.</fr:li>
  <fr:li><fr:strong>Compositionality:</fr:strong> build bigger programs out of smaller ones, taking advantage of patterns.</fr:li>
  <fr:li><fr:strong>Abstraction:</fr:strong> use types/specification to guide program development.</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1506</fr:anchor><fr:taxon>Principle</fr:taxon><fr:addr>150-000W</fr:addr><fr:route>150-000W.xml</fr:route><fr:title>Programming as a linguistic process</fr:title></fr:frontmatter><fr:mainmatter><fr:p><fr:strong>Imperative programming</fr:strong> is telling a computer <fr:em>how</fr:em> to compute a result.<fr:tex
display="block">   \begin {aligned}     x &amp;\leftarrow  2; \\     y &amp;\leftarrow  x + x   \end {aligned} </fr:tex></fr:p><fr:p><fr:strong>Functional programming</fr:strong> is explaining what you want to compute. <fr:tex
display="block">2 + 2</fr:tex></fr:p><fr:p>Functional programming is applicable in all "high-level" programming languages.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1509</fr:anchor><fr:taxon>Perspective</fr:taxon><fr:addr>150-00CL</fr:addr><fr:route>150-00CL.xml</fr:route><fr:title>On code</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Code is <html:mark
xmlns:html="http://www.w3.org/1999/xhtml">math</html:mark>: it transforms data and is subject to precise analysis.</fr:p><fr:p>Code is <html:mark
xmlns:html="http://www.w3.org/1999/xhtml">art</html:mark>: it can communicate ideas and help you think beautiful thoughts.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree>
  <html:hr
xmlns:html="http://www.w3.org/1999/xhtml"></html:hr>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1823</fr:anchor><fr:addr>150-bonus</fr:addr><fr:route>150-bonus.xml</fr:route><fr:title>Bonus Lectures</fr:title><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter><fr:p>This content is entirely optional and should be ignored when completing assignments or exams.</fr:p><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="false"
root="false"><fr:frontmatter><fr:anchor>1644</fr:anchor><fr:taxon>Lecture</fr:taxon><fr:addr>150-bonus01</fr:addr><fr:route>150-bonus01.xml</fr:route><fr:title>Cost analysis and phases</fr:title><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>31</fr:day></fr:date><fr:authors><fr:author><fr:link
href="hgrodin.xml"
type="local"
addr="hgrodin">Harrison Grodin</fr:link></fr:author></fr:authors></fr:frontmatter><fr:mainmatter>
  <html:link
xmlns:html="http://www.w3.org/1999/xhtml"
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"></html:link>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sml.min.js"></html:script>
  <html:script
xmlns:html="http://www.w3.org/1999/xhtml">hljs.highlightAll();</html:script>
<fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1626</fr:anchor><fr:addr>150-003Q</fr:addr><fr:route>150-003Q.xml</fr:route><fr:title>Cost annotations</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1612</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-003T</fr:addr><fr:route>150-003T.xml</fr:route><fr:title>Cost annotations</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We extend Standard ML with a new primitive for cost tracking.</fr:p><fr:p>If <fr:code>e : t</fr:code>, then <fr:code>$c(e) : t</fr:code>, as well, when <fr:code>c</fr:code> is a natural number. <fr:code>$c(e)</fr:code> means "increase the cost of <fr:code>e</fr:code> by <fr:code>c</fr:code> units".</fr:p><fr:p>The cost primitive has the following properties, allowing trivial zero cost to be deleted and multiple cost to be consolidated:</fr:p><fr:tex
display="block">   \begin {aligned}     {\hspace {-2pt}\text {\textdollar }{0}}(e) &amp;= e \\     {\hspace {-2pt}\text {\textdollar }{c_1}}({\hspace {-2pt}\text {\textdollar }{c_2}}(e)) &amp;= {\hspace {-2pt}\text {\textdollar }{(c_1 + c_2)}}(e)   \end {aligned} </fr:tex><fr:p>Moreover, cost can always be pulled out to the front:</fr:p><fr:tex
display="block">   \begin {aligned}     e~({\hspace {-2pt}\text {\textdollar }{c}}(e_1)) &amp;= {\hspace {-2pt}\text {\textdollar }{c}}(e~e_1) \\     ({\hspace {-2pt}\text {\textdollar }{c_1}}(e_1), {\hspace {-2pt}\text {\textdollar }{c_2}}(e_2)) &amp;= {\hspace {-2pt}\text {\textdollar }{(c_1 + c_2)}}((e_1, e_2))   \end {aligned} </fr:tex></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1614</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003W</fr:addr><fr:route>150-003W.xml</fr:route><fr:title>Cost-annotated <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun x ++ y = $1(x + y)

fun sum Empty = 0
  | sum (Node (l, x, r)) = sum l ++ x ++ sum r
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1615</fr:anchor><fr:taxon>Concern</fr:taxon><fr:addr>150-003X</fr:addr><fr:route>150-003X.xml</fr:route><fr:title>Missing information for general recurrence for <fr:link
href="150-003W.xml"
type="local"
addr="150-003W">cost-annotated <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>To write a recurrence for <fr:link
href="150-003W.xml"
type="local"
addr="150-003W">cost-annotated <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link></fr:link> <fr:em>without any tree shape assumptions</fr:em> (like spine or balanced), sometimes it is said that:</fr:p><fr:tex
display="block">   \begin {aligned}     W(0) &amp;= 0 \\     W(n) &amp;= W(n_1) + W(n_2) + 2   \end {aligned} </fr:tex><fr:p>where <fr:tex>n_1</fr:tex> and <fr:tex>n_2</fr:tex> are the sizes of the two subtrees. But, this does not define a function: the only input to <fr:tex>W</fr:tex> is the tree size <fr:tex>n</fr:tex>, which does not include information about how the nodes are split between the subtrees!</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1617</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-003V</fr:addr><fr:route>150-003V.xml</fr:route><fr:title>Cost-annotated <fr:link
href="150-0029.xml"
type="local"
addr="150-0029">slow list reverse</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun revSlow nil = nil
  | revSlow (x :: xs) = $1(revSlow xs) @ [x]
</html:code></fr:pre></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1618</fr:anchor><fr:taxon>Concern</fr:taxon><fr:addr>150-003U</fr:addr><fr:route>150-003U.xml</fr:route><fr:title>Use of lemma to write recurrence for <fr:link
href="150-003V.xml"
type="local"
addr="150-003V">cost-annotated <fr:link
href="150-0029.xml"
type="local"
addr="150-0029">slow list reverse</fr:link></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>The recurrence is:</fr:p><fr:tex
display="block">   \begin {aligned}     W(0) &amp;= 0 \\     W(n) &amp;= W(n - 1) + W_\texttt {@}(n - 1, 1) + 1   \end {aligned} </fr:tex><fr:p>To define this recurrence, we need the fact that <fr:tex
display="block">n - 1 = \texttt {length xs} = \texttt {length (revSlow xs)},</fr:tex> which is a separate lemma. How come we need a lemma to state the recurrence in the first place?</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1619</fr:anchor><fr:taxon>Innovation</fr:taxon><fr:addr>150-003Y</fr:addr><fr:route>150-003Y.xml</fr:route><fr:title>A program is its own cost recurrence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Rather than take a program like <fr:code>revSlow</fr:code> and extract a recurrence <fr:tex>W_\texttt {revSlow}</fr:tex>, we treat the cost-annotated <fr:code>revSlow</fr:code> as a "2-in-1" solution, expressing both the program data and its cost simultaneously.</fr:p><fr:ol><fr:li>
    By taking in the full data structure rather than a number, we address <fr:ref
addr="150-003X"
href="150-003X.xml"
taxon="Concern"></fr:ref>: now, we have access to the shape of the input, rather than only the size.
  </fr:li>
  <fr:li>
    By producing the full data as output rather than just the cost, we address <fr:ref
addr="150-003U"
href="150-003U.xml"
taxon="Concern"></fr:ref>: now, we can pass the recursive result as an input to another "recurrence" without proving anything about its size relative to the inputs.
  </fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1620</fr:anchor><fr:taxon>Concept</fr:taxon><fr:addr>150-0040</fr:addr><fr:route>150-0040.xml</fr:route><fr:title>Solving generalized recurrences</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To solve a program-as-recurrence <fr:code>f</fr:code>, we prove that <fr:tex>\texttt {f x} = {\hspace {-2pt}\text {\textdollar }{c}}(\texttt {F x})</fr:tex>, where cost <fr:code>c</fr:code> is in terms of <fr:code>x</fr:code> and <fr:code>F</fr:code> is a (zero-cost) specification-level implementation of <fr:code>f</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1622</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-0043</fr:addr><fr:route>150-0043.xml</fr:route><fr:title>Cost of <fr:link
href="150-003W.xml"
type="local"
addr="150-003W">cost-annotated <fr:link
href="150-003F.xml"
type="local"
addr="150-003F">tree sum</fr:link></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>t : tree</fr:code>, we have <fr:tex
display="block">\texttt {sum t} = {\hspace {-2pt}\text {\textdollar }{(\texttt {2 * size t})}}(\texttt {SUM t}).</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1621</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#195</fr:addr><fr:route>unstable-195.xml</fr:route><fr:parent>150-0043</fr:parent></fr:frontmatter><fr:mainmatter>
  By structural induction on <fr:code>t</fr:code>.
  <fr:ol><fr:li>
      Case <fr:code>Empty</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {sum Empty} \\           &amp;= \texttt {0} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{0}}(0) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {2 * size Empty})}}(\texttt {SUM Empty})         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:code>Node (l, x, r)</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {sum (Node (l, x, r))} \\           &amp;= \texttt {sum l ++ x ++ sum r} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{2}}(\texttt {sum l + x + sum r}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{2}}({\hspace {-2pt}\text {\textdollar }{(\texttt {2 * size l})}}(\texttt {SUM l})\texttt { + x + } {\hspace {-2pt}\text {\textdollar }{(\texttt {2 * size r})}}(\texttt {SUM r})) &amp;&amp;\text {(IHs)} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {2 + 2 * size l + 2 * size r})}}(\texttt {SUM l + x + SUM r}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {2 * size (Node (l, x, r))})}}(\texttt {SUM (Node (l, x, r))})         \end {aligned}       </fr:tex></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1623</fr:anchor><fr:taxon>Lemma</fr:taxon><fr:addr>150-0041</fr:addr><fr:route>150-0041.xml</fr:route><fr:title>Cost of append</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>l1, l2 : int list</fr:code>, we have <fr:tex
display="block">\texttt {l1 @ l2} = {\hspace {-2pt}\text {\textdollar }{(\texttt {length l1})}}(\texttt {APP (l1, l2)}).</fr:tex></fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1625</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-0042</fr:addr><fr:route>150-0042.xml</fr:route><fr:title>Cost of <fr:link
href="150-003V.xml"
type="local"
addr="150-003V">cost-annotated <fr:link
href="150-0029.xml"
type="local"
addr="150-0029">slow list reverse</fr:link></fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>l : int list</fr:code>, we have <fr:tex
display="block">\texttt {revSlow l} = {\hspace {-2pt}\text {\textdollar }{(\texttt {(length l + 1) * (length l)} / 2)}}(\texttt {REV l}).</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1624</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#196</fr:addr><fr:route>unstable-196.xml</fr:route><fr:parent>150-0042</fr:parent></fr:frontmatter><fr:mainmatter>
  By structural induction on <fr:code>l</fr:code>.
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revSlow nil} \\           &amp;= \texttt {nil} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{0}}(\texttt {nil}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {1 * 0} / 2)}}(\texttt {REV nil})         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:
      <fr:p>Let <fr:tex>\texttt {n} = \texttt {length xs}</fr:tex>.</fr:p>
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revSlow (x :: xs)} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{1}}(\texttt {revSlow xs})\texttt { @ [x]} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{1}}({\hspace {-2pt}\text {\textdollar }{((n+1)n/2)}}(\texttt {REV xs}))\texttt { @ [x]} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + (n+1)n/2)}}(\texttt {REV xs @ [x]}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + (n+1)n/2)}}({\hspace {-2pt}\text {\textdollar }{(\texttt {length (REV xs)})}}(\texttt {APP (REV xs, [x])})) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + (n+1)n/2)}}({\hspace {-2pt}\text {\textdollar }{(\texttt {length (REV xs)})}}(\texttt {REV (x :: xs)})) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + (n+1)n/2)}}({\hspace {-2pt}\text {\textdollar }{(\texttt {length xs})}}(\texttt {REV (x :: xs)})) &amp;&amp;\text {(lemma)} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + (n+1)n/2 + n)}}(\texttt {REV (x :: xs)})         \end {aligned}       </fr:tex>
      As desired, this is <fr:tex
display="block">{\hspace {-2pt}\text {\textdollar }{(\texttt {(length (x :: xs) + 1) * (length (x :: xs))} / 2)}}(\texttt {REV (x :: xs)}).</fr:tex>
      Here, we use <fr:ref
addr="150-0041"
href="150-0041.xml"
taxon="Lemma"></fr:ref> while solving to turn <fr:code>length (REV xs)</fr:code> into <fr:code>length xs</fr:code>.
    </fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1636</fr:anchor><fr:addr>150-003R</fr:addr><fr:route>150-003R.xml</fr:route><fr:title>Program inequality</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1628</fr:anchor><fr:taxon>Example</fr:taxon><fr:addr>150-0044</fr:addr><fr:route>150-0044.xml</fr:route><fr:title>Cost-annotated zero chomp</fr:title></fr:frontmatter><fr:mainmatter><fr:p>The following function removes leading zeros from a list:</fr:p><fr:pre><html:code
xmlns:html="http://www.w3.org/1999/xhtml"
class="hljs language-sml">fun chomp nil = nil
  | chomp (0 :: xs) = $1(chomp xs)
  | chomp (x :: xs) = x :: xs
</html:code></fr:pre><fr:p>(Note that using traditional recurrences, we again run into <fr:ref
addr="150-003X"
href="150-003X.xml"
taxon="Concern"></fr:ref>, since the cost depends on the value of the first element of the list.)</fr:p><fr:p>The cost of <fr:code>chomp l</fr:code> is at most <fr:code>length l</fr:code>; however, if the zeros end before we reach <fr:code>nil</fr:code>, the cost will be less than <fr:code>length l</fr:code>.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1629</fr:anchor><fr:taxon>Innovation</fr:taxon><fr:addr>150-0045</fr:addr><fr:route>150-0045.xml</fr:route><fr:title>Program inequality</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We add a new notion, <fr:tex>e \le  e'</fr:tex>, which means that <fr:tex>e</fr:tex> and <fr:tex>e'</fr:tex> behave the same way, but <fr:tex>e</fr:tex> may incur less cost.</fr:p><fr:p>Program inequality satisfies the following properties:</fr:p><fr:ul><fr:li>
    Inequality is a preorder:
    <fr:ul><fr:li>For all <fr:tex>e</fr:tex>, we have <fr:tex>e \le  e'</fr:tex>.</fr:li>
      <fr:li>For all <fr:tex>e, e', e''</fr:tex>, if <fr:tex>e \le  e'</fr:tex> and <fr:tex>e' \le  e''</fr:tex>, then <fr:tex>e \le  e''</fr:tex>.</fr:li></fr:ul></fr:li>
  <fr:li>If <fr:tex>c \le _\mathbb {N} c'</fr:tex>, then <fr:tex>{\hspace {-2pt}\text {\textdollar }{c}}(e) \le  {\hspace {-2pt}\text {\textdollar }{c}}(e')</fr:tex>.</fr:li>
  <fr:li>For functions <fr:tex>f</fr:tex> and <fr:tex>f'</fr:tex>, to show <fr:tex>f \le  f'</fr:tex>, we must show that "for all <fr:tex>x</fr:tex>, we have <fr:tex>f~x \le  f'~x</fr:tex>".</fr:li></fr:ul></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1631</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-0046</fr:addr><fr:route>150-0046.xml</fr:route><fr:title>Cost of <fr:link
href="150-0044.xml"
type="local"
addr="150-0044">cost-annotated zero chomp</fr:link></fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>l : int list</fr:code>, we have <fr:tex
display="block">\texttt {chomp l} \le  {\hspace {-2pt}\text {\textdollar }{(\texttt {length l})}}(\texttt {CHOMP l}).</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1630</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#194</fr:addr><fr:route>unstable-194.xml</fr:route><fr:parent>150-0046</fr:parent></fr:frontmatter><fr:mainmatter>
  By structural induction on <fr:code>l</fr:code>.
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {chomp nil} \\           &amp;= \texttt {nil} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{0}}(\texttt {nil}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {length nil})}}(\texttt {CHOMP nil})         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:
      <fr:p>By cases on <fr:code>x</fr:code>.</fr:p>
      <fr:ol><fr:li>
          Case <fr:code>0</fr:code>:
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {chomp (0 :: xs)} \\               &amp;= {\hspace {-2pt}\text {\textdollar }{1}}(\texttt {chomp xs}) \\               &amp;\le  {\hspace {-2pt}\text {\textdollar }{1}}({\hspace {-2pt}\text {\textdollar }{(\texttt {length xs})}}(\texttt {CHOMP xs})) &amp;&amp;\text {(IH)} \\               &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + \texttt {length xs})}}(\texttt {CHOMP xs}) \\               &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {length (0 :: xs)})}}(\texttt {CHOMP (0 :: xs)}) \\             \end {aligned}           </fr:tex></fr:li>
        <fr:li>
          Case otherwise:
          <fr:tex
display="block">             \begin {aligned}               &amp;\texttt {chomp (x :: xs)} \\               &amp;= \texttt {x :: xs} &amp;&amp;\text {(case assumption)} \\               &amp;= {\hspace {-2pt}\text {\textdollar }{0}}(\texttt {x :: xs}) \\               &amp;\le  {\hspace {-2pt}\text {\textdollar }{(\texttt {length (x :: xs)})}}(\texttt {x :: xs}) \\               &amp;= {\hspace {-2pt}\text {\textdollar }{(\texttt {length (x :: xs)})}}(\texttt {CHOMP (x :: xs)}) \\             \end {aligned}           </fr:tex></fr:li></fr:ol></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1633</fr:anchor><fr:taxon>Theorem</fr:taxon><fr:addr>150-0047</fr:addr><fr:route>150-0047.xml</fr:route><fr:title>Inequality of reverse-and-append with slow reverse and append</fr:title></fr:frontmatter><fr:mainmatter><fr:p>For all <fr:code>l, acc : int list</fr:code>, we have <fr:tex
display="block">\texttt {revApp (l, acc)} \le  \texttt {APP (revSlow l, acc)}.</fr:tex></fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1632</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#193</fr:addr><fr:route>unstable-193.xml</fr:route><fr:parent>150-0047</fr:parent></fr:frontmatter><fr:mainmatter>
  By structural induction on <fr:code>l</fr:code>.
  <fr:ol><fr:li>
      Case <fr:code>nil</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revApp (nil, acc)} \\           &amp;= \texttt {acc} \\           &amp;= \texttt {APPEND (nil, acc)} \\           &amp;= \texttt {APPEND (revSlow nil, acc)}         \end {aligned}       </fr:tex></fr:li>
    <fr:li>
      Case <fr:code>x :: xs</fr:code>:
      <fr:tex
display="block">         \begin {aligned}           &amp;\texttt {revApp (x :: xs, acc)} \\           &amp;= {\hspace {-2pt}\text {\textdollar }{1}}(\texttt {revApp (xs, x :: acc)}) \\           &amp;\le  {\hspace {-2pt}\text {\textdollar }{1}}(\texttt {APP (revSlow xs, x :: acc)}) &amp;&amp;\text {(IH)} \\           &amp;\le  {\hspace {-2pt}\text {\textdollar }{(1 + \texttt {length xs})}}(\texttt {APP (revSlow xs, x :: acc)}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{(1 + \texttt {length xs})}}(\texttt {APP (APP (revSlow xs, [x]), acc)}) \\           &amp;= {\hspace {-2pt}\text {\textdollar }{1}}(\texttt {APP (revSlow xs @ [x], acc)}) \\           &amp;= \texttt {APP (revSlow (x :: xs), acc)}         \end {aligned}       </fr:tex></fr:li></fr:ol>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1635</fr:anchor><fr:taxon>Corollary</fr:taxon><fr:addr>150-0048</fr:addr><fr:route>150-0048.xml</fr:route><fr:title>Inequality of fast and slow reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We have <fr:tex>\texttt {rev} \le  \texttt {revSlow}</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1634</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#192</fr:addr><fr:route>unstable-192.xml</fr:route><fr:parent>150-0048</fr:parent></fr:frontmatter><fr:mainmatter>
  Let <fr:code>l : int list</fr:code> be arbitrary.
  Using <fr:ref
addr="150-0047"
href="150-0047.xml"
taxon="Theorem"></fr:ref>:
  <fr:tex
display="block">     \begin {aligned}       &amp;\texttt {rev l} \\       &amp;= \texttt {revApp (l, nil)} \\       &amp;\le  \texttt {APP (revSlow l, nil)} &amp;&amp;\text {(theorem)} \\       &amp;= \texttt {revSlow l}     \end {aligned}   </fr:tex>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1642</fr:anchor><fr:addr>150-003S</fr:addr><fr:route>150-003S.xml</fr:route><fr:title>Extensional phase</fr:title></fr:frontmatter><fr:mainmatter><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1637</fr:anchor><fr:taxon>Innovation</fr:taxon><fr:addr>150-0049</fr:addr><fr:route>150-0049.xml</fr:route><fr:title>Extensional phase</fr:title></fr:frontmatter><fr:mainmatter><fr:p>In intuitionistic/modal logic, we sometimes have propositions beyond "true" and "false".</fr:p><fr:p>We add a third proposition (like "sometimes"), <fr:tex>\mathbf {ext}</fr:tex>, meaning "true if you don't care about cost". We call this proposition "the extensional phase". It comes with the following axioms:</fr:p><fr:ol><fr:li>If <fr:tex>\mathbf {ext}</fr:tex>, then <fr:tex>{\hspace {-2pt}\text {\textdollar }{c}}(e) = e</fr:tex>. (If we don't care about cost, then we might as well delete the cost annotations.)</fr:li>
  <fr:li>If <fr:tex>\mathbf {ext}</fr:tex>, then <fr:tex>e \le  e'</fr:tex> implies <fr:tex>e = e'</fr:tex>. (Since <fr:link
href="150-0045.xml"
type="local"
addr="150-0045">program inequality</fr:link> requires programs behave the same way except for cost, two inequal programs are equal if we don't care about cost.)</fr:li></fr:ol></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1638</fr:anchor><fr:taxon>Remark</fr:taxon><fr:addr>150-004B</fr:addr><fr:route>150-004B.xml</fr:route><fr:title>Asymmetry between cost and data</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Cost and data are asymmetric. We ran into trouble (<fr:ref
addr="150-003X"
href="150-003X.xml"
taxon="Concern"></fr:ref> and <fr:ref
addr="150-003U"
href="150-003U.xml"
taxon="Concern"></fr:ref>) when trying to delete data and only reason about cost, but there's no issue with deleting cost and only reasoning about data.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1639</fr:anchor><fr:taxon>Definition</fr:taxon><fr:addr>150-004A</fr:addr><fr:route>150-004A.xml</fr:route><fr:title>Extensional equivalence</fr:title></fr:frontmatter><fr:mainmatter><fr:p>Define <fr:tex>e \cong  e'</fr:tex> as "if <fr:tex>\mathbf {ext}</fr:tex>, then <fr:tex>e = e'</fr:tex>". Informally, this means that <fr:tex>e</fr:tex> and <fr:tex>e'</fr:tex> are equal, as long as we don't care about cost.</fr:p></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1641</fr:anchor><fr:taxon>Corollary</fr:taxon><fr:addr>150-004C</fr:addr><fr:route>150-004C.xml</fr:route><fr:title>Extensional equivalence of fast and slow reverse</fr:title></fr:frontmatter><fr:mainmatter><fr:p>We have <fr:tex>\texttt {rev} \cong  \texttt {revSlow}</fr:tex>.</fr:p>
 
   
   <fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="false"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1640</fr:anchor><fr:taxon>Proof</fr:taxon><fr:addr>#191</fr:addr><fr:route>unstable-191.xml</fr:route><fr:parent>150-004C</fr:parent></fr:frontmatter><fr:mainmatter>
  <fr:p>Assume <fr:tex>\mathbf {ext}</fr:tex>; it remains to show <fr:tex>\texttt {rev} = \texttt {revSlow}</fr:tex>.</fr:p>
  <fr:p>By <fr:ref
addr="150-0048"
href="150-0048.xml"
taxon="Corollary"></fr:ref>, we have that <fr:tex>\texttt {rev} \le  \texttt {revSlow}</fr:tex>. So, by the property of the <fr:link
href="150-0049.xml"
type="local"
addr="150-0049">extensional phase</fr:link> about inequality, we have <fr:tex>\texttt {rev} = \texttt {revSlow}</fr:tex>.</fr:p>
</fr:mainmatter></fr:tree>
 
</fr:mainmatter></fr:tree></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1643</fr:anchor><fr:addr>150-003Z</fr:addr><fr:route>150-003Z.xml</fr:route><fr:title>Summary</fr:title></fr:frontmatter><fr:mainmatter><fr:p>To address subtleties with numbers-only recurrences, we justified the stance that <fr:link
href="150-003Y.xml"
type="local"
addr="150-003Y">a program is its own cost recurrence</fr:link> when <fr:link
href="150-003T.xml"
type="local"
addr="150-003T">cost annotations</fr:link> are included in the program itself. This allowed us to give exact solutions to cost recurrences; to give upper bounds, we introduced <fr:link
href="150-0045.xml"
type="local"
addr="150-0045">program inequality</fr:link>, comparing the cost of two programs when they behave the same way. Finally, to recover <fr:link
href="150-004A.xml"
type="local"
addr="150-004A">extensional equivalence</fr:link>, we introduced the <fr:link
href="150-0049.xml"
type="local"
addr="150-0049">extensional phase</fr:link>, a logical proposition that justifies deleting cost and unifying inequality and equality.</fr:p></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter></fr:tree></fr:mainmatter><fr:backmatter><fr:contributions></fr:contributions><fr:context></fr:context><fr:related><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1684</fr:anchor><fr:taxon>Person</fr:taxon><fr:addr>bjwu</fr:addr><fr:route>bjwu.xml</fr:route><fr:title>Brandon Wu</fr:title><fr:meta
name="external">https://brandonspark.github.io/</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1685</fr:anchor><fr:taxon>Person</fr:taxon><fr:addr>dilsunk</fr:addr><fr:route>dilsunk.xml</fr:route><fr:title>Dilsun Kaynar</fr:title><fr:meta
name="external">https://www.cs.cmu.edu/~dilsun/</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1686</fr:anchor><fr:taxon>Person</fr:taxon><fr:addr>hgrodin</fr:addr><fr:route>hgrodin.xml</fr:route><fr:title>Harrison Grodin</fr:title><fr:meta
name="external">https://www.harrisongrodin.com/</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1687</fr:anchor><fr:taxon>Person</fr:taxon><fr:addr>jacobneu</fr:addr><fr:route>jacobneu.xml</fr:route><fr:title>Jacob Neumann</fr:title><fr:meta
name="external">https://jacobneu.github.io/</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1688</fr:anchor><fr:taxon>Person</fr:taxon><fr:addr>me51</fr:addr><fr:route>me51.xml</fr:route><fr:title>Michael Erdmann</fr:title><fr:meta
name="external">https://www.cs.cmu.edu/~me/whois-me.html</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1689</fr:anchor><fr:taxon>Person</fr:taxon><fr:addr>sb21</fr:addr><fr:route>sb21.xml</fr:route><fr:title>Stephen Brookes</fr:title><fr:meta
name="external">http://www.cs.cmu.edu/~brookes/</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree></fr:related><fr:backlinks></fr:backlinks><fr:references><fr:tree
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"><fr:frontmatter><fr:anchor>1683</fr:anchor><fr:taxon>Reference</fr:taxon><fr:addr>standardml</fr:addr><fr:route>standardml.xml</fr:route><fr:title>Standard ML</fr:title><fr:meta
name="external">https://smlfamily.github.io/</fr:meta></fr:frontmatter><fr:mainmatter></fr:mainmatter></fr:tree></fr:references></fr:backmatter></fr:tree>