<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.26">
<title>SMLNJDeviations</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<link rel="stylesheet" href="./asciidoctor.css">
<link rel="stylesheet" href="./mlton.css">

</head>
<body class="article">
<div id="mlton-header">
<div id="mlton-header-text">
<h2>
<a href="./Home">
MLton
20241230+git20251029+dfsg-5
</a>
</h2>
</div>
</div>
<div id="header">
<h1>SMLNJDeviations</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Here are some deviations of <a href="SMLNJ">SML/NJ</a> from
<a href="DefinitionOfStandardML">The Definition of Standard ML (Revised)</a>.
Some of these are documented in the
<a href="http://www.smlnj.org/doc/Conversion/index.html">SML '97 Conversion Guide</a>.
Since MLton does not deviate from the Definition, you should look here
if you are having trouble porting a program from MLton to SML/NJ or
vice versa.  If you discover other deviations of SML/NJ that aren&#8217;t
listed here, please send mail to
<a href="mailto:MLton-devel@mlton.org"><code>MLton-devel@mlton.org</code></a>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>SML/NJ allows spaces in long identifiers, as in <code>S . x</code>.  Section
2.5 of the Definition implies that <code>S . x</code> should be treated as three
separate lexical items.</p>
</li>
<li>
<p>SML/NJ allows <code>op</code> to appear in <code>val</code> specifications:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature FOO = sig
   val op + : int * int -&gt; int
end</code></pre>
</div>
</div>
<div class="paragraph">
<p>The grammar on page 14 of the Definition does not allow it. Recent
versions of SML/NJ do give a warning.</p>
</div>
</li>
<li>
<p>SML/NJ rejects</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">(op *)</code></pre>
</div>
</div>
<div class="paragraph">
<p>as an unmatched close comment.</p>
</div>
</li>
<li>
<p>SML/NJ allows <code>=</code> to be rebound by the declaration:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">val op = = 13</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is explicitly forbidden on page 5 of the Definition. Recent
versions of SML/NJ do give a warning.</p>
</div>
</li>
<li>
<p>SML/NJ allows rebinding <code>true</code>, <code>false</code>, <code>nil</code>, <code>::</code>, and <code>ref</code> by
the declarations:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">fun true () = ()
fun false () = ()
fun nil () = ()
fun op :: () = ()
fun ref () = ()</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is explicitly forbidden on page 9 of the Definition.</p>
</div>
</li>
<li>
<p>SML/NJ extends the syntax of the language to allow vector
expressions and patterns like the following:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">val v = #[1,2,3]
val #[x,y,z] = v</code></pre>
</div>
</div>
<div class="paragraph">
<p>MLton supports vector expressions and patterns with the <a href="SuccessorML#VectorExpsAndPats"><code>allowVectorExpsAndPats</code></a> <a href="MLBasisAnnotations">ML Basis annotation</a>.</p>
</div>
</li>
<li>
<p>SML/NJ extends the syntax of the language to allow <em>or patterns</em>
like the following:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">datatype foo = Foo of int | Bar of int
val (Foo x | Bar x) = Foo 13</code></pre>
</div>
</div>
<div class="paragraph">
<p>MLton supports or patterns with the <a href="SuccessorML#OrPats"><code>allowOrPats</code></a> <a href="MLBasisAnnotations">ML Basis annotation</a>.</p>
</div>
</li>
<li>
<p>SML/NJ allows higher-order functors, that is, functors can be
components of structures and can be passed as functor arguments and
returned as functor results.  As a consequence, SML/NJ allows
abbreviated functor definitions, as in the following:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature S =
  sig
    type t
    val x: t
  end
functor F (structure A: S): S =
  struct
    type t = A.t * A.t
    val x = (A.x, A.x)
  end
functor G = F</code></pre>
</div>
</div>
</li>
<li>
<p>SML/NJ extends the syntax of the language to allow <code>functor</code> and
<code>signature</code> declarations to occur within the scope of <code>local</code> and
<code>structure</code> declarations.</p>
</li>
<li>
<p>SML/NJ allows duplicate type specifications in signatures when the
duplicates are introduced by <code>include</code>, as in the following:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature SIG1 =
   sig
      type t
      type u
   end
signature SIG2 =
   sig
      type t
      type v
   end
signature SIG =
   sig
      include SIG1
      include SIG2
   end</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is disallowed by rule 77 of the Definition.</p>
</div>
</li>
<li>
<p>SML/NJ allows sharing constraints between type abbreviations in
signatures, as in the following:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature SIG =
   sig
      type t = int * int
      type u = int * int
      sharing type t = u
   end</code></pre>
</div>
</div>
<div class="paragraph">
<p>These are disallowed by rule 78 of the Definition.  Recent versions of
SML/NJ correctly disallow sharing constraints between type
abbreviations in signatures.</p>
</div>
</li>
<li>
<p>SML/NJ disallows multiple <code>where type</code> specifications of the same
type name, as in the following</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature S =
  sig
     type t
     type u = t
  end
  where type u = int</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is allowed by rule 64 of the Definition.</p>
</div>
</li>
<li>
<p>SML/NJ allows <code>and</code> in <code>sharing</code> specs in signatures, as in</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature S =
   sig
      type t
      type u
      type v
      sharing type t = u
      and type u = v
   end</code></pre>
</div>
</div>
</li>
<li>
<p>SML/NJ does not expand the <code>withtype</code> derived form as described by
the Definition.  According to page 55 of the Definition, the type
bindings of a <code>withtype</code> declaration are substituted simultaneously in
the connected datatype.  Consider the following program.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">type u = real ;
datatype a =
    A of t
  | B of u
withtype u = int
and t = u</code></pre>
</div>
</div>
<div class="paragraph">
<p>According to the Definition, it should be expanded to the following.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">type u = real ;
datatype a =
    A of u
  | B of int ;
type u = int
and t = u</code></pre>
</div>
</div>
<div class="paragraph">
<p>However, SML/NJ expands <code>withtype</code> bindings sequentially, meaning that
earlier bindings are expanded within later ones. Hence, the above
program is expanded to the following.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">type u = real ;
datatype a =
    A of int
  | B of int ;
type u = int
type t = int</code></pre>
</div>
</div>
</li>
<li>
<p>SML/NJ allows <code>withtype</code> specifications in signatures.</p>
<div class="paragraph">
<p>MLton supports <code>withtype</code> specifications in signatures with the <a href="SuccessorML#SigWithtype"><code>allowSigWithtype</code></a> <a href="MLBasisAnnotations">ML Basis annotation</a>.</p>
</div>
</li>
<li>
<p>SML/NJ allows a <code>where</code> structure specification that is similar to a
<code>where type</code> specification.  For example:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">structure S = struct type t = int end
signature SIG =
  sig
     structure T : sig type t end
  end where T = S</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is equivalent to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">structure S = struct type t = int end
signature SIG =
  sig
     structure T : sig type t end
  end where type T.t = S.t</code></pre>
</div>
</div>
<div class="paragraph">
<p>SML/NJ also allows a definitional structure specification that is
similar to a definitional type specification.  For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">structure S = struct type t = int end
signature SIG =
  sig
     structure T : sig type t end = S
  end</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is equivalent to the previous examples and to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">structure S = struct type t = int end
signature SIG =
  sig
     structure T : sig type t end where type t = S.t
  end</code></pre>
</div>
</div>
</li>
<li>
<p>SML/NJ disallows binding non-datatypes with datatype replication.
For example, it rejects the following program that should be allowed
according to the Definition.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">type ('a, 'b) t = 'a * 'b
datatype u = datatype t</code></pre>
</div>
</div>
<div class="paragraph">
<p>This idiom can be useful when one wants to rename a type without
rewriting all the type arguments.  For example, the above would have
to be written in SML/NJ as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">type ('a, 'b) t = 'a * 'b
type ('a, 'b) u = ('a, 'b) t</code></pre>
</div>
</div>
</li>
<li>
<p>SML/NJ disallows sharing a structure with one of its substructures.
For example, SML/NJ disallows the following.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">signature SIG =
   sig
      structure S:
         sig
            type t
            structure T: sig type t end
         end
      sharing S = S.T
   end</code></pre>
</div>
</div>
<div class="paragraph">
<p>This signature is allowed by the Definition.</p>
</div>
</li>
<li>
<p>SML/NJ disallows polymorphic generalization of refutable
patterns. For example, SML/NJ disallows the following.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">val [x] = [[]]
val _ = (1 :: x, "one" :: x)</code></pre>
</div>
</div>
<div class="paragraph">
<p>Recent versions of SML/NJ correctly allow polymorphic generalization
of refutable patterns.</p>
</div>
</li>
<li>
<p>SML/NJ uses an overly restrictive context for type inference.  For
example, SML/NJ rejects both of the following.</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">structure S =
struct
  val z = (fn x =&gt; x) []
  val y = z :: [true] :: nil
end</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">structure S : sig val z : bool list end =
struct
  val z = (fn x =&gt; x) []
end</code></pre>
</div>
</div>
<div class="paragraph">
<p>These structures are allowed by the Definition.</p>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_deviations_from_the_basis_library_specification">Deviations from the Basis Library Specification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Here are some deviations of SML/NJ from the <a href="BasisLibrary">Basis Library</a>
<a href="https://smlfamily.github.io/Basis">specification</a>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>SML/NJ exposes the equality of the <code>vector</code> type in structures such
as <code>Word8Vector</code> that abstractly match <code>MONO_VECTOR</code>, which says
<code>type vector</code>, not <code>eqtype vector</code>.  So, for example, SML/NJ accepts
the following program:</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">fun f (v: Word8Vector.vector) = v = v</code></pre>
</div>
</div>
</li>
<li>
<p>SML/NJ exposes the equality property of the type <code>status</code> in
<code>OS.Process</code>. This means that programs which directly compare two
values of type <code>status</code> will work with SML/NJ but not MLton.</p>
</li>
<li>
<p>Under SML/NJ on Windows, <code>OS.Path.validVolume</code> incorrectly considers
absolute empty volumes to be valid. In other words, when the
expression</p>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">OS.Path.validVolume { isAbs = true, vol = "" }</code></pre>
</div>
</div>
<div class="paragraph">
<p>is evaluated by SML/NJ on Windows, the result is <code>true</code>.  MLton, on
the other hand, correctly follows the Basis Library Specification,
which states that on Windows, <code>OS.Path.validVolume</code> should return
<code>false</code> whenever <code>isAbs = true</code> and <code>vol = ""</code>.</p>
</div>
<div class="paragraph">
<p>This incorrect behavior causes other <code>OS.Path</code> functions to behave
differently. For example, when the expression</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="sml">OS.Path.toString (OS.Path.fromString "\\usr\\local")</code></pre>
</div>
</div>
<div class="paragraph">
<p>is evaluated by SML/NJ on Windows, the result is <code>"\\usr\\local"</code>,
whereas under MLton on Windows, evaluating this expression (correctly)
causes an <code>OS.Path.Path</code> exception to be raised.</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>