<!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 MLTONWIKIVERSION</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">13</FONT></B>, b = <B><FONT COLOR="#5F9EA0">14</FONT></B>, c = <B><FONT COLOR="#5F9EA0">15</FONT></B>} 
</PRE>
 with <tt>c&nbsp;=&nbsp;16</tt> yields a new record  
<pre class=code>
{a = <B><FONT COLOR="#5F9EA0">13</FONT></B>, b = <B><FONT COLOR="#5F9EA0">14</FONT></B>, c = <B><FONT COLOR="#5F9EA0">16</FONT></B>}
</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">18</FONT></B>, b = <B><FONT COLOR="#5F9EA0">14</FONT></B>, c = <B><FONT COLOR="#5F9EA0">19</FONT></B>}
</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">16</FONT></B>, b = <B><FONT COLOR="#5F9EA0">17</FONT></B>}
</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 reusable 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> withA ({a = _, b, c}, a) = {a = a, b = b, c = c}
<B><FONT COLOR="#A020F0">fun</FONT></B> withB ({a, b = _, c}, b) = {a = a, b = b, c = c}
<B><FONT COLOR="#A020F0">fun</FONT></B> withC ({a, b, c = _}, c) = {a = a, b = b, c = 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, <B><FONT COLOR="#5F9EA0">16</FONT></B>), <B><FONT COLOR="#5F9EA0">17</FONT></B>)
</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 <B><FONT COLOR="#5F9EA0">16</FONT></B> withB <B><FONT COLOR="#5F9EA0">17</FONT></B>
</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="#A020F0">fn</FONT></B> z =&gt;
   <B><FONT COLOR="#A020F0">let</FONT></B>
      <B><FONT COLOR="#A020F0">fun</FONT></B> p2r (v1 &amp; v2) = {a = v1, b = v2}
      <B><FONT COLOR="#A020F0">fun</FONT></B> r2p {a = v1, b = v2} = (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 <a href="FirstClassPolymorphism">first-class polymorphism</a> 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">13</FONT></B>, 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">13.5</FONT></B>, b = true} (U#b false) (U#a <B><FONT COLOR="#5F9EA0">12.5</FONT></B>) $
</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="#A020F0">fn</FONT></B> z =&gt;
   <B><FONT COLOR="#A020F0">let</FONT></B>
      <B><FONT COLOR="#A020F0">fun</FONT></B> p2r (v1 &amp; v2 &amp; v3) = {b = v1, c = v2, d = v3}
      <B><FONT COLOR="#A020F0">fun</FONT></B> r2p {b = v1, c = v2, d = v3} = (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">1</FONT></B>, c = <B><FONT COLOR="#5F9EA0">2</FONT></B>, d = <B><FONT COLOR="#5F9EA0">3</FONT></B>} (U#c <B><FONT COLOR="#5F9EA0">4</FONT></B>) (U#c <B><FONT COLOR="#5F9EA0">5</FONT></B>) $
</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="#A020F0">fn</FONT></B> z =&gt;
   <B><FONT COLOR="#A020F0">let</FONT></B> 
      <B><FONT COLOR="#A020F0">fun</FONT></B> p2r (v1 &amp; v2 &amp; ... &amp; vn) = {f1 = v1, f2 = v2, ..., <B><FONT COLOR="#A020F0">fn</FONT></B> = vn}
      <B><FONT COLOR="#A020F0">fun</FONT></B> r2p {f1 = v1, f2 = v2, ..., <B><FONT COLOR="#A020F0">fn</FONT></B> = vn} = (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 = v1, ..., <B><FONT COLOR="#A020F0">fn</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="#0000FF">structure</FONT></B> FunctionalRecordUpdate =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">datatype</FONT></B><B><FONT COLOR="#228B22"> ('x, 'y) u </FONT></B>=<B><FONT COLOR="#228B22"> <FONT COLOR="#B8860B">X</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> 'x </FONT></B>|<B><FONT COLOR="#228B22"> <FONT COLOR="#B8860B">Y</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> 'y

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

      <B><FONT COLOR="#A020F0">fun</FONT></B> makeUpdate2 z = makeUpdate A A $ z
      <B><FONT COLOR="#A020F0">fun</FONT></B> makeUpdate3 z = makeUpdate A A A $ z
      <B><FONT COLOR="#A020F0">fun</FONT></B> makeUpdate4 z = makeUpdate A A A A $ z

      <B><FONT COLOR="#A020F0">fun</FONT></B> U s v = Fold.step0 (<B><FONT COLOR="#A020F0">fn</FONT></B> (r, up, p) =&gt; (r, up, up (p, s r v)))
   <B><FONT COLOR="#0000FF">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 2007-08-15 22:06:30 by <span title="fenrir.uchicago.edu"><a href="MatthewFluet">MatthewFluet</a></span>.
</body></html>
