<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="generator" content="AsciiDoc 8.6.8"> <title>StandardMLGotchas</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(2); /*]]>*/ </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 20130715</a> </div> </div> <div id="header"> <h1>StandardMLGotchas</h1> <div id="toc"> <div id="toctitle">Table of Contents</div> <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript> </div> </div> <div id="content"> <div id="preamble"> <div class="sectionbody"> <div class="paragraph"><p>This page contains brief explanations of some recurring sources of confusion and problems that SML newbies encounter.</p></div> <div class="paragraph"><p>Many confusions about the syntax of SML seem to arise from the use of an interactive REPL (Read-Eval Print Loop) while trying to learn the basics of the language. While writing your first SML programs, you should keep the source code of your programs in a form that is accepted by an SML compiler as a whole.</p></div> </div> </div> <div class="sect1"> <h2 id="_the_span_class_monospaced_and_span_keyword">The <span class="monospaced">and</span> keyword</h2> <div class="sectionbody"> <div class="paragraph"><p>It is a common mistake to misuse the <span class="monospaced">and</span> keyword or to not know how to introduce mutually recursive definitions. The purpose of the <span class="monospaced">and</span> keyword is to introduce mutually recursive definitions of functions and datatypes. For example,</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">isEven</span><span class="w"> </span><span class="mi">0w0</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">true</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">isEven</span><span class="w"> </span><span class="mi">0w1</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">false</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">isEven</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">isOdd</span><span class="w"> </span><span class="p">(</span><span class="n">n-</span><span class="mi">0w1</span><span class="p">)</span><span class="w"></span> <span class="k">and</span><span class="w"> </span><span class="n">isOdd</span><span class="w"> </span><span class="mi">0w0</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">false</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">isOdd</span><span class="w"> </span><span class="mi">0w1</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">true</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">isOdd</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">isEven</span><span class="w"> </span><span class="p">(</span><span class="n">n-</span><span class="mi">0w1</span><span class="p">)</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>and</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">datatype</span><span class="w"> </span><span class="n">decl</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">VAL</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">pat</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">expr</span><span class="w"></span> <span class="w"> </span><span class="cm">(* | ... *)</span><span class="w"></span> <span class="w"> </span><span class="k">and</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">LET</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">decl</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">expr</span><span class="w"></span> <span class="w"> </span><span class="cm">(* | ... *)</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>You can also use <span class="monospaced">and</span> as a shorthand in a couple of other places, but it is not necessary.</p></div> </div> </div> <div class="sect1"> <h2 id="_constructed_patterns">Constructed patterns</h2> <div class="sectionbody"> <div class="paragraph"><p>It is a common mistake to forget to parenthesize constructed patterns in <span class="monospaced">fun</span> bindings. Consider the following invalid definition:</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="n">nil</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="n">::</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">+</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="n">t</span><span class="w"></span> </pre></div></div></div> <div class="dlist"><dl> <dt class="hdlist1"> The pattern `h </dt> <dd> <p> t` needs to be parenthesized: </p> </dd> </dl></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="n">nil</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">0</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="p">(</span><span class="n">h</span><span class="w"> </span><span class="n">::</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">+</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="n">t</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>The parentheses are needed, because a <span class="monospaced">fun</span> definition may have multiple consecutive constructed patterns through currying.</p></div> <div class="paragraph"><p>The same applies to nonfix constructors. For example, the parentheses in</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">valOf</span><span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">raise</span><span class="w"> </span><span class="n">Option</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">valOf</span><span class="w"> </span><span class="p">(</span><span class="n">SOME</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">x</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>are required. However, the outermost constructed pattern in a <span class="monospaced">fn</span> or <span class="monospaced">case</span> expression need not be parenthesized, because in those cases there is always just one constructed pattern. So, both</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">valOf</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="k">raise</span><span class="w"> </span><span class="n">Option</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>and</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">valOf</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">of</span><span class="w"></span> <span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="k">raise</span><span class="w"> </span><span class="n">Option</span><span class="w"></span> <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>are fine.</p></div> </div> </div> <div class="sect1"> <h2 id="_declarations_and_expressions">Declarations and expressions</h2> <div class="sectionbody"> <div class="paragraph"><p>It is a common mistake to confuse expressions and declarations. Normally an SML source file should only contain declarations. The following are declarations:</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">datatype</span><span class="w"> </span><span class="n">dt</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">fun</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">functor</span><span class="w"> </span><span class="n">Fn</span><span class="w"> </span><span class="p">(...)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">infix</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">infixr</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">local</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="k">end</span><span class="w"></span> <span class="k">nonfix</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">open</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">signature</span><span class="w"> </span><span class="n">SIG</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">...</span><span class="w"></span> <span class="k">structure</span><span class="w"> </span><span class="n">Struct</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">...</span><span class="w"></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="p">...</span><span class="w"></span> <span class="k">val</span><span class="w"> </span><span class="n">v</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>Note that</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">let</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="k">end</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>isn’t a declaration.</p></div> <div class="paragraph"><p>To specify a side-effecting computation in a source file, you can write:</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="p">()</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> </div> <div class="sect1"> <h2 id="_equality_types">Equality types</h2> <div class="sectionbody"> <div class="paragraph"><p>SML has a fairly intricate built-in notion of equality. See <a href="EqualityType">EqualityType</a> and <a href="EqualityTypeVariable">EqualityTypeVariable</a> for a thorough discussion.</p></div> </div> </div> <div class="sect1"> <h2 id="_nested_cases">Nested cases</h2> <div class="sectionbody"> <div class="paragraph"><p>It is a common mistake to write nested case expressions without the necessary parentheses. See <a href="UnresolvedBugs">UnresolvedBugs</a> for a discussion.</p></div> </div> </div> <div class="sect1"> <h2 id="_op">(op *)</h2> <div class="sectionbody"> <div class="paragraph"><p>It used to be a common mistake to parenthesize <span class="monospaced">op *</span> as <span class="monospaced">(op *)</span>. Before SML’97, <span class="monospaced">*)</span> was considered a comment terminator in SML and caused a syntax error. At the time of writing, <a href="SMLNJ">SML/NJ</a> still rejects the code. An extra space may be used for portability: <span class="monospaced">(op * )</span>. However, parenthesizing <span class="monospaced">op</span> is redundant, even though it is a widely used convention.</p></div> </div> </div> <div class="sect1"> <h2 id="_overloading">Overloading</h2> <div class="sectionbody"> <div class="paragraph"><p>A number of standard operators (<span class="monospaced">+</span>, <span class="monospaced">-</span>, <span class="monospaced">~</span>, <span class="monospaced">*</span>, <span class="monospaced"><</span>, <span class="monospaced">></span>, …) and numeric constants are overloaded for some of the numeric types (<span class="monospaced">int</span>, <span class="monospaced">real</span>, <span class="monospaced">word</span>). It is a common surprise that definitions using overloaded operators such as</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">min</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n"><</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="n">x</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>are not overloaded themselves. SML doesn’t really support (user-defined) overloading or other forms of ad hoc polymorphism. In cases such as the above where the context doesn’t resolve the overloading, expressions using overloaded operators or constants get assigned a default type. The above definition gets the type</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">min</span><span class="w"> </span><span class="p">:</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">int</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">int</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>See <a href="Overloading">Overloading</a> and <a href="TypeIndexedValues">TypeIndexedValues</a> for further discussion.</p></div> </div> </div> <div class="sect1"> <h2 id="_semicolons">Semicolons</h2> <div class="sectionbody"> <div class="paragraph"><p>It is a common mistake to use redundant semicolons in SML code. This is probably caused by the fact that in an SML REPL, a semicolon (and enter) is used to signal the REPL that it should evaluate the preceding chunk of code as a unit. In SML source files, semicolons are really needed in only two places. Namely, in expressions of the form</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="p">(</span><span class="n">exp</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">exp</span><span class="p">)</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>and</p></div> <div class="listingblock"> <div class="content"><div class="highlight"><pre><span class="k">let</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">exp</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">exp</span><span class="w"> </span><span class="k">end</span><span class="w"></span> </pre></div></div></div> <div class="paragraph"><p>Note that semicolons act as expression (or declaration) separators rather than as terminators.</p></div> </div> </div> <div class="sect1"> <h2 id="_stale_bindings">Stale bindings</h2> <div class="sectionbody"> <div class="paragraph"><p></p></div> </div> </div> <div class="sect1"> <h2 id="_unresolved_records">Unresolved records</h2> <div class="sectionbody"> <div class="paragraph"><p></p></div> </div> </div> <div class="sect1"> <h2 id="_value_restriction">Value restriction</h2> <div class="sectionbody"> <div class="paragraph"><p>See <a href="ValueRestriction">ValueRestriction</a>.</p></div> </div> </div> <div class="sect1"> <h2 id="_type_variable_scope">Type Variable Scope</h2> <div class="sectionbody"> <div class="paragraph"><p>See <a href="TypeVariableScope">TypeVariableScope</a>.</p></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>