1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
<!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>GenerativeException</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 20130715</a>
</div>
</div>
<div id="header">
<h1>GenerativeException</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>In <a href="StandardML">Standard ML</a>, exception declarations are said to be
<em>generative</em>, because each time an exception declaration is evaluated,
it yields a new exception.</p></div>
<div class="paragraph"><p>The following program demonstrates the generativity of exceptions.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">exception</span><span class="w"> </span><span class="n">E</span><span class="w"></span>
<span class="k">val</span><span class="w"> </span><span class="n">e1</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">E</span><span class="w"></span>
<span class="k">fun</span><span class="w"> </span><span class="n">isE1</span><span class="w"> </span><span class="p">(</span><span class="n">e</span><span class="p">:</span><span class="w"> </span><span class="n">exn</span><span class="p">):</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="k">of</span><span class="w"></span>
<span class="w"> </span><span class="n">E</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="p">_</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">false</span><span class="w"></span>
<span class="k">exception</span><span class="w"> </span><span class="n">E</span><span class="w"></span>
<span class="k">val</span><span class="w"> </span><span class="n">e2</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">E</span><span class="w"></span>
<span class="k">fun</span><span class="w"> </span><span class="n">isE2</span><span class="w"> </span><span class="p">(</span><span class="n">e</span><span class="p">:</span><span class="w"> </span><span class="n">exn</span><span class="p">):</span><span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="k">of</span><span class="w"></span>
<span class="w"> </span><span class="n">E</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="p">_</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">false</span><span class="w"></span>
<span class="k">fun</span><span class="w"> </span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="p">:</span><span class="w"> </span><span class="n">bool</span><span class="p">):</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="p">(</span><span class="n">concat</span><span class="w"> </span><span class="p">[</span><span class="n">Bool</span><span class="p">.</span><span class="n">toString</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">])</span><span class="w"></span>
<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="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE1</span><span class="w"> </span><span class="n">e1</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">;</span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE1</span><span class="w"> </span><span class="n">e2</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE2</span><span class="w"> </span><span class="n">e1</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE2</span><span class="w"> </span><span class="n">e2</span><span class="p">))</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>In the above program, two different exception declarations declare an
exception <span class="monospaced">E</span> and a corresponding function that returns <span class="monospaced">true</span> only on
that exception. Although declared by syntactically identical
exception declarations, <span class="monospaced">e1</span> and <span class="monospaced">e2</span> are different exceptions. The
program, when run, prints <span class="monospaced">true</span>, <span class="monospaced">false</span>, <span class="monospaced">false</span>, <span class="monospaced">true</span>.</p></div>
<div class="paragraph"><p>A slight modification of the above program shows that even a single
exception declaration yields a new exception each time it is
evaluated.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><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="n">exn</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="p">(</span><span class="n">exn</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">bool</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">exception</span><span class="w"> </span><span class="n">E</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="n">E</span><span class="p">,</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">true</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">false</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
<span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">e1</span><span class="p">,</span><span class="w"> </span><span class="n">isE1</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">e2</span><span class="p">,</span><span class="w"> </span><span class="n">isE2</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</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">pb</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="p">:</span><span class="w"> </span><span class="n">bool</span><span class="p">):</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="p">(</span><span class="n">concat</span><span class="w"> </span><span class="p">[</span><span class="n">Bool</span><span class="p">.</span><span class="n">toString</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">])</span><span class="w"></span>
<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="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE1</span><span class="w"> </span><span class="n">e1</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE1</span><span class="w"> </span><span class="n">e2</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE2</span><span class="w"> </span><span class="n">e1</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">pb</span><span class="w"> </span><span class="p">(</span><span class="n">isE2</span><span class="w"> </span><span class="n">e2</span><span class="p">))</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>Each call to <span class="monospaced">f</span> yields a new exception and a function that returns
<span class="monospaced">true</span> only on that exception. The program, when run, prints <span class="monospaced">true</span>,
<span class="monospaced">false</span>, <span class="monospaced">false</span>, <span class="monospaced">true</span>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_type_safety">Type Safety</h2>
<div class="sectionbody">
<div class="paragraph"><p>Exception generativity is required for type safety. Consider the
following valid SML program.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><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="n">'a</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">exn</span><span class="p">)</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="p">(</span><span class="n">exn</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">'a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">exception</span><span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">'a</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="p">(</span><span class="n">E</span><span class="p">,</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">E</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><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">raise</span><span class="w"> </span><span class="n">Fail</span><span class="w"> </span><span class="s">"f"</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
<span class="k">fun</span><span class="w"> </span><span class="n">cast</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="n">'a</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="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">make</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">exn</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">f</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">(_,</span><span class="w"> </span><span class="n">get</span><span class="p">:</span><span class="w"> </span><span class="n">exn</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">'b</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="n">get</span><span class="w"> </span><span class="p">(</span><span class="n">make</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
<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="n">cast</span><span class="w"> </span><span class="mi">13</span><span class="p">):</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="p">)</span><span class="w"> </span><span class="mi">14</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>If exceptions weren’t generative, then each call <span class="monospaced">f ()</span> would yield
the same exception constructor <span class="monospaced">E</span>. Then, our <span class="monospaced">cast</span> function could
use <span class="monospaced">make: 'a -> exn</span> to convert any value into an exception and then
<span class="monospaced">get: exn -> 'b</span> to convert that exception to a value of arbitrary
type. If <span class="monospaced">cast</span> worked, then we could cast an integer as a function
and apply. Of course, because of generative exceptions, this program
raises <span class="monospaced">Fail "f"</span>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_applications">Applications</h2>
<div class="sectionbody">
<div class="paragraph"><p>The <span class="monospaced">exn</span> type is effectively a <a href="UniversalType">universal type</a>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_also_see">Also see</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
<a href="GenerativeDatatype">GenerativeDatatype</a>
</p>
</li>
</ul></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>
|