<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="AsciiDoc 8.6.10">
<title>AdmitsEquality</title>
<link rel="stylesheet" href="./asciidoc.css" type="text/css">
<link rel="stylesheet" href="./pygments.css" type="text/css">


<script type="text/javascript" src="./asciidoc.js"></script>
<script type="text/javascript">
/*<![CDATA[*/
asciidoc.install();
/*]]>*/
</script>
<link rel="stylesheet" href="./mlton.css" type="text/css">
</head>
<body class="article">
<div id="banner">
<div id="banner-home">
<a href="./Home">MLton 20201002</a>
</div>
</div>
<div id="header">
<h1>AdmitsEquality</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>A <a href="TypeConstructor">TypeConstructor</a> admits equality if whenever it is applied to
equality types, the result is an <a href="EqualityType">EqualityType</a>.  This notion enables
one to determine whether a type constructor application yields an
equality type solely from the application, without looking at the
definition of the type constructor.  It helps to ensure that
<a href="PolymorphicEquality">PolymorphicEquality</a> is only applied to sensible values.</p></div>
<div class="paragraph"><p>The definition of admits equality depends on whether the type
constructor was declared by a <span class="monospaced">type</span> definition or a
<span class="monospaced">datatype</span> declaration.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_type_definitions">Type definitions</h2>
<div class="sectionbody">
<div class="paragraph"><p>For type definition</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">type</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a1</span><span class="p">,</span><span class="w"> </span><span class="p">...,</span><span class="w"> </span><span class="n">&#39;an</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">...</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>type constructor <span class="monospaced">t</span> admits equality if the right-hand side of the
definition is an equality type after replacing <span class="monospaced">'a1</span>, &#8230;,
<span class="monospaced">'an</span> by equality types (it doesn&#8217;t matter which equality types
are chosen).</p></div>
<div class="paragraph"><p>For a nullary type definition, this amounts to the right-hand side
being an equality type.  For example, after the definition</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">type</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">int</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>type constructor <span class="monospaced">t</span> admits equality because <span class="monospaced">bool * int</span> is
an equality type.   On the other hand, after the definition</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">type</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">real</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>type constructor <span class="monospaced">t</span> does not admit equality, because <span class="monospaced">real</span>
is not an equality type.</p></div>
<div class="paragraph"><p>For another example, after the definition</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>type constructor <span class="monospaced">t</span> admits equality because <span class="monospaced">bool * int</span>
is an equality type (we could have chosen any equality type other than
<span class="monospaced">int</span>).</p></div>
<div class="paragraph"><p>On the other hand, after the definition</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>type constructor <span class="monospaced">t</span> does not admit equality because
<span class="monospaced">real * int</span> is not equality type.</p></div>
<div class="paragraph"><p>We can check that a type constructor admits equality using an
<span class="monospaced">eqtype</span> specification.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">structure</span><span class="w"> </span><span class="n">Ok</span><span class="p">:</span><span class="w"> </span><span class="k">sig</span><span class="w"> </span><span class="k">eqtype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w">   </span><span class="k">struct</span><span class="w"></span>
<span class="w">      </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
<span class="w">   </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">structure</span><span class="w"> </span><span class="n">Bad</span><span class="p">:</span><span class="w"> </span><span class="k">sig</span><span class="w"> </span><span class="k">eqtype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w">   </span><span class="k">struct</span><span class="w"></span>
<span class="w">      </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
<span class="w">   </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>On <span class="monospaced">structure Bad</span>, MLton reports the following error.</p></div>
<div class="listingblock">
<div class="content monospaced">
<pre>Error: z.sml 1.16-1.34.
  Type in structure disagrees with signature (admits equality): t.
    structure: type 'a t = [real] * _ * _
    defn at: z.sml 3.15-3.15
    signature: [eqtype] 'a t
    spec at: z.sml 1.30-1.30</pre>
</div></div>
<div class="paragraph"><p>The <span class="monospaced">structure:</span> section provides an explanation of why the type
did not admit equality, highlighting the problematic component
(<span class="monospaced">real</span>).</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_datatype_declarations">Datatype declarations</h2>
<div class="sectionbody">
<div class="paragraph"><p>For a type constructor declared by a datatype declaration to admit
equality, every <a href="Variant">variant</a> of the datatype must admit equality.  For
example, the following datatype admits equality because <span class="monospaced">bool</span> and
<span class="monospaced">char * int</span> are equality types.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">char</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">int</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>Nullary constructors trivially admit equality, so that the following
datatype admits equality.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">C</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>For a parameterized datatype constructor to admit equality, we
consider each <a href="Variant">variant</a> as a type definition, and require that the
definition admit equality.  For example, for the datatype</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>the type definitions</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">tA</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
<span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">tB</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>both admit equality.  Thus, type constructor <span class="monospaced">t</span> admits equality.</p></div>
<div class="paragraph"><p>On the other hand, the following datatype does not admit equality.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>As with type definitions, we can check using an <span class="monospaced">eqtype</span>
specification.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">structure</span><span class="w"> </span><span class="n">Bad</span><span class="p">:</span><span class="w"> </span><span class="k">sig</span><span class="w"> </span><span class="k">eqtype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w">   </span><span class="k">struct</span><span class="w"></span>
<span class="w">      </span><span class="k">datatype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
<span class="w">   </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>MLton reports the following error.</p></div>
<div class="listingblock">
<div class="content monospaced">
<pre>Error: z.sml 1.16-1.34.
  Type in structure disagrees with signature (admits equality): t.
    structure: datatype 'a t = B of [real] * _ | ...
    defn at: z.sml 3.19-3.19
    signature: [eqtype] 'a t
    spec at: z.sml 1.30-1.30</pre>
</div></div>
<div class="paragraph"><p>MLton indicates the problematic constructor (<span class="monospaced">B</span>), as well as
the problematic component of the constructor&#8217;s argument.</p></div>
<div class="sect2">
<h3 id="_recursive_datatypes">Recursive datatypes</h3>
<div class="paragraph"><p>A recursive datatype like</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>introduces a new problem, since in order to decide whether <span class="monospaced">t</span>
admits equality, we need to know for the <span class="monospaced">B</span> <a href="Variant">variant</a> whether
<span class="monospaced">t</span> admits equality.  The <a href="DefinitionOfStandardML">Definition</a>
answers this question by requiring a type constructor to admit
equality if it is consistent to do so.  So, in our above example, if
we assume that <span class="monospaced">t</span> admits equality, then the <a href="Variant">variant</a>
<span class="monospaced">B of int * t</span> admits equality.  Then, since the <span class="monospaced">A</span> <a href="Variant">variant</a>
trivially admits equality, so does the type constructor <span class="monospaced">t</span>.
Thus, it was consistent to assume that <span class="monospaced">t</span> admits equality, and
so, <span class="monospaced">t</span> does admit equality.</p></div>
<div class="paragraph"><p>On the other hand, in the following declaration</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>if we assume that <span class="monospaced">t</span> admits equality, then the <span class="monospaced">B</span> <a href="Variant">variant</a>
does not admit equality.  Hence, the type constructor <span class="monospaced">t</span> does not
admit equality, and our assumption was inconsistent.  Hence, <span class="monospaced">t</span>
does not admit equality.</p></div>
<div class="paragraph"><p>The same kind of reasoning applies to mutually recursive datatypes as
well.  For example, the following defines both <span class="monospaced">t</span> and <span class="monospaced">u</span> to
admit equality.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">u</span><span class="w"></span>
<span class="k">and</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">C</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">D</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>But the following defines neither <span class="monospaced">t</span> nor <span class="monospaced">u</span> to admit
equality.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">real</span><span class="w"></span>
<span class="k">and</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">C</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">D</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>As always, we can check whether a type admits equality using an
<span class="monospaced">eqtype</span> specification.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span></span><span class="k">structure</span><span class="w"> </span><span class="n">Bad</span><span class="p">:</span><span class="w"> </span><span class="k">sig</span><span class="w"> </span><span class="k">eqtype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">eqtype</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w">   </span><span class="k">struct</span><span class="w"></span>
<span class="w">      </span><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">real</span><span class="w"></span>
<span class="w">      </span><span class="k">and</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">C</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">D</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
<span class="w">   </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>MLton reports the following error.</p></div>
<div class="listingblock">
<div class="content monospaced">
<pre>Error: z.sml 1.16-1.40.
  Type in structure disagrees with signature (admits equality): t.
    structure: datatype t = B of [_str.u] * [real] | ...
    defn at: z.sml 3.16-3.16
    signature: [eqtype] t
    spec at: z.sml 1.27-1.27
Error: z.sml 1.16-1.40.
  Type in structure disagrees with signature (admits equality): u.
    structure: datatype u = D of [_str.t] | ...
    defn at: z.sml 4.11-4.11
    signature: [eqtype] u
    spec at: z.sml 1.36-1.36</pre>
</div></div>
</div>
</div>
</div>
</div>
<div id="footnotes"><hr></div>
<div id="footer">
<div id="footer-text">
</div>
<div id="footer-badges">
</div>
</div>
</body>
</html>
