<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta name="robots" content="index,nofollow">



<title>FunctionalRecordUpdate - MLton Standard ML Compiler (SML Compiler)</title>
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="all" href="common.css">
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="screen" href="screen.css">
<link rel="stylesheet" type="text/css" charset="iso-8859-1" media="print" href="print.css">


<link rel="Start" href="Home">


</head>

<body lang="en" dir="ltr">

<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-833377-1";
urchinTracker();
</script>
<table bgcolor = lightblue cellspacing = 0 style = "border: 0px;" width = 100%>
  <tr>
    <td style = "
		border: 0px;
		color: darkblue; 
		font-size: 150%;
		text-align: left;">
      <a class = mltona href="Home">MLton 20061025</a>
    <td style = "
		border: 0px;
		font-size: 150%;
		text-align: center;
		width: 50%;">
      FunctionalRecordUpdate
    <td style = "
		border: 0px;
		text-align: right;">
      <table cellspacing = 0 style = "border: 0px">
        <tr style = "vertical-align: middle;">
      </table>
  <tr style = "background-color: white;">
    <td colspan = 3
	style = "
		border: 0px;
		font-size:70%;
		text-align: right;">
      <a href = "Home">Home</a>
      &nbsp;<a href = "Index">Index</a>
      &nbsp;
</table>
<div id="content" lang="en" dir="ltr">
Functional record update is the copying of a record while replacing the values of some of the fields.  <a href="StandardML">Standard ML</a> does not have explicit syntax for functional record update.  We will show below how to implement functional record update in SML, with a little boilerplate code. <p>
As an example, the functional update of the record 
<pre class=code>
{a <B><FONT COLOR="#5F9EA0">=</FONT></B> 13, b <B><FONT COLOR="#5F9EA0">=</FONT></B> 14, c <B><FONT COLOR="#5F9EA0">=</FONT></B> 15} 
</PRE>
 with <tt>c&nbsp;=&nbsp;16</tt> yields a new record  
<pre class=code>
{a <B><FONT COLOR="#5F9EA0">=</FONT></B> 13, b <B><FONT COLOR="#5F9EA0">=</FONT></B> 14, c <B><FONT COLOR="#5F9EA0">=</FONT></B> 16}
</PRE>
 Functional record update also makes sense with multiple simultaneous updates.  For example, the functional update of the record above with <tt>a&nbsp;=&nbsp;18,&nbsp;c&nbsp;=&nbsp;19</tt> yields a new record  
<pre class=code>
{a <B><FONT COLOR="#5F9EA0">=</FONT></B> 18, b <B><FONT COLOR="#5F9EA0">=</FONT></B> 14, c <B><FONT COLOR="#5F9EA0">=</FONT></B> 19}
</PRE>
 
</p>
<p>
One could easily imagine an extension of the SML that supports functional record update.  For example 
<pre class=code>
e <B><FONT COLOR="#A020F0">with</FONT></B> {a <B><FONT COLOR="#5F9EA0">=</FONT></B> 16, b <B><FONT COLOR="#5F9EA0">=</FONT></B> 17}
</PRE>
 would create a copy of the record denoted by <tt>e</tt> with field <tt>a</tt> replaced with <tt>16</tt> and <tt>b</tt> replaced with <tt>17</tt>. 
</p>
<p>
Since there is no such syntax in SML, we now show how to implement functional record update directly.  We first give a simple implementation that has a number of problems.  We then give an advanced implementation, that, while complex underneath, is a resuable library that admits simple use. 
</p>
<h2 id="head-fa2179e8b7b0b4d2c689f9612a22a231e6cd9bf2">Simple implementation</h2>
<p>
To support functional record update on the record type 
<pre class=code>
{a: 'a, b: 'b, c: 'c} 
</PRE>
 first, define an update function for each component. 
<pre class=code>
<B><FONT COLOR="#A020F0">fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">withA</FONT></I></B></FONT></B> ({a <B><FONT COLOR="#5F9EA0">=</FONT></B> _, b, c}, a) <B><FONT COLOR="#5F9EA0">=</FONT></B> {a <B><FONT COLOR="#5F9EA0">=</FONT></B> a, b <B><FONT COLOR="#5F9EA0">=</FONT></B> b, c <B><FONT COLOR="#5F9EA0">=</FONT></B> c}
<B><FONT COLOR="#A020F0">fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">withB</FONT></I></B></FONT></B> ({a, b <B><FONT COLOR="#5F9EA0">=</FONT></B> _, c}, b) <B><FONT COLOR="#5F9EA0">=</FONT></B> {a <B><FONT COLOR="#5F9EA0">=</FONT></B> a, b <B><FONT COLOR="#5F9EA0">=</FONT></B> b, c <B><FONT COLOR="#5F9EA0">=</FONT></B> c}
<B><FONT COLOR="#A020F0">fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">withC</FONT></I></B></FONT></B> ({a, b, c <B><FONT COLOR="#5F9EA0">=</FONT></B> _}, c) <B><FONT COLOR="#5F9EA0">=</FONT></B> {a <B><FONT COLOR="#5F9EA0">=</FONT></B> a, b <B><FONT COLOR="#5F9EA0">=</FONT></B> b, c <B><FONT COLOR="#5F9EA0">=</FONT></B> c}
</PRE>
 Then, one can express <tt>e&nbsp;with&nbsp;{a&nbsp;=&nbsp;16,&nbsp;b&nbsp;=&nbsp;17}&nbsp;</tt> as 
<pre class=code>
withB (withA (e, 16), 17)
</PRE>
 With infix notation 
<pre class=code>
<B><FONT COLOR="#A020F0">infix</FONT></B> withA withB withC
</PRE>
 the syntax is almost as concise as a language extension. 
<pre class=code>
e withA 16 withB 17
</PRE>
 
</p>
<p>
This approach suffers from the fact that the amount of boilerplate code is quadratic in the number of record fields.  Furthermore, changing, adding, or deleting a field requires time proportional to the number of fields (because each <tt>with</tt> function must be changed).  It is also annoying to have to define a <tt>with</tt> function, possibly with a fixity declaration, for each field. 
</p>
<p>
Fortunately, there is a solution to these problems. 
</p>
<h2 id="head-02713f1aab596f254ab1dd3551f0c5a015b6e40b">Advanced implementation</h2>
<p>
Using <a href="Fold">Fold</a> one can define a family of <tt>makeUpdate&lt;N&gt;</tt> functions and single <em>update</em> operator <tt>U</tt> so that one can define a functional record update function for any record type simply by specifying a (trivial) isomorphism between that type and a <a href="ProductType">product type</a>.  For example, suppose that we would like to do functional record update on records with fields <tt>a</tt> and <tt>b</tt>.  Then one defines a function <tt>updateAB</tt> as follows. 
</p>

<pre class=code>
<B><FONT COLOR="#A020F0">val</FONT></B> updateAB <B><FONT COLOR="#5F9EA0">=</FONT></B>
   <B><FONT COLOR="#A020F0">fn</FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
   <B><FONT COLOR="#A020F0">let</FONT></B>
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">p2r</FONT></I></B></FONT></B> (v1 &amp; v2) <B><FONT COLOR="#5F9EA0">=</FONT></B> {a <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, b <B><FONT COLOR="#5F9EA0">=</FONT></B> v2}
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">r2p</FONT></I></B></FONT></B> {a <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, b <B><FONT COLOR="#5F9EA0">=</FONT></B> v2} <B><FONT COLOR="#5F9EA0">=</FONT></B> (v1 &amp; v2)
   <B><FONT COLOR="#A020F0">in</FONT></B>
      makeUpdate2 (p2r, p2r, r2p)
   <B><FONT COLOR="#A020F0">end</FONT></B>
   z
</PRE>
<p>
 
</p>
<p>
The functions <tt>p2r</tt> (think <em>product to record</em>) and <tt>r2p</tt> (think <em>record to product</em>) specify an isomorphism between  <tt>a,b</tt> records and binary products.  There is a second use of <tt>p2r</tt> to work around the lack of first-class polymorphism in SML. 
</p>
<p>
With the definition of <tt>updateAB</tt> in place, the following expressions are valid. 
</p>

<pre class=code>
updateAB {a <B><FONT COLOR="#5F9EA0">=</FONT></B> 13, b <B><FONT COLOR="#5F9EA0">=</FONT></B> <B><FONT COLOR="#BC8F8F">&quot;hello&quot;</FONT></B>} (U#b <B><FONT COLOR="#BC8F8F">&quot;goodbye&quot;</FONT></B>) $
updateAB {a <B><FONT COLOR="#5F9EA0">=</FONT></B> 13.5, b <B><FONT COLOR="#5F9EA0">=</FONT></B> true} (U#b false) (U#a 12.5) $
</PRE>
<p>
 
</p>
<p>
As another example, suppose that we would like to do functional record update on records with fields <tt>b</tt>, <tt>c</tt>, and <tt>d</tt>.  Then one defines a function <tt>updateBCD</tt> as follows. 
</p>

<pre class=code>
<B><FONT COLOR="#A020F0">val</FONT></B> updateBCD <B><FONT COLOR="#5F9EA0">=</FONT></B>
   <B><FONT COLOR="#A020F0">fn</FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
   <B><FONT COLOR="#A020F0">let</FONT></B>
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">p2r</FONT></I></B></FONT></B> (v1 &amp; v2 &amp; v3) <B><FONT COLOR="#5F9EA0">=</FONT></B> {b <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, c <B><FONT COLOR="#5F9EA0">=</FONT></B> v2, d <B><FONT COLOR="#5F9EA0">=</FONT></B> v3}
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">r2p</FONT></I></B></FONT></B> {b <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, c <B><FONT COLOR="#5F9EA0">=</FONT></B> v2, d <B><FONT COLOR="#5F9EA0">=</FONT></B> v3} <B><FONT COLOR="#5F9EA0">=</FONT></B> (v1 &amp; v2 &amp; v3)
   <B><FONT COLOR="#A020F0">in</FONT></B>
      makeUpdate3 (p2r, p2r, r2p)
   <B><FONT COLOR="#A020F0">end</FONT></B>
   z
</PRE>
<p>
 
</p>
<p>
With the definition of <tt>updateBCD</tt> in place, the following expression is valid. 
</p>

<pre class=code>
updateBCD {b <B><FONT COLOR="#5F9EA0">=</FONT></B> 1, c <B><FONT COLOR="#5F9EA0">=</FONT></B> 2, d <B><FONT COLOR="#5F9EA0">=</FONT></B> 3} (U#c 4) (U#c 5) $
</PRE>
<p>
 
</p>
<p>
Note that not all fields need be updated and that the same field may be updated multiple times.  Further note that the same <tt>U</tt> operator is used for all update functions (in the above, for both <tt>updateAB</tt> and <tt>updateBCD</tt>). 
</p>
<p>
In general, to define a functional-record-update function on records with fields <tt>f1</tt>, <tt>f2</tt>, ..., <tt>fN</tt>, use the following template. 
</p>

<pre class=code>
<B><FONT COLOR="#A020F0">val</FONT></B> update <B><FONT COLOR="#5F9EA0">=</FONT></B>
   <B><FONT COLOR="#A020F0">fn</FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
   <B><FONT COLOR="#A020F0">let</FONT></B> 
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">p2r</FONT></I></B></FONT></B> (v1 &amp; v2 &amp; ... &amp; vn) <B><FONT COLOR="#5F9EA0">=</FONT></B> {f1 <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, f2 <B><FONT COLOR="#5F9EA0">=</FONT></B> v2, ..., <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">=</FONT></B> vn}
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">r2p</FONT></I></B></FONT></B> {f1 <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, f2 <B><FONT COLOR="#5F9EA0">=</FONT></B> v2, ..., <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">=</FONT></B> vn} <B><FONT COLOR="#5F9EA0">=</FONT></B> (v1 &amp; v2 &amp; ... &amp; vn)
   <B><FONT COLOR="#A020F0">in</FONT></B>
      makeUpdateN (p2r, p2r, r2p)
   <B><FONT COLOR="#A020F0">end</FONT></B>
   z
</PRE>
<p>
 
</p>
<p>
With this, one can update a record as follows. 
<pre class=code>
update {f1 <B><FONT COLOR="#5F9EA0">=</FONT></B> v1, ..., <B><FONT COLOR="#A020F0">fn</FONT></B> <B><FONT COLOR="#5F9EA0">=</FONT></B> vn} (U#fi1 vi1) ... (U#fim vim) $
</PRE>
 
</p>
<p>
If <tt>makeUpdateN</tt> is not already defined for the desired <tt>N</tt>, a generic <tt>makeUpdate</tt> function and special value, <tt>A</tt>, is defined so that one can use the following for <tt>makeUpdateN</tt>, where <tt>A</tt> is repeated <tt>N</tt> times. 
</p>

<pre class=code>
makeUpdate A ... A $
</PRE>
<p>
 
</p>
<h2 id="head-f7b6e4357c7be44d1408bdf8f0ac43469123a056">The FunctionalRecordUpdate structure</h2>
<p>
Here is the implementation of functional record update. 
</p>

<pre class=code>
<B><FONT COLOR="#5F9EA0">structure</FONT></B> FunctionalRecordUpdate <B><FONT COLOR="#5F9EA0">=</FONT></B>
   <B><FONT COLOR="#5F9EA0">struct</FONT></B>
      <B><FONT COLOR="#A020F0">datatype</FONT></B> ('x, 'y) u <B><FONT COLOR="#5F9EA0">=</FONT></B> X <B><FONT COLOR="#A020F0">of</FONT></B> 'x <B><FONT COLOR="#5F9EA0">|</FONT></B> Y <B><FONT COLOR="#A020F0">of</FONT></B> 'y

      <B><FONT COLOR="#A020F0">val</FONT></B> makeUpdate <B><FONT COLOR="#5F9EA0">=</FONT></B>
         <B><FONT COLOR="#A020F0">fn</FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
         Fold.fold
         (((), (),
           <B><FONT COLOR="#A020F0">fn</FONT></B> f <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> f <B><FONT COLOR="#A020F0">o</FONT></B> X,
           <B><FONT COLOR="#A020F0">fn</FONT></B> (a, u) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#A020F0">case</FONT></B> u <B><FONT COLOR="#A020F0">of</FONT></B> X x <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> x <B><FONT COLOR="#5F9EA0">|</FONT></B> _ <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> a),
          <B><FONT COLOR="#A020F0">fn</FONT></B> (p, up, _, _) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#A020F0">fn</FONT></B> (p2r, p2r', r2p) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> <B><FONT COLOR="#A020F0">fn</FONT></B> r <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
          Fold.fold ((p2r' (p id), up, r2p r),
                     <B><FONT COLOR="#A020F0">fn</FONT></B> (_, _, p) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> p2r p))
         z
         
      <B><FONT COLOR="#A020F0">val</FONT></B> A <B><FONT COLOR="#5F9EA0">=</FONT></B>
         <B><FONT COLOR="#A020F0">fn</FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
         Fold.step0
         (<B><FONT COLOR="#A020F0">fn</FONT></B> (_, _, p, up) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
          (p, up, <B><FONT COLOR="#A020F0">fn</FONT></B> f <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> p (f <B><FONT COLOR="#A020F0">o</FONT></B> X) &amp; (f <B><FONT COLOR="#A020F0">o</FONT></B> Y),
           <B><FONT COLOR="#A020F0">fn</FONT></B> (a &amp; b, u) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B>
           (<B><FONT COLOR="#A020F0">case</FONT></B> u <B><FONT COLOR="#A020F0">of</FONT></B> X x <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> up (a, x) <B><FONT COLOR="#5F9EA0">|</FONT></B> _ <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> a)
           &amp; (<B><FONT COLOR="#A020F0">case</FONT></B> u <B><FONT COLOR="#A020F0">of</FONT></B> Y y <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> y <B><FONT COLOR="#5F9EA0">|</FONT></B> _ <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> b)))
         z

<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">makeUpdate2</FONT></I></B></FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B> makeUpdate A A $ z
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">makeUpdate3</FONT></I></B></FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B> makeUpdate A A A $ z
<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">makeUpdate4</FONT></I></B></FONT></B> z <B><FONT COLOR="#5F9EA0">=</FONT></B> makeUpdate A A A A $ z

<B><FONT COLOR="#A020F0">      fun </FONT></B><B><FONT COLOR="#0000FF"><B><I><FONT COLOR="#000000">U</FONT></I></B></FONT></B> s v <B><FONT COLOR="#5F9EA0">=</FONT></B> Fold.step0 (<B><FONT COLOR="#A020F0">fn</FONT></B> (r, up, p) <B><FONT COLOR="#5F9EA0">=</FONT></B><B><FONT COLOR="#5F9EA0">&gt;</FONT></B> (r, up, up (p, s r v)))
   <B><FONT COLOR="#A020F0">end</FONT></B>
</PRE>
<p>
 
</p>
<p>
The idea of <tt>makeUpdate</tt> is to inductively build the update function for n-ary product types.  Each <tt>A</tt> supplied to <tt>makeUpdate</tt> adds one more level to the product.  When finished with its arguments, <tt>makeUpdate</tt> begins a second fold, this time to process a variable number of <tt>U</tt> steps.  The second fold begins by converting the supplied record to a product, using the supplied isomorphism (<tt>p2r'</tt>).  Each step works by selecting a "path",  <tt>s&nbsp;r&nbsp;v</tt>), from the inductively constructed product, reformatted by the supplied isomorphism to look like a record.  Then, the inductively constructed update function is applied to the record-as-product and the path <tt>up&nbsp;(p,&nbsp;s&nbsp;r&nbsp;v)</tt> to yield a new record-as-product. Finally, at the end of the fold, the product is converted back to a record using the supplied isomorphism (<tt>p2r</tt>). 
</p>
<h2 id="head-12c4ffe1d987164a4bedf6ab2aac597a113e181c">Efficiency</h2>
<p>
With MLton, the efficiency of this approach is as good as one would expect with the special syntax.  Namely a sequence of updates will be optimized into a single record construction that copies the unchanged fields and fills in the changed fields with their new values. 
</p>
</div>



<p>
<hr>
Last edited on 2006-03-22 03:29:37 by <span title="209-6-203-188.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com"><a href="MatthewFluet">MatthewFluet</a></span>.
</body></html>
