Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > d07d7ab417d79053e7e0155c99e1a1c8 > files > 2492

mlton-20100608-3.fc15.i686.rpm

<!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>UniversalType - 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%;">
      UniversalType
    <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 = "TitleIndex">Index</a>
      &nbsp;
</table>
<div id="content" lang="en" dir="ltr">
A universal type is a type into which all other types can be embedded. Here's a <a href="StandardML">Standard ML</a> signature for a universal type. 
<pre class=code>
<B><FONT COLOR="#0000FF">signature</FONT></B> UNIVERSAL_TYPE =
   <B><FONT COLOR="#0000FF">sig</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><B><FONT COLOR="#228B22"> t

      </FONT></B><B><FONT COLOR="#A020F0">val</FONT></B> embed: unit -&gt; ('a -&gt; t) * (t -&gt; 'a option)
   <B><FONT COLOR="#0000FF">end</FONT></B>
</PRE>
<p>
 
</p>
<p>
The idea is that <tt>type&nbsp;t</tt> is the universal type and that each call to <tt>embed</tt> returns a new pair of functions  <tt>(inject,&nbsp;project)</tt>, where <tt>inject</tt> embeds a value into the universal type and <tt>project</tt> extracts the value from the universal type.  A pair <tt>(inject,&nbsp;project)</tt> returned by <tt>embed</tt> works together in that <tt>project&nbsp;u</tt> will return <tt>SOME&nbsp;v</tt> if and only if <tt>u</tt> was created by <tt>inject&nbsp;v</tt>.  If <tt>u</tt> was created by a different function <tt>inject'</tt>, then <tt>project</tt> returns <tt>NONE</tt>. 
</p>
<p>
Here's an example embedding integers and reals into a universal type. 
<pre class=code>
<B><FONT COLOR="#0000FF">functor</FONT></B> Test (U: UNIVERSAL_TYPE): <B><FONT COLOR="#0000FF">sig</FONT></B> <B><FONT COLOR="#0000FF">end</FONT></B> =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">val</FONT></B> (intIn: int -&gt; U.t, intOut) = U.embed ()
      <B><FONT COLOR="#A020F0">val</FONT></B> r: U.t ref = ref (intIn <B><FONT COLOR="#5F9EA0">13</FONT></B>)
      <B><FONT COLOR="#A020F0">val</FONT></B> s1 =
         <B><FONT COLOR="#A020F0">case</FONT></B> intOut (!r) <B><FONT COLOR="#A020F0">of</FONT></B>
            NONE =&gt; <B><FONT COLOR="#BC8F8F">&quot;NONE&quot;</FONT></B>
          | SOME i =&gt; Int.toString i
      <B><FONT COLOR="#A020F0">val</FONT></B> (realIn: real -&gt; U.t, realOut) = U.embed ()
      <B><FONT COLOR="#A020F0">val</FONT></B> () = r := realIn <B><FONT COLOR="#5F9EA0">13.0</FONT></B>
      <B><FONT COLOR="#A020F0">val</FONT></B> s2 =
         <B><FONT COLOR="#A020F0">case</FONT></B> intOut (!r) <B><FONT COLOR="#A020F0">of</FONT></B>
            NONE =&gt; <B><FONT COLOR="#BC8F8F">&quot;NONE&quot;</FONT></B>
          | SOME i =&gt; Int.toString i
      <B><FONT COLOR="#A020F0">val</FONT></B> s3 =
         <B><FONT COLOR="#A020F0">case</FONT></B> realOut (!r) <B><FONT COLOR="#A020F0">of</FONT></B>
            NONE =&gt; <B><FONT COLOR="#BC8F8F">&quot;NONE&quot;</FONT></B>
          | SOME x =&gt; Real.toString x
      <B><FONT COLOR="#A020F0">val</FONT></B> () = print (concat [s1, <B><FONT COLOR="#BC8F8F">&quot; &quot;</FONT></B>, s2, <B><FONT COLOR="#BC8F8F">&quot; &quot;</FONT></B>, s3, <B><FONT COLOR="#BC8F8F">&quot;\n&quot;</FONT></B>])
   <B><FONT COLOR="#0000FF">end</FONT></B>
</PRE>
 
</p>
<p>
Applying <tt>Test</tt> to an appropriate implementation will print 
<pre>13 NONE 13.0
</pre>
</p>
<p>
Note that two different calls to embed on the same type return different embeddings. 
</p>
<p>
Standard ML does not have explicit support for universal types; however, there are at least two ways to implement them. 
</p>
<h2 id="head-5ab5e9f7a9267673649cd34bf0a7cf4b914d2288">Implementation Using Exceptions</h2>
<p>
While the intended use of SML exceptions is for exception handling, an accidental feature of their design is that the <tt>exn</tt> type is a universal type.  The implementation relies on being able to declare exceptions locally to a function and on the fact that exceptions are <a href="GenerativeException">generative</a>. 
</p>

<pre class=code>
<B><FONT COLOR="#0000FF">structure</FONT></B> U:&gt; UNIVERSAL_TYPE =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><B><FONT COLOR="#228B22"> t </FONT></B>=<B><FONT COLOR="#228B22"> exn

      </FONT></B><B><FONT COLOR="#A020F0">fun</FONT></B> <B><FONT COLOR="#228B22">'a</FONT></B> embed () =
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">exception</FONT></B><B><FONT COLOR="#228B22"> <FONT COLOR="#B8860B">E</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> 'a
            </FONT></B><B><FONT COLOR="#A020F0">fun</FONT></B> project (e: t): 'a option =
               <B><FONT COLOR="#A020F0">case</FONT></B> e <B><FONT COLOR="#A020F0">of</FONT></B>
                  E a =&gt; SOME a
                | _ =&gt; NONE
         <B><FONT COLOR="#A020F0">in</FONT></B>
            (E, project)
         <B><FONT COLOR="#A020F0">end</FONT></B>
   <B><FONT COLOR="#0000FF">end</FONT></B>
</PRE>
<p>
 
</p>
<h2 id="head-ce424b82430977939b90a4c1cb21f7a8e6f6301c">Implementation Using Functions and References</h2>

<pre class=code>
<B><FONT COLOR="#0000FF">structure</FONT></B> U:&gt; UNIVERSAL_TYPE =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">datatype</FONT></B><B><FONT COLOR="#228B22"> t </FONT></B>=<B><FONT COLOR="#228B22"> <FONT COLOR="#B8860B">T</FONT> <B><FONT COLOR="#A020F0">of</FONT></B> {clear: unit -&gt; unit,
                         store: unit -&gt; unit}

      </FONT></B><B><FONT COLOR="#A020F0">fun</FONT></B> <B><FONT COLOR="#228B22">'a</FONT></B> embed () =
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> r: 'a option ref = ref NONE
            <B><FONT COLOR="#A020F0">fun</FONT></B> inject (a: 'a): t =
               T {clear = <B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; r := NONE,
                  store = <B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; r := SOME a}
            <B><FONT COLOR="#A020F0">fun</FONT></B> project (T {clear, store}): 'a option =
               <B><FONT COLOR="#A020F0">let</FONT></B>
                  <B><FONT COLOR="#A020F0">val</FONT></B> () = store ()
                  <B><FONT COLOR="#A020F0">val</FONT></B> res = !r
                  <B><FONT COLOR="#A020F0">val</FONT></B> () = clear ()
               <B><FONT COLOR="#A020F0">in</FONT></B>
                  res
               <B><FONT COLOR="#A020F0">end</FONT></B>
         <B><FONT COLOR="#A020F0">in</FONT></B>
            (inject, project)
         <B><FONT COLOR="#A020F0">end</FONT></B>
   <B><FONT COLOR="#0000FF">end</FONT></B>
</PRE>
<p>
 
</p>
<p>
Note that due to the use of a shared ref cell, the above implementation is not thread safe. 
</p>
<p>
One could try to simplify the above implementation by eliminating the <tt>clear</tt> function, making <tt>type&nbsp;t&nbsp;=&nbsp;unit&nbsp;-&gt;&nbsp;unit</tt>. 
</p>

<pre class=code>
<B><FONT COLOR="#0000FF">structure</FONT></B> U:&gt; UNIVERSAL_TYPE =
   <B><FONT COLOR="#0000FF">struct</FONT></B>
      <B><FONT COLOR="#A020F0">type</FONT></B><B><FONT COLOR="#228B22"> t </FONT></B>=<B><FONT COLOR="#228B22"> unit -&gt; unit

      </FONT></B><B><FONT COLOR="#A020F0">fun</FONT></B> <B><FONT COLOR="#228B22">'a</FONT></B> embed () =
         <B><FONT COLOR="#A020F0">let</FONT></B>
            <B><FONT COLOR="#A020F0">val</FONT></B> r: 'a option ref = ref NONE
            <B><FONT COLOR="#A020F0">fun</FONT></B> inject (a: 'a): t = <B><FONT COLOR="#A020F0">fn</FONT></B> () =&gt; r := SOME a
            <B><FONT COLOR="#A020F0">fun</FONT></B> project (f: t): 'a option = (r := NONE; f (); !r)
         <B><FONT COLOR="#A020F0">in</FONT></B>
            (inject, project)
         <B><FONT COLOR="#A020F0">end</FONT></B>
   <B><FONT COLOR="#0000FF">end</FONT></B>
</PRE>
<p>
 
</p>
<p>
While correct, this approach keeps the contents of the ref cell alive longer than necessary, which could cause a space leak.  The problem is in <tt>project</tt>, where the call to <tt>f</tt> stores some value in some ref cell <tt>r'</tt>.  Perhaps <tt>r'</tt> is the same ref cell as <tt>r</tt>, but perhaps not.  If we do not clear <tt>r'</tt> before returning from <tt>project</tt>, then <tt>r'</tt> will keep the value alive, even though it is useless. 
</p>
<h2 id="head-a4bc8bf5caf54b18cea9f58e83dd4acb488deb17">Also see</h2>

    <ul>

    <li>
<p>
 <a href="PropertyList">PropertyList</a>: Lisp-style property lists implemented with a  universal type. 
</p>
</li>
</ul>

</div>



<p>
<hr>
Last edited on 2005-05-29 03:04:34 by <span title="cs78147114.pp.htv.fi"><a href="VesaKarvonen">VesaKarvonen</a></span>.
</body></html>