6003 lines
278 KiB
HTML
6003 lines
278 KiB
HTML
|
<?xml version="1.0" encoding="iso-8859-1" ?>
|
||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
<!--http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd-->
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||
|
>
|
||
|
<head><title>4 Declarations and Bindings</title>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||
|
<meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)" />
|
||
|
<meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/)" />
|
||
|
<!-- 2,html,xhtml -->
|
||
|
<meta name="src" content="haskell.tex" />
|
||
|
<meta name="date" content="2010-07-20 13:11:00" />
|
||
|
<link rel="stylesheet" type="text/css" href="haskell.css" />
|
||
|
</head><body
|
||
|
>
|
||
|
<!--l. 7--><div class="crosslinks"><p class="noindent">[<a
|
||
|
href="haskellch5.html" >next</a>] [<a
|
||
|
href="haskellch3.html" >prev</a>] [<a
|
||
|
href="haskellch3.html#tailhaskellch3.html" >prev-tail</a>] [<a
|
||
|
href="#tailhaskellch4.html">tail</a>] [<a
|
||
|
href="haskellpa1.html#haskellch4.html" >up</a>] </p></div>
|
||
|
<h2 class="chapterHead"><span class="titlemark">Chapter 4</span><br /><a
|
||
|
id="x10-620004"></a>Declarations and Bindings</h2> <a
|
||
|
id="dx10-62001"></a><a
|
||
|
id="dx10-62002"></a>
|
||
|
<p class="noindent"> In this chapter, we describe the syntax and informal semantics of Haskell <span
|
||
|
class="ptmri7t-">declarations</span>.
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-59" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-59-1g"><col
|
||
|
id="TBL-59-1" /><col
|
||
|
id="TBL-59-2" /><col
|
||
|
id="TBL-59-3" /><col
|
||
|
id="TBL-59-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">module </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">module</span><span
|
||
|
class="cmmi-10"> modid</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">exports</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> body </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-2-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-2-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">body </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-3-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">body </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-3-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-3-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> impdecls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> topdecls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-4-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-4-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> impdecls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-5-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-5-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-5-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> topdecls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-6-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-7-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-8-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-8-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-8-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> topdecl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-8-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-9-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-9-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-9-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">type</span><span
|
||
|
class="cmmi-10"> simpletype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> type </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-10-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-10-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-10-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-10-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">data</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">context</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> simpletype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> constrs</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">deriving</span><span
|
||
|
class="cmr-10">]</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-11-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-11-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-11-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-11-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">newtype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">context</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> simpletype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> newconstr</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">deriving</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-12-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-12-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-12-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-12-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">class</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">scontext</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> tycls</span><span
|
||
|
class="cmmi-10"> tyvar</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> cdecls</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-13-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-13-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-13-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-13-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">instance</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">scontext</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> qtycls</span><span
|
||
|
class="cmmi-10"> inst</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> idecls</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-14-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-14-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-14-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-14-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">default</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">type</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> type</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-14-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-">  </span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-15-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-15-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-15-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-15-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">foreign</span><span
|
||
|
class="cmmi-10"> fdecl </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-16-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-16-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-16-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-16-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">decl </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-17-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-17-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-18-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-18-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-19-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-19-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">decls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-19-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-19-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> decl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> decl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-19-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-20-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-20-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">decl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-20-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-20-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gendecl </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-21-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-21-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-21-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-21-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">pat</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> rhs</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-22-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-22-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-23-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-23-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-24-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-24-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">cdecls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-24-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-24-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> cdecl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> cdecl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-24-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-25-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-25-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">cdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-25-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-25-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gendecl </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-26-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-26-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-26-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-26-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> var</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> rhs </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-27-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-27-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-28-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-28-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-29-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-29-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">idecls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-29-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-29-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> idecl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> idecl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-29-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-30-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-30-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">idecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-30-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-30-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> var</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> rhs </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-31-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-31-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-31-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-31-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-31-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>empty<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-32-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-32-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-33-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-33-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-34-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-34-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gendecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-34-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-34-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">vars</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">context</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> type </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-59-34-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>type signature<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-35-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-35-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-35-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-35-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">fixity</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">integer</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> ops </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-59-35-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>fixity declaration<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-36-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-36-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-59-36-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-36-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-36-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>empty declaration<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-37-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-37-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-38-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-38-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-39-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-39-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">ops </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-39-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-39-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">op</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> op</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-39-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-40-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-40-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">vars </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-40-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-40-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">var</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> var</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-40-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-59-41-"><td style="white-space:nowrap; text-align:left;" id="TBL-59-41-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">fixity </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-59-41-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-59-41-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">infixl</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">infixr</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">infix</span> </td>
|
||
|
</tr></table></div></div>
|
||
|
|
||
|
|
||
|
|
||
|
<a
|
||
|
id="dx10-62003"></a>
|
||
|
<a
|
||
|
id="dx10-62004"></a>
|
||
|
<a
|
||
|
id="dx10-62005"></a>
|
||
|
<a
|
||
|
id="dx10-62006"></a>
|
||
|
<a
|
||
|
id="dx10-62007"></a>
|
||
|
<a
|
||
|
id="dx10-62008"></a>
|
||
|
<a
|
||
|
id="dx10-62009"></a>
|
||
|
<a
|
||
|
id="dx10-62010"></a>
|
||
|
<a
|
||
|
id="dx10-62011"></a>
|
||
|
<a
|
||
|
id="dx10-62012"></a>
|
||
|
<a
|
||
|
id="dx10-62013"></a>
|
||
|
<a
|
||
|
id="dx10-62014"></a>
|
||
|
<a
|
||
|
id="dx10-62015"></a>
|
||
|
<p class="noindent"> The declarations in the syntactic category <span
|
||
|
class="cmmi-10">topdecls</span> are only allowed at the top level of a Haskell module (see
|
||
|
Chapter <a
|
||
|
href="haskellch5.html#x11-980005">5<!--tex4ht:ref: modules --></a>), whereas <span
|
||
|
class="cmmi-10">decls</span> may be used either at the top level or in nested scopes (i.e. those within a <span
|
||
|
class="pcrr7t-">let</span> or <span
|
||
|
class="pcrr7t-">where</span>
|
||
|
construct).
|
||
|
<p class="noindent"> For exposition, we divide the declarations into three groups: user-defined datatypes, consisting of <span
|
||
|
class="pcrr7t-">type</span>, <span
|
||
|
class="pcrr7t-">newtype</span>,
|
||
|
and <span
|
||
|
class="pcrr7t-">data</span> declarations (Section <a
|
||
|
href="#x10-680004.2">4.2<!--tex4ht:ref: user-defined-datatypes --></a>); type classes and overloading, consisting of <span
|
||
|
class="pcrr7t-">class</span>, <span
|
||
|
class="pcrr7t-">instance</span>, and
|
||
|
<span
|
||
|
class="pcrr7t-">default</span> declarations (Section <a
|
||
|
href="#x10-750004.3">4.3<!--tex4ht:ref: overloading --></a>); and nested declarations, consisting of value bindings, type signatures, and
|
||
|
fixity declarations (Section <a
|
||
|
href="#x10-800004.4">4.4<!--tex4ht:ref: nested --></a>).
|
||
|
<p class="noindent"> Haskell has several primitive datatypes that are “hard-wired” (such as integers and floating-point numbers), but most
|
||
|
“built-in” datatypes are defined with normal Haskell code, using normal <span
|
||
|
class="pcrr7t-">type</span> and <span
|
||
|
class="pcrr7t-">data</span> declarations. These
|
||
|
“built-in” datatypes are described in detail in Section <a
|
||
|
href="haskellch6.html#x13-1170006.1">6.1<!--tex4ht:ref: basic-types --></a>.
|
||
|
<h3 class="sectionHead"><span class="titlemark">4.1 </span> <a
|
||
|
id="x10-630004.1"></a>Overview of Types and Classes</h3>
|
||
|
<p class="noindent"> Haskell uses a traditional Hindley-Milner<a
|
||
|
id="dx10-63001"></a> polymorphic type system to provide a static type semantics <span class="cite">[<a
|
||
|
href="haskellli3.html#Xdamas-milner82">4</a>, <a
|
||
|
href="haskellli3.html#Xhindley69">6</a>]</span>, but the
|
||
|
type system has been extended with <span
|
||
|
class="ptmri7t-">type classes </span>(or just <span
|
||
|
class="ptmri7t-">classes</span><a
|
||
|
id="dx10-63002"></a>) that provide a structured way to introduce
|
||
|
<span
|
||
|
class="ptmri7t-">overloaded </span>functions.<a
|
||
|
id="dx10-63003"></a> <a
|
||
|
id="dx10-63004"></a><a
|
||
|
id="dx10-63005"></a>
|
||
|
<p class="noindent"> A <span
|
||
|
class="pcrr7t-">class</span> declaration (Section <a
|
||
|
href="#x10-760004.3.1">4.3.1<!--tex4ht:ref: class-decls --></a>) introduces a new <span
|
||
|
class="ptmri7t-">type class </span>and the overloaded operations that must be
|
||
|
supported by any type that is an instance of that class. An <span
|
||
|
class="pcrr7t-">instance</span> declaration (Section <a
|
||
|
href="#x10-770004.3.2">4.3.2<!--tex4ht:ref: instance-decls --></a>) declares that a type
|
||
|
is an <span
|
||
|
class="ptmri7t-">instance </span>of a class and includes the definitions of the overloaded operations—called <span
|
||
|
class="ptmri7t-">class methods</span>—instantiated
|
||
|
on the named type. <a
|
||
|
id="dx10-63006"></a>
|
||
|
<p class="noindent"> For example, suppose we wish to overload the operations <span
|
||
|
class="pcrr7t-">(+)</span> and <span
|
||
|
class="pcrr7t-">negate</span> on types <span
|
||
|
class="pcrr7t-">Int</span> and <span
|
||
|
class="pcrr7t-">Float</span>. We
|
||
|
introduce a new type class called <span
|
||
|
class="pcrr7t-">Num</span>:
|
||
|
<p class="noindent">
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-25">
|
||
|
  class Num a  where          -- simplified class declaration for Num
|
||
|
 <br />    (+)    :: a -> a -> a     -- (Num is defined in the Prelude)
|
||
|
 <br />    negate :: a -> a
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> This declaration may be read “a type <span
|
||
|
class="pcrr7t-">a</span> is an instance of the class <span
|
||
|
class="pcrr7t-">Num</span> if there are class methods <span
|
||
|
class="pcrr7t-">(+)</span> and <span
|
||
|
class="pcrr7t-">negate</span>,
|
||
|
of the given types, defined on it.”
|
||
|
<p class="noindent"> We may then declare <span
|
||
|
class="pcrr7t-">Int</span> and <span
|
||
|
class="pcrr7t-">Float</span> to be instances of this class:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-26">
|
||
|
  instance Num Int  where     -- simplified instance of Num Int
|
||
|
 <br />    x + y       =  addInt x y
|
||
|
 <br />    negate x    =  negateInt x
|
||
|
 <br />
|
||
|
 <br />  instance Num Float  where   -- simplified instance of Num Float
|
||
|
 <br />    x + y       =  addFloat x y
|
||
|
 <br />    negate x    =  negateFloat x
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> where <span
|
||
|
class="pcrr7t-">addInt</span>, <span
|
||
|
class="pcrr7t-">negateInt</span>, <span
|
||
|
class="pcrr7t-">addFloat</span>, and <span
|
||
|
class="pcrr7t-">negateFloat</span> are assumed in this case to be primitive
|
||
|
functions, but in general could be any user-defined function. The first declaration above may be read
|
||
|
“<span
|
||
|
class="pcrr7t-">Int</span> is an instance of the class <span
|
||
|
class="pcrr7t-">Num</span> as witnessed by these definitions (i.e. class methods)<a
|
||
|
id="dx10-63007"></a> for <span
|
||
|
class="pcrr7t-">(+)</span> and
|
||
|
<span
|
||
|
class="pcrr7t-">negate</span>.”
|
||
|
<p class="noindent"> More examples of type classes can be found in the papers by Jones <span class="cite">[<a
|
||
|
href="haskellli3.html#Xjones:cclasses">8</a>]</span> or Wadler and Blott <span class="cite">[<a
|
||
|
href="haskellli3.html#Xwadler:classes">13</a>]</span>. The term ‘type
|
||
|
class’ was used to describe the original Haskell 1.0 type system; ‘constructor class’ was used to describe an extension
|
||
|
to the original type classes. There is no longer any reason to use two different terms: in this report,
|
||
|
‘type class’ includes both the original Haskell type classes and the constructor classes introduced by
|
||
|
Jones.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.1.1 </span> <a
|
||
|
id="x10-640004.1.1"></a>Kinds</h4>
|
||
|
<p class="noindent"> To ensure that they are valid, type expressions are classified into different <span
|
||
|
class="ptmri7t-">kinds</span>, <a
|
||
|
id="dx10-64001"></a>which take one of two possible
|
||
|
forms:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize">The symbol <span
|
||
|
class="cmsy-10">∗ </span>represents the kind of all nullary type constructors.
|
||
|
</li>
|
||
|
<li class="itemize">If <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub> and <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">2</span></sub> are kinds, then <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub> <span
|
||
|
class="cmsy-10">→ </span><span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">2</span></sub> is the kind of types that take a type of kind <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub> and return a type
|
||
|
of kind <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">2</span></sub>.</li></ul>
|
||
|
<p class="noindent"> Kind inference checks the validity of type expressions in a similar way that type inference checks the validity of
|
||
|
value expressions. However, unlike types, kinds are entirely implicit and are not a visible part of the language. Kind
|
||
|
inference is discussed in Section <a
|
||
|
href="#x10-970004.6">4.6<!--tex4ht:ref: kindinference --></a>.
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.1.2 </span> <a
|
||
|
id="x10-650004.1.2"></a>Syntax of Types</h4>
|
||
|
<a
|
||
|
id="dx10-65001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-60" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-60-1g"><col
|
||
|
id="TBL-60-1" /><col
|
||
|
id="TBL-60-2" /><col
|
||
|
id="TBL-60-3" /><col
|
||
|
id="TBL-60-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">type </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-60-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-1-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">btype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="cmmi-10"> type</span><span
|
||
|
class="cmr-10">] </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-60-1-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>function type<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-2-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-3-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-4-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">btype </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-60-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">btype</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> atype </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-60-4-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>type application<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-5-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-6-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-7-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">atype </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-60-7-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-7-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gtycon </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-8-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-8-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-8-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">tyvar </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-9-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-9-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-9-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> type</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> type</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-9-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>tuple type<span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">2) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-10-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-10-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-10-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-10-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">[</span><span
|
||
|
class="cmmi-10"> type</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">]</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-10-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>list type<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-11-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-11-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-11-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-11-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> type</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-11-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>parenthesised constructor<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-12-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-12-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-13-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-13-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-14-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-14-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gtycon </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-60-14-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-14-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">qtycon </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-15-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-15-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-15-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-15-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">()</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-15-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>unit type<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-16-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-16-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-16-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-16-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">[]</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-16-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>list constructor<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-17-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-17-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-17-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-17-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(->)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-17-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>function constructor<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-60-18-"><td style="white-space:nowrap; text-align:left;" id="TBL-60-18-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-60-18-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-18-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(,</span><span
|
||
|
class="cmsy-10">{</span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmsy-10">}</span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-60-18-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>tupling constructors<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-65002"></a>
|
||
|
<a
|
||
|
id="dx10-65003"></a>
|
||
|
<a
|
||
|
id="dx10-65004"></a>
|
||
|
<a
|
||
|
id="dx10-65005"></a>
|
||
|
<p class="noindent"> The syntax for Haskell type expressions <a
|
||
|
id="dx10-65006"></a><a
|
||
|
id="dx10-65007"></a> is given above. Just as data values are built using data constructors, type
|
||
|
values are built from <span
|
||
|
class="cmmi-10">type</span><span
|
||
|
class="cmmi-10"> constructors</span>. As with data constructors, the names of type constructors start
|
||
|
with uppercase letters. Unlike data constructors, infix type constructors are not allowed (other than
|
||
|
<span
|
||
|
class="pcrr7t-">(->)</span>).
|
||
|
<p class="noindent"> The main forms of type expression are as follows:
|
||
|
<ol class="enumerate1" >
|
||
|
<li
|
||
|
class="enumerate" id="x10-65009x1">Type variables, written as identifiers beginning with a lowercase letter. The kind of a variable is
|
||
|
determined implicitly by the context in which it appears.
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-65011x2">Type constructors. Most type constructors are written as an identifier beginning with an uppercase letter. For
|
||
|
example:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize"><span
|
||
|
class="pcrr7t-">Char</span>, <span
|
||
|
class="pcrr7t-">Int</span>, <span
|
||
|
class="pcrr7t-">Integer</span>, <span
|
||
|
class="pcrr7t-">Float</span>, <span
|
||
|
class="pcrr7t-">Double</span> and <span
|
||
|
class="pcrr7t-">Bool</span> are type constants with kind <span
|
||
|
class="cmsy-10">∗</span>.
|
||
|
</li>
|
||
|
<li class="itemize"><span
|
||
|
class="pcrr7t-">Maybe</span> and <span
|
||
|
class="pcrr7t-">IO</span> are unary type constructors, and treated as types with kind <span
|
||
|
class="cmsy-10">∗→∗</span>.
|
||
|
</li>
|
||
|
<li class="itemize">The declarations <span
|
||
|
class="pcrr7t-">data</span><span
|
||
|
class="pcrr7t-"> T</span><span
|
||
|
class="pcrr7t-"> ...</span> or <span
|
||
|
class="pcrr7t-">newtype</span><span
|
||
|
class="pcrr7t-"> T</span><span
|
||
|
class="pcrr7t-"> ...</span> add the type constructor <span
|
||
|
class="pcrr7t-">T</span> to the type
|
||
|
vocabulary. The kind of <span
|
||
|
class="pcrr7t-">T</span> is determined by kind inference.</li></ul>
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent"> Special syntax is provided for certain built-in type constructors:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize">The <span
|
||
|
class="ptmri7t-">trivial type</span><a
|
||
|
id="dx10-65012"></a> is written as <span
|
||
|
class="pcrr7t-">()</span> and has kind <span
|
||
|
class="cmsy-10">∗</span>. It denotes the “nullary tuple” type, and has exactly
|
||
|
one value, also written <span
|
||
|
class="pcrr7t-">()</span> (see Sections <a
|
||
|
href="haskellch3.html#x8-380003.9">3.9<!--tex4ht:ref: unit-expression --></a> and <a
|
||
|
href="haskellch6.html#x13-1220006.1.5">6.1.5<!--tex4ht:ref: basic-trivial --></a>).
|
||
|
</li>
|
||
|
<li class="itemize">The <span
|
||
|
class="ptmri7t-">function type </span>is written as <span
|
||
|
class="pcrr7t-">(->)</span> and has<a
|
||
|
id="dx10-65013"></a> kind <span
|
||
|
class="cmsy-10">∗→∗→∗</span>.
|
||
|
</li>
|
||
|
<li class="itemize">The <span
|
||
|
class="ptmri7t-">list type </span>is written as <span
|
||
|
class="pcrr7t-">[]</span> and has kind <span
|
||
|
class="cmsy-10">∗→∗</span>.<a
|
||
|
id="dx10-65014"></a>
|
||
|
</li>
|
||
|
<li class="itemize">The <span
|
||
|
class="ptmri7t-">tuple types </span>are written as <span
|
||
|
class="pcrr7t-">(,)</span>,<a
|
||
|
id="dx10-65015"></a> <span
|
||
|
class="pcrr7t-">(,,)</span>, and so on. Their kinds are <span
|
||
|
class="cmsy-10">∗→∗→∗</span>, <span
|
||
|
class="cmsy-10">∗→∗→∗→</span>
|
||
|
<span
|
||
|
class="cmsy-10">∗</span>, and so on.</li></ul>
|
||
|
<p class="noindent"> Use of the <span
|
||
|
class="pcrr7t-">(->)</span> and <span
|
||
|
class="pcrr7t-">[]</span> constants is described in more detail below.
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-65017x3">Type application. If <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub> is a type of kind <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub> <span
|
||
|
class="cmsy-10">→ </span><span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">2</span></sub> and <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">2</span></sub> is a type of kind <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub>, then <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">2</span></sub> is a type expression of
|
||
|
kind <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">2</span></sub>.
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-65019x4">A <span
|
||
|
class="ptmri7t-">parenthesized type</span>, having form <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">t</span><span
|
||
|
class="pcrr7t-">)</span>, is identical to the type <span
|
||
|
class="cmmi-10">t</span>.
|
||
|
</li></ol>
|
||
|
<p class="noindent"> For example, the type expression <span
|
||
|
class="pcrr7t-">IO</span><span
|
||
|
class="pcrr7t-"> a</span> can be understood as the application of a constant, <span
|
||
|
class="pcrr7t-">IO</span>, to the variable <span
|
||
|
class="pcrr7t-">a</span>.
|
||
|
Since the <span
|
||
|
class="pcrr7t-">IO</span> type constructor has kind <span
|
||
|
class="cmsy-10">∗→∗</span>, it follows that both the variable <span
|
||
|
class="pcrr7t-">a</span> and the whole expression, <span
|
||
|
class="pcrr7t-">IO</span><span
|
||
|
class="pcrr7t-"> a</span>,
|
||
|
must have kind <span
|
||
|
class="cmsy-10">∗</span>. In general, a process of <span
|
||
|
class="ptmri7t-">kind inference</span><a
|
||
|
id="dx10-65020"></a><a
|
||
|
id="dx10-65021"></a> (see Section <a
|
||
|
href="#x10-970004.6">4.6<!--tex4ht:ref: kindinference --></a>) is needed to determine appropriate kinds
|
||
|
for user-defined datatypes, type synonyms, and classes.
|
||
|
<p class="noindent"> Special syntax is provided to allow certain type expressions to be written in a more traditional style:
|
||
|
<ol class="enumerate1" >
|
||
|
<li
|
||
|
class="enumerate" id="x10-65023x1">A <span
|
||
|
class="ptmri7t-">function type</span><a
|
||
|
id="dx10-65024"></a> has the form <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">2</span></sub>, which is equivalent to the type <span
|
||
|
class="pcrr7t-">(->)</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">2</span></sub>.
|
||
|
Function arrows associate to the right. For example, <span
|
||
|
class="pcrr7t-">Int</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> Int</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> Float</span> means
|
||
|
<span
|
||
|
class="pcrr7t-">Int</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> (Int</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> Float)</span>.
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-65026x2">A <span
|
||
|
class="ptmri7t-">tuple type</span><a
|
||
|
id="dx10-65027"></a> has the form <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="pcrr7t-">)</span> where <span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">2</span>, which is equivalent to the type
|
||
|
<span
|
||
|
class="pcrr7t-">(,</span>…<span
|
||
|
class="pcrr7t-">,)</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> where there are <span
|
||
|
class="cmmi-10">k</span><span
|
||
|
class="cmsy-10">−</span><span
|
||
|
class="cmr-10">1 </span>commas between the parenthesis. It denotes the type of <span
|
||
|
class="cmmi-10">k</span>-tuples
|
||
|
with the first component of type <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub>, the second component of type <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">2</span></sub>, and so on (see Sections <a
|
||
|
href="haskellch3.html#x8-360003.8">3.8<!--tex4ht:ref: tuples --></a> and
|
||
|
<a
|
||
|
href="haskellch6.html#x13-1210006.1.4">6.1.4<!--tex4ht:ref: basic-tuples --></a>).
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-65029x3">A <span
|
||
|
class="ptmri7t-">list type</span><a
|
||
|
id="dx10-65030"></a> has the form <span
|
||
|
class="pcrr7t-">[</span><span
|
||
|
class="cmmi-10">t</span><span
|
||
|
class="pcrr7t-">]</span>, which is equivalent to the type <span
|
||
|
class="pcrr7t-">[]</span><span
|
||
|
class="cmmi-10"> t</span>. It denotes the type of lists with
|
||
|
elements of type <span
|
||
|
class="cmmi-10">t</span> (see Sections <a
|
||
|
href="haskellch3.html#x8-340003.7">3.7<!--tex4ht:ref: lists --></a> and <a
|
||
|
href="haskellch6.html#x13-1200006.1.3">6.1.3<!--tex4ht:ref: basic-lists --></a>).
|
||
|
</li></ol>
|
||
|
<p class="noindent"> These special syntactic forms always denote the built-in type constructors for functions, tuples, and lists, regardless
|
||
|
of what is in scope. In a similar way, the prefix type constructors <span
|
||
|
class="pcrr7t-">(->)</span>, <span
|
||
|
class="pcrr7t-">[]</span>, <span
|
||
|
class="pcrr7t-">()</span>, <span
|
||
|
class="pcrr7t-">(,)</span>, and so on, always denote the
|
||
|
built-in type constructors; they cannot be qualified, nor mentioned in import or export lists (Chapter <a
|
||
|
href="haskellch5.html#x11-980005">5<!--tex4ht:ref: modules --></a>). (Hence the
|
||
|
special production, “gtycon”, above.)
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent"> Although the list and tuple types have special syntax, their semantics is the same as the equivalent user-defined
|
||
|
algebraic data types.
|
||
|
<p class="noindent"> Notice that expressions and types have a consistent syntax. If <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is the type of expression or pattern <span
|
||
|
class="cmmi-10">e</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>, then
|
||
|
the expressions <span
|
||
|
class="pcrr7t-">(\</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="pcrr7t-">)</span>, <span
|
||
|
class="pcrr7t-">[</span><span
|
||
|
class="cmmi-10">e</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="pcrr7t-">]</span>, and <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">e</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,e</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="pcrr7t-">)</span> have the types <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="pcrr7t-">)</span>, <span
|
||
|
class="pcrr7t-">[</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="pcrr7t-">]</span>, and <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,t</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="pcrr7t-">)</span>,
|
||
|
respectively.
|
||
|
<a
|
||
|
id="dx10-65031"></a>
|
||
|
<p class="noindent"> With one exception (that of the distinguished type variable in a class declaration (Section <a
|
||
|
href="#x10-760004.3.1">4.3.1<!--tex4ht:ref: class-decls --></a>)), the type variables
|
||
|
in a Haskell type expression are all assumed to be universally quantified; there is no explicit syntax for universal
|
||
|
quantification <span class="cite">[<a
|
||
|
href="haskellli3.html#Xdamas-milner82">4</a>]</span>. For example, the type expression <span
|
||
|
class="pcrr7t-">a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> a</span> denotes the type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span>. For clarity, however,
|
||
|
we often write quantification explicitly when discussing the types of Haskell programs. When we write an explicitly
|
||
|
quantified type, the scope of the <span
|
||
|
class="cmsy-10">∀</span> extends as far to the right as possible; for example, <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span> means
|
||
|
<span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmr-10">)</span>.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.1.3 </span> <a
|
||
|
id="x10-660004.1.3"></a>Syntax of Class Assertions and Contexts</h4>
|
||
|
<a
|
||
|
id="dx10-66001"></a>
|
||
|
<a
|
||
|
id="dx10-66002"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-61" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-61-1g"><col
|
||
|
id="TBL-61-1" /><col
|
||
|
id="TBL-61-2" /><col
|
||
|
id="TBL-61-3" /><col
|
||
|
id="TBL-61-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">context </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-61-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-1-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">class </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-2-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-61-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-2-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> class</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> class</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-2-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-3-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">class </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-61-3-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-3-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">qtycls</span><span
|
||
|
class="cmmi-10"> tyvar </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-4-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-61-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">qtycls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> tyvar</span><span
|
||
|
class="cmmi-10"> atype</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> atype</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-4-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-5-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">qtycls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-61-5-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-5-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10"> modid</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> tycls </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-6-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">tycls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-61-6-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-6-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">conid </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-61-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-61-7-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">tyvar </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-61-7-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-61-7-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">varid </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-66003"></a>
|
||
|
<a
|
||
|
id="dx10-66004"></a>
|
||
|
<a
|
||
|
id="dx10-66005"></a>
|
||
|
<a
|
||
|
id="dx10-66006"></a>
|
||
|
<a
|
||
|
id="dx10-66007"></a>
|
||
|
<p class="noindent"> A <span
|
||
|
class="ptmri7t-">class assertion </span>has form <span
|
||
|
class="cmmi-10">qtycls</span><span
|
||
|
class="cmmi-10"> tyvar</span>, and indicates the membership of the type <span
|
||
|
class="cmmi-10">tyvar</span> in the class <span
|
||
|
class="cmmi-10">qtycls</span>. A
|
||
|
class identifier begins with an uppercase letter. A <span
|
||
|
class="ptmri7t-">context </span>consists of zero or more class assertions, and has the general
|
||
|
form
|
||
|
|
||
|
|
||
|
|
||
|
<span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> C</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> C</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span>
|
||
|
where <span
|
||
|
class="cmmi-10">C</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> C</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> are class identifiers, and each of the <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> is either a type variable, or the
|
||
|
application of type variable to one or more types. The outer parentheses may be omitted when <span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmr-10">= 1</span>.
|
||
|
In general, we use <span
|
||
|
class="cmmi-10">cx</span> to denote a context and we write <span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> t</span> to indicate the type <span
|
||
|
class="cmmi-10">t</span> restricted by
|
||
|
the context <span
|
||
|
class="cmmi-10">cx</span>. The context <span
|
||
|
class="cmmi-10">cx</span> must only contain type variables referenced in <span
|
||
|
class="cmmi-10">t</span>. For convenience, we
|
||
|
write <span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> t</span> even if the context <span
|
||
|
class="cmmi-10">cx</span> is empty, although in this case the concrete syntax contains no
|
||
|
<span
|
||
|
class="pcrr7t-">=></span>.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.1.4 </span> <a
|
||
|
id="x10-670004.1.4"></a>Semantics of Types and Classes</h4>
|
||
|
<p class="noindent"> In this section, we provide informal details of the type system. (Wadler and Blott <span class="cite">[<a
|
||
|
href="haskellli3.html#Xwadler:classes">13</a>]</span> and Jones <span class="cite">[<a
|
||
|
href="haskellli3.html#Xjones:cclasses">8</a>]</span> discuss type and
|
||
|
constructor classes, respectively, in more detail.)
|
||
|
<p class="noindent"> The Haskell type system attributes a <span
|
||
|
class="ptmri7t-">type </span>to each <a
|
||
|
id="dx10-67001"></a>expression in the program. In general, a type is of the form
|
||
|
<span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span>, where <span class="overline"><span
|
||
|
class="cmmi-10">u</span></span> is a set of type variables <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">n</span></sub>. In any such type, any of the universally-quantified
|
||
|
type variables <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> that are free in <span
|
||
|
class="cmmi-10">cx</span> must also be free in <span
|
||
|
class="cmmi-10">t</span>. Furthermore, the context <span
|
||
|
class="cmmi-10">cx</span> must be of the form given
|
||
|
above in Section <a
|
||
|
href="#x10-660004.1.3">4.1.3<!--tex4ht:ref: classes&contexts --></a>. For example, here are some valid types:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-27">
|
||
|
  Eq a => a -> a
|
||
|
 <br />  (Eq a, Show a, Eq b) => [a] -> [b] -> String
|
||
|
 <br />  (Eq (f a), Functor f) => (a -> b) -> f a -> f b -> Bool
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> In the third type, the constraint <span
|
||
|
class="pcrr7t-">Eq</span><span
|
||
|
class="pcrr7t-"> (f</span><span
|
||
|
class="pcrr7t-"> a)</span> cannot be made simpler because <span
|
||
|
class="pcrr7t-">f</span> is universally quantified.
|
||
|
<p class="noindent"> The type of an expression <span
|
||
|
class="cmmi-10">e</span> depends on a <span
|
||
|
class="ptmri7t-">type environment</span><a
|
||
|
id="dx10-67002"></a> that gives types for the free variables in <span
|
||
|
class="cmmi-10">e</span>, and a <span
|
||
|
class="ptmri7t-">class</span>
|
||
|
<span
|
||
|
class="ptmri7t-">environment</span><a
|
||
|
id="dx10-67003"></a> that declares which types are instances of which classes (a type becomes an instance of a class only via
|
||
|
the presence of an <span
|
||
|
class="pcrr7t-">instance</span> declaration or a <span
|
||
|
class="pcrr7t-">deriving</span> clause).
|
||
|
<p class="noindent"> Types are related by a generalization preorder <a
|
||
|
id="dx10-67004"></a>(specified below); the most general type, up to the equivalence
|
||
|
induced by the generalization preorder, that can be assigned to a particular expression (in a given environment) is
|
||
|
called its <span
|
||
|
class="ptmri7t-">principal type</span>. <a
|
||
|
id="dx10-67005"></a>Haskell’s extended Hindley-Milner type system can infer the principal type of all
|
||
|
expressions, including the proper use of overloaded class methods (although certain ambiguous overloadings could
|
||
|
arise, as described in Section <a
|
||
|
href="#x10-790004.3.4">4.3.4<!--tex4ht:ref: default-decls --></a>). Therefore, explicit typings (called <span
|
||
|
class="ptmri7t-">type signatures</span>) <a
|
||
|
id="dx10-67006"></a>are usually optional (see
|
||
|
Sections <a
|
||
|
href="haskellch3.html#x8-560003.16">3.16<!--tex4ht:ref: expression-type-sigs --></a> and <a
|
||
|
href="#x10-810004.4.1">4.4.1<!--tex4ht:ref: type-signatures --></a>).
|
||
|
<p class="noindent"> The type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">1</span></sub> is <span
|
||
|
class="ptmri7t-">more general than </span>the type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">w</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">2</span></sub> if and only if there is a substitution <span
|
||
|
class="cmmi-10">S</span>
|
||
|
whose domain is <span class="overline"><span
|
||
|
class="cmmi-10">u</span></span> such that:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize"><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">2</span></sub> is identical to <span
|
||
|
class="cmmi-10">S</span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmr-10">)</span>.
|
||
|
</li>
|
||
|
<li class="itemize">Whenever <span
|
||
|
class="cmmi-10">cx</span><sub><span
|
||
|
class="cmr-7">2</span></sub> holds in the class environment, <span
|
||
|
class="cmmi-10">S</span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">cx</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmr-10">)</span> also holds.</li></ul>
|
||
|
<p class="noindent"> A value of type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span>, may be instantiated at types <span class="overline"><span
|
||
|
class="cmmi-10">s</span></span> if and only if the context <span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmr-10">[</span><span class="overline"><span
|
||
|
class="cmmi-10">s</span></span><span
|
||
|
class="cmmi-10">∕</span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmr-10">]</span> holds. For
|
||
|
example, consider the function <span
|
||
|
class="pcrr7t-">double</span>:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-28">
|
||
|
  double x = x + x
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The most general type of <span
|
||
|
class="pcrr7t-">double</span> is <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span>. <span
|
||
|
class="pcrr7t-">double</span> may be applied to values of type <span
|
||
|
class="pcrr7t-">Int</span>
|
||
|
(instantiating <span
|
||
|
class="cmmi-10">a</span> to <span
|
||
|
class="pcrr7t-">Int</span>), since <span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="pcrr7t-"> Int</span> holds, because <span
|
||
|
class="pcrr7t-">Int</span> is an instance of the class <span
|
||
|
class="pcrr7t-">Num</span>. However, <span
|
||
|
class="pcrr7t-">double</span> may
|
||
|
not normally be applied to values of type <span
|
||
|
class="pcrr7t-">Char</span>, because <span
|
||
|
class="pcrr7t-">Char</span> is not normally an instance of class <span
|
||
|
class="pcrr7t-">Num</span>.
|
||
|
The user may choose to declare such an instance, in which case <span
|
||
|
class="pcrr7t-">double</span> may indeed be applied to a
|
||
|
<span
|
||
|
class="pcrr7t-">Char</span>.
|
||
|
<p class="noindent">
|
||
|
<h3 class="sectionHead"><span class="titlemark">4.2 </span> <a
|
||
|
id="x10-680004.2"></a>User-Defined Datatypes</h3>
|
||
|
<a
|
||
|
id="dx10-68001"></a>
|
||
|
<p class="noindent"> In this section, we describe algebraic datatypes (<span
|
||
|
class="pcrr7t-">data</span> declarations), renamed datatypes (<span
|
||
|
class="pcrr7t-">newtype</span>
|
||
|
declarations), and type synonyms (<span
|
||
|
class="pcrr7t-">type</span> declarations). These declarations may only appear at the top level of a
|
||
|
module.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.2.1 </span> <a
|
||
|
id="x10-690004.2.1"></a>Algebraic Datatype Declarations</h4>
|
||
|
<a
|
||
|
id="dx10-69001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-62" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-62-1g"><col
|
||
|
id="TBL-62-1" /><col
|
||
|
id="TBL-62-2" /><col
|
||
|
id="TBL-62-3" /><col
|
||
|
id="TBL-62-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">data</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">context</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> simpletype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> constrs</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">deriving</span><span
|
||
|
class="cmr-10">]</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-2-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-3-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-4-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">simpletype </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">tycon</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-4-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-5-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-6-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-7-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">constrs </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-7-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-7-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">constr</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> constr</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-7-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-8-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">constr </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-8-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-8-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">con</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> atype</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> atype</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-8-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>arity<span
|
||
|
class="cmmi-10"> con</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmr-10">=</span> <span
|
||
|
class="cmmi-10"> k,</span><span
|
||
|
class="cmmi-10"> k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-9-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-62-9-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-9-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">btype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmmi-10"> atype</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> conop</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">btype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmmi-10"> atype</span><span
|
||
|
class="cmr-10">) </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-62-9-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>infix<span
|
||
|
class="cmmi-10"> conop</span><span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-10-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-10-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-62-10-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-10-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">con</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> fielddecl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> fielddecl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-10-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-11-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-11-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">fielddecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-11-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-11-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">vars</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">type</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmmi-10"> atype</span><span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-12-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-12-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-13-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-13-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-14-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-14-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">deriving </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-14-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-14-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">deriving</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">dclass</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">dclass</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> dclass</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="pcrr7t-">)</span><span
|
||
|
class="cmr-10">) </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-62-14-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-62-15-"><td style="white-space:nowrap; text-align:left;" id="TBL-62-15-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">dclass </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-62-15-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-62-15-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">qtycls </span></td>
|
||
|
</tr></table></div></div>
|
||
|
|
||
|
|
||
|
|
||
|
<a
|
||
|
id="dx10-69002"></a>
|
||
|
<a
|
||
|
id="dx10-69003"></a>
|
||
|
<a
|
||
|
id="dx10-69004"></a>
|
||
|
<a
|
||
|
id="dx10-69005"></a>
|
||
|
<a
|
||
|
id="dx10-69006"></a>
|
||
|
<a
|
||
|
id="dx10-69007"></a>
|
||
|
<a
|
||
|
id="dx10-69008"></a>
|
||
|
<a
|
||
|
id="dx10-69009"></a>
|
||
|
<p class="noindent"> The precedence<a
|
||
|
id="dx10-69010"></a> for <span
|
||
|
class="cmmi-10">constr</span> is the same as that for expressions—normal constructor application has higher
|
||
|
precedence than infix constructor application (thus <span
|
||
|
class="pcrr7t-">a</span><span
|
||
|
class="pcrr7t-"> :</span><span
|
||
|
class="pcrr7t-"> Foo</span><span
|
||
|
class="pcrr7t-"> a</span> parses as <span
|
||
|
class="pcrr7t-">a</span><span
|
||
|
class="pcrr7t-"> :</span><span
|
||
|
class="pcrr7t-"> (Foo</span><span
|
||
|
class="pcrr7t-"> a)</span>).
|
||
|
<p class="noindent"> An algebraic datatype declaration has the form:
|
||
|
<span
|
||
|
class="pcrr7t-">data</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> K</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">11</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">1</span><span
|
||
|
class="cmmi-7">k</span><sub><span
|
||
|
class="cmr-5">1</span></sub></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><img
|
||
|
src="haskell0x.png" alt="⋅⋅⋅" class="cdots" /><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> K</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">n</span><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">nk</span><sub><span
|
||
|
class="cmmi-5">n</span></sub></sub>
|
||
|
where <span
|
||
|
class="cmmi-10">cx</span> is a context. This declaration introduces a new <span
|
||
|
class="ptmri7t-">type constructor</span> <span
|
||
|
class="cmmi-10">T</span> with zero or more constituent
|
||
|
<span
|
||
|
class="ptmri7t-">data constructors</span> <span
|
||
|
class="cmmi-10">K</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> K</span><sub><span
|
||
|
class="cmmi-7">n</span></sub>. <a
|
||
|
id="dx10-69011"></a><a
|
||
|
id="dx10-69012"></a> In this Report, the unqualified term “constructor” always means “data
|
||
|
constructor”.
|
||
|
<p class="noindent"> The types of the data constructors are given by:
|
||
|
<span
|
||
|
class="cmmi-10">K</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmr-10">::</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> cx</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">i</span><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><img
|
||
|
src="haskell1x.png" alt="⋅⋅⋅" class="cdots" /><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">ik</span><sub><span
|
||
|
class="cmmi-5">i</span></sub></sub><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmr-10">)</span>
|
||
|
where <span
|
||
|
class="cmmi-10">cx</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is the largest subset of <span
|
||
|
class="cmmi-10">cx</span> that constrains only those type variables free in the types <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">ik</span><sub><span
|
||
|
class="cmmi-5">i</span></sub></sub>. The type
|
||
|
variables <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmr-7">1</span></sub> through <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> must be distinct and may appear in <span
|
||
|
class="cmmi-10">cx</span> and the <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">ij</span></sub>; it is a static error for any other
|
||
|
type variable to appear in <span
|
||
|
class="cmmi-10">cx</span> or on the right-hand-side. The new type constant <span
|
||
|
class="cmmi-10">T</span> has a kind of the form
|
||
|
<span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub> <span
|
||
|
class="cmsy-10">→</span><span
|
||
|
class="cmmi-10">…</span> <span
|
||
|
class="cmsy-10">→ </span><span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> <span
|
||
|
class="cmsy-10">→∗ </span>where the kinds <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> of the argument variables <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> are determined by kind inference as described
|
||
|
in Section <a
|
||
|
href="#x10-970004.6">4.6<!--tex4ht:ref: kindinference --></a><a
|
||
|
id="dx10-69013"></a><a
|
||
|
id="dx10-69014"></a>. This means that <span
|
||
|
class="cmmi-10">T</span> may be used in type expressions with anywhere between <span
|
||
|
class="cmr-10">0</span> and <span
|
||
|
class="cmmi-10">k</span>
|
||
|
arguments.
|
||
|
<p class="noindent"> For example, the declaration
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-29">
|
||
|
  data Eq a => Set a = NilSet | ConsSet a (Set a)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> introduces a type constructor <span
|
||
|
class="pcrr7t-">Set</span> of kind <span
|
||
|
class="cmsy-10">∗→∗</span>, and constructors <span
|
||
|
class="pcrr7t-">NilSet</span> and <span
|
||
|
class="pcrr7t-">ConsSet</span> with types
|
||
|
<div class="array"> <table id="TBL-63" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-63-1g"><col
|
||
|
id="TBL-63-1" /><col
|
||
|
id="TBL-63-2" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">NilSet</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmr-10">::</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Set</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span> </div></td></tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">ConsSet</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmr-10">::</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Eq</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Set</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Set</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span></div></td>
|
||
|
</tr></table> </div>
|
||
|
In the example given, the overloaded type for <span
|
||
|
class="pcrr7t-">ConsSet</span> ensures that <span
|
||
|
class="pcrr7t-">ConsSet</span> can only be applied to values whose
|
||
|
type is an instance of the class <span
|
||
|
class="pcrr7t-">Eq</span>. Pattern matching against <span
|
||
|
class="pcrr7t-">ConsSet</span> also gives rise to an <span
|
||
|
class="pcrr7t-">Eq</span><span
|
||
|
class="pcrr7t-"> a</span> constraint. For
|
||
|
example:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-30">
|
||
|
  f (ConsSet a s) = a
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> the function <span
|
||
|
class="pcrr7t-">f</span> has inferred type <span
|
||
|
class="pcrr7t-">Eq</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> =></span><span
|
||
|
class="pcrr7t-"> Set</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> a</span>. The context in the <span
|
||
|
class="pcrr7t-">data</span> declaration has no other effect
|
||
|
whatsoever.
|
||
|
<p class="noindent"> The visibility of a datatype’s constructors (i.e. the “abstractness” <a
|
||
|
id="dx10-69015"></a>of the datatype) outside of the module in which the
|
||
|
datatype is defined is controlled by the form of the datatype’s name in the export list as described in
|
||
|
Section <a
|
||
|
href="haskellch5.html#x11-1150005.8">5.8<!--tex4ht:ref: abstract-types --></a>.
|
||
|
<p class="noindent"> The optional <span
|
||
|
class="pcrr7t-">deriving</span> part of a <span
|
||
|
class="pcrr7t-">data</span> declaration has to do with <span
|
||
|
class="ptmri7t-">derived instances</span>, and is described in
|
||
|
Section <a
|
||
|
href="#x10-780004.3.3">4.3.3<!--tex4ht:ref: derived-decls --></a>.
|
||
|
<p class="noindent"> <span class="paragraphHead"><a
|
||
|
id="x10-700004.2.1"></a><span
|
||
|
class="ptmb7t-">Labelled Fields</span></span>
|
||
|
<a
|
||
|
id="dx10-70001"></a>
|
||
|
A data constructor of arity <span
|
||
|
class="cmmi-10">k</span> creates an object with <span
|
||
|
class="cmmi-10">k</span> components. These components are normally accessed
|
||
|
positionally as arguments to the constructor in expressions or patterns. For large datatypes it is useful to assign
|
||
|
<span
|
||
|
class="cmmi-10">field</span><span
|
||
|
class="cmmi-10"> labels</span> to the components of a data object. This allows a specific field to be referenced independently of its
|
||
|
location within the constructor.
|
||
|
<p class="noindent"> A constructor definition in a <span
|
||
|
class="pcrr7t-">data</span> declaration may assign labels to the fields of the constructor, using the record
|
||
|
syntax (<span
|
||
|
class="pcrr7t-">C</span><span
|
||
|
class="pcrr7t-"> {</span><span
|
||
|
class="pcrr7t-"> ...</span><span
|
||
|
class="pcrr7t-"> }</span>). Constructors using field labels may be freely mixed with constructors without them. A
|
||
|
constructor with associated field labels may still be used as an ordinary constructor; features using labels
|
||
|
are simply a shorthand for operations using an underlying positional constructor. The arguments to
|
||
|
the positional constructor occur in the same order as the labeled fields. For example, the declaration
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-31">
|
||
|
  data C = F { f1,f2 :: Int, f3 :: Bool }
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> defines a type and constructor identical to the one produced by
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-32">
|
||
|
  data C = F Int Int Bool
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Operations using field labels are described in Section <a
|
||
|
href="haskellch3.html#x8-490003.15">3.15<!--tex4ht:ref: field-ops --></a>. A <span
|
||
|
class="pcrr7t-">data</span> declaration may use the same field label
|
||
|
in multiple constructors as long as the typing of the field is the same in all cases after type synonym
|
||
|
expansion. A label cannot be shared by more than one type in scope. Field names share the top level
|
||
|
namespace with ordinary variables and class methods and must not conflict with other top level names in
|
||
|
scope.
|
||
|
<p class="noindent"> The pattern <span
|
||
|
class="pcrr7t-">F</span><span
|
||
|
class="pcrr7t-"> {}</span> matches any value built with constructor <span
|
||
|
class="pcrr7t-">F</span>, <span
|
||
|
class="ptmri7t-">whether or not</span> <span
|
||
|
class="pcrr7t-">F</span> <span
|
||
|
class="ptmri7t-">was declared with record</span>
|
||
|
<span
|
||
|
class="ptmri7t-">syntax</span>.
|
||
|
<p class="noindent"> <span class="paragraphHead"><a
|
||
|
id="x10-710004.2.1"></a><span
|
||
|
class="ptmb7t-">Strictness Flags</span></span>
|
||
|
<a
|
||
|
id="dx10-71001"></a>
|
||
|
Whenever a data constructor is applied, each argument to the constructor is evaluated if and only if the corresponding
|
||
|
type in the algebraic datatype declaration has a strictness flag, denoted by an exclamation point, “<span
|
||
|
class="pcrr7t-">!</span>”. <a
|
||
|
id="dx10-71002"></a>Lexically, “<span
|
||
|
class="pcrr7t-">!</span>” is
|
||
|
an ordinary varsym not a <span
|
||
|
class="cmmi-10">reservedop</span>; it has special significance only in the context of the argument types of a data
|
||
|
declaration.
|
||
|
<div class="center"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="fbox"><div class="minipage"><p class="noindent"> <span class="likeparagraphHead"><a
|
||
|
id="x10-720004.2.1"></a>Translation:</span>
|
||
|
A declaration of the form
|
||
|
<span
|
||
|
class="pcrr7t-">data</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> K</span><span
|
||
|
class="cmmi-10"> s</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> s</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span>
|
||
|
where each <span
|
||
|
class="cmmi-10">s</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is either of the form <span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> or <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>, replaces every occurrence of <span
|
||
|
class="cmmi-10">K</span> in an expression by
|
||
|
<span
|
||
|
class="pcrr7t-">(\</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">x</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> x</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">((</span><span
|
||
|
class="cmmi-10">K</span><span
|
||
|
class="cmmi-10"> op</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> x</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> op</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="cmmi-10"> x</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> op</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> x</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmr-10">)</span>
|
||
|
where <span
|
||
|
class="cmmi-10">op</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is the non-strict apply function <span
|
||
|
class="pcrr7t-">$</span> if <span
|
||
|
class="cmmi-10">s</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is of the form <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>, and <span
|
||
|
class="cmmi-10">op</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is the strict apply function
|
||
|
<span
|
||
|
class="pcrr7t-">$!</span> (see Section <a
|
||
|
href="haskellch6.html#x13-1260006.2">6.2<!--tex4ht:ref: strict-eval --></a>) if <span
|
||
|
class="cmmi-10">s</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is of the form <span
|
||
|
class="pcrr7t-">!</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>. Pattern matching on <span
|
||
|
class="cmmi-10">K</span> is not affected by strictness
|
||
|
flags. </div></div>
|
||
|
</div>
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.2.2 </span> <a
|
||
|
id="x10-730004.2.2"></a>Type Synonym Declarations</h4>
|
||
|
<a
|
||
|
id="dx10-73001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-64" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-64-1g"><col
|
||
|
id="TBL-64-1" /><col
|
||
|
id="TBL-64-2" /><col
|
||
|
id="TBL-64-3" /><col
|
||
|
id="TBL-64-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-64-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-64-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-64-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-64-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">type</span><span
|
||
|
class="cmmi-10"> simpletype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> type </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-64-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-64-2-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">simpletype </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-64-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-64-2-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">tycon</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-64-2-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-73002"></a>
|
||
|
<a
|
||
|
id="dx10-73003"></a>
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent"> A type synonym declaration introduces a new type that is equivalent to an old type. It has the form
|
||
|
<span
|
||
|
class="pcrr7t-">type</span><span
|
||
|
class="cmmi-10"> T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> t</span>
|
||
|
which introduces a new type constructor, <span
|
||
|
class="cmmi-10">T</span> . The type <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmr-10">)</span> is equivalent to the type <span
|
||
|
class="cmmi-10">t</span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">∕u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10">∕u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmr-10">]</span>. The
|
||
|
type variables <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmr-7">1</span></sub> through <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> must be distinct and are scoped only over <span
|
||
|
class="cmmi-10">t</span>; it is a static error for any other type variable
|
||
|
to appear in <span
|
||
|
class="cmmi-10">t</span>. The kind of the new type constructor <span
|
||
|
class="cmmi-10">T</span> is of the form <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmr-7">1</span></sub> <span
|
||
|
class="cmsy-10">→</span><span
|
||
|
class="cmmi-10">…</span> <span
|
||
|
class="cmsy-10">→ </span><span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> <span
|
||
|
class="cmsy-10">→ </span><span
|
||
|
class="cmmi-10">κ </span>where the kinds <span
|
||
|
class="cmmi-10">κ</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> of the
|
||
|
arguments <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> and <span
|
||
|
class="cmmi-10">κ</span> of the right hand side <span
|
||
|
class="cmmi-10">t</span> are determined by kind inference as described in Section <a
|
||
|
href="#x10-970004.6">4.6<!--tex4ht:ref: kindinference --></a><a
|
||
|
id="dx10-73004"></a><a
|
||
|
id="dx10-73005"></a>. For
|
||
|
example, the following definition can be used to provide an alternative way of writing the list type constructor:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-33">
|
||
|
  type List = []
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Type constructor symbols <span
|
||
|
class="cmmi-10">T</span> introduced by type synonym declarations cannot be partially applied; it is a static error
|
||
|
to use <span
|
||
|
class="cmmi-10">T</span> without the full number of arguments.
|
||
|
<p class="noindent"> Although recursive and mutually recursive datatypes are allowed, <a
|
||
|
id="dx10-73006"></a><a
|
||
|
id="dx10-73007"></a> this is not so for type synonyms, <span
|
||
|
class="ptmri7t-">unless an</span>
|
||
|
<span
|
||
|
class="ptmri7t-">algebraic datatype intervenes</span>. For example,
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-34">
|
||
|
  type Rec a   =  [Circ a]
|
||
|
 <br />  data Circ a  =  Tag [Rec a]
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> is allowed, whereas
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-35">
|
||
|
  type Rec a   =  [Circ a]        -- invalid
|
||
|
 <br />  type Circ a  =  [Rec a]         -- invalid
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> is not. Similarly, <span
|
||
|
class="pcrr7t-">type</span><span
|
||
|
class="pcrr7t-"> Rec</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> =</span><span
|
||
|
class="pcrr7t-"> [Rec</span><span
|
||
|
class="pcrr7t-"> a]</span> is not allowed.
|
||
|
<p class="noindent"> Type synonyms are a convenient, but strictly syntactic, mechanism to make type signatures more readable. A
|
||
|
synonym and its definition are completely interchangeable, except in the instance type of an <span
|
||
|
class="pcrr7t-">instance</span> declaration
|
||
|
(Section <a
|
||
|
href="#x10-770004.3.2">4.3.2<!--tex4ht:ref: instance-decls --></a>).
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.2.3 </span> <a
|
||
|
id="x10-740004.2.3"></a>Datatype Renamings</h4>
|
||
|
<a
|
||
|
id="dx10-74001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-65" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-65-1g"><col
|
||
|
id="TBL-65-1" /><col
|
||
|
id="TBL-65-2" /><col
|
||
|
id="TBL-65-3" /><col
|
||
|
id="TBL-65-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-65-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-65-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-65-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-65-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">newtype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">context</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> simpletype</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> newconstr</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">deriving</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-65-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-65-2-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">newconstr </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-65-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-65-2-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">con</span><span
|
||
|
class="cmmi-10"> atype </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-65-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-65-3-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-65-3-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-65-3-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">con</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> var</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> type</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-65-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-65-4-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">simpletype </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-65-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-65-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">tycon</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmmi-7">k</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-65-4-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-74002"></a>
|
||
|
<a
|
||
|
id="dx10-74003"></a>
|
||
|
<a
|
||
|
id="dx10-74004"></a>
|
||
|
<p class="noindent"> A declaration of the form
|
||
|
<span
|
||
|
class="pcrr7t-">newtype</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> N</span><span
|
||
|
class="cmmi-10"> t</span>
|
||
|
introduces a new type whose representation is the same as an existing type. The type <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="pcrr7t-">)</span> renames the
|
||
|
|
||
|
|
||
|
|
||
|
datatype <span
|
||
|
class="cmmi-10">t</span>. It differs from a type synonym in that it creates a distinct type that must be explicitly coerced to or from
|
||
|
the original type. Also, unlike type synonyms, <span
|
||
|
class="pcrr7t-">newtype</span> may be used to define recursive types. The constructor <span
|
||
|
class="cmmi-10">N</span> in
|
||
|
an expression coerces a value from type <span
|
||
|
class="cmmi-10">t</span> to type <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="pcrr7t-">)</span>. Using <span
|
||
|
class="cmmi-10">N</span> in a pattern coerces a value from type
|
||
|
<span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="pcrr7t-">)</span> to type <span
|
||
|
class="cmmi-10">t</span>. These coercions may be implemented without execution time overhead; <span
|
||
|
class="pcrr7t-">newtype</span> does not
|
||
|
change the underlying representation of an object.
|
||
|
<p class="noindent"> New instances (see Section <a
|
||
|
href="#x10-770004.3.2">4.3.2<!--tex4ht:ref: instance-decls --></a>) can be defined for a type defined by <span
|
||
|
class="pcrr7t-">newtype</span> but may not be
|
||
|
defined for a type synonym. A type created by <span
|
||
|
class="pcrr7t-">newtype</span> differs from an algebraic datatype in that the
|
||
|
representation of an algebraic datatype has an extra level of indirection. This difference may make access to
|
||
|
the representation less efficient. The difference is reflected in different rules for pattern matching (see
|
||
|
Section <a
|
||
|
href="haskellch3.html#x8-580003.17">3.17<!--tex4ht:ref: pattern-matching --></a>). Unlike algebraic datatypes, the newtype constructor <span
|
||
|
class="cmmi-10">N</span> is <span
|
||
|
class="ptmri7t-">unlifted</span>, so that <span
|
||
|
class="cmmi-10">N</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span> is the same as
|
||
|
<span
|
||
|
class="cmsy-10">⊥</span>.
|
||
|
<p class="noindent"> The following examples clarify the differences between <span
|
||
|
class="pcrr7t-">data</span> (algebraic datatypes), <span
|
||
|
class="pcrr7t-">type</span> (type synonyms), and
|
||
|
<span
|
||
|
class="pcrr7t-">newtype</span> (renaming types.) Given the declarations
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-36">
|
||
|
  data D1 = D1 Int
|
||
|
 <br />  data D2 = D2 !Int
|
||
|
 <br />  type S = Int
|
||
|
 <br />  newtype N = N Int
|
||
|
 <br />  d1 (D1 i) = 42
|
||
|
 <br />  d2 (D2 i) = 42
|
||
|
 <br />  s i = 42
|
||
|
 <br />  n (N i) = 42
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> the expressions <span
|
||
|
class="pcrr7t-">(d1</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">)</span>, <span
|
||
|
class="pcrr7t-">(d2</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">)</span> and <span
|
||
|
class="pcrr7t-">(d2</span><span
|
||
|
class="pcrr7t-"> (D2</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">))</span> are all equivalent to <span
|
||
|
class="cmsy-10">⊥</span>, whereas <span
|
||
|
class="pcrr7t-">(n</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">)</span>, <span
|
||
|
class="pcrr7t-">(n</span><span
|
||
|
class="pcrr7t-"> (N</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">))</span>,
|
||
|
<span
|
||
|
class="pcrr7t-">(d1</span><span
|
||
|
class="pcrr7t-"> (D1</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">))</span> and <span
|
||
|
class="pcrr7t-">(s</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">)</span> are all equivalent to <span
|
||
|
class="pcrr7t-">42</span>. In particular, <span
|
||
|
class="pcrr7t-">(N</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">)</span> is equivalent to <span
|
||
|
class="cmsy-10">⊥</span> while <span
|
||
|
class="pcrr7t-">(D1</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">⊥</span><span
|
||
|
class="pcrr7t-">)</span> is not
|
||
|
equivalent to <span
|
||
|
class="cmsy-10">⊥</span>.
|
||
|
<p class="noindent"> The optional deriving part of a <span
|
||
|
class="pcrr7t-">newtype</span> declaration is treated in the same way as the deriving component of a
|
||
|
<span
|
||
|
class="pcrr7t-">data</span> declaration; see Section <a
|
||
|
href="#x10-780004.3.3">4.3.3<!--tex4ht:ref: derived-decls --></a>.
|
||
|
<p class="noindent"> A <span
|
||
|
class="pcrr7t-">newtype</span> declaration may use field-naming syntax, though of course there may only be one field. Thus:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-37">
|
||
|
  newtype Age = Age { unAge :: Int }
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> brings into scope both a constructor and a de-constructor:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-38">
|
||
|
  Age   :: Int -> Age
|
||
|
 <br />  unAge :: Age -> Int
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent">
|
||
|
<h3 class="sectionHead"><span class="titlemark">4.3 </span> <a
|
||
|
id="x10-750004.3"></a>Type Classes and Overloading</h3>
|
||
|
<a
|
||
|
id="dx10-75001"></a>
|
||
|
<a
|
||
|
id="dx10-75002"></a>
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.3.1 </span> <a
|
||
|
id="x10-760004.3.1"></a>Class Declarations</h4>
|
||
|
<a
|
||
|
id="dx10-76001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-66" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-66-1g"><col
|
||
|
id="TBL-66-1" /><col
|
||
|
id="TBL-66-2" /><col
|
||
|
id="TBL-66-3" /><col
|
||
|
id="TBL-66-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-66-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">class</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">scontext</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> tycls</span><span
|
||
|
class="cmmi-10"> tyvar</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> cdecls</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-2-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">scontext </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-66-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-2-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">simpleclass </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-3-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-66-3-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-3-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> simpleclass</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> simpleclass</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-3-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-4-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">simpleclass </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-66-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">qtycls</span><span
|
||
|
class="cmmi-10"> tyvar </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-5-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">cdecls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-66-5-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-5-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> cdecl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> cdecl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-5-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-6-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">cdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-66-6-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-6-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gendecl </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-66-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-66-7-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-66-7-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-66-7-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> var</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> rhs </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-76002"></a>
|
||
|
<a
|
||
|
id="dx10-76003"></a>
|
||
|
<a
|
||
|
id="dx10-76004"></a>
|
||
|
<a
|
||
|
id="dx10-76005"></a>
|
||
|
<a
|
||
|
id="dx10-76006"></a>
|
||
|
<p class="noindent"> A <span
|
||
|
class="ptmri7t-">class declaration </span>introduces a new class and the operations (<span
|
||
|
class="ptmri7t-">class methods</span>) on it. A class declaration has the
|
||
|
general form:
|
||
|
|
||
|
|
||
|
|
||
|
<div class="array"> <table id="TBL-67" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-67-1g"><col
|
||
|
id="TBL-67-1" /><col
|
||
|
id="TBL-67-2" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:right;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">class</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> C</span><span
|
||
|
class="cmmi-10"> u</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> cdecls</span> </div></td>
|
||
|
</tr></table> </div>
|
||
|
This introduces a new class name <span
|
||
|
class="cmmi-10">C</span>; the type variable <span
|
||
|
class="cmmi-10">u</span> is scoped only over the class method signatures in the class
|
||
|
body. The context <span
|
||
|
class="cmmi-10">cx</span> specifies the superclasses<a
|
||
|
id="dx10-76007"></a> of <span
|
||
|
class="cmmi-10">C</span>, as described below; the only type variable that may be referred
|
||
|
to in <span
|
||
|
class="cmmi-10">cx</span> is <span
|
||
|
class="cmmi-10">u</span>.
|
||
|
<p class="noindent"> The superclass relation must not be cyclic; i.e. it must form a directed acyclic graph.<a
|
||
|
id="dx10-76008"></a>
|
||
|
<p class="noindent"> The <span
|
||
|
class="cmmi-10">cdecls</span> part of a <span
|
||
|
class="pcrr7t-">class</span> declaration contains three kinds of declarations:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize">The class declaration introduces new <span
|
||
|
class="ptmri7t-">class methods</span> <a
|
||
|
id="dx10-76009"></a><span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>, whose scope extends outside the <span
|
||
|
class="pcrr7t-">class</span>
|
||
|
declaration. The class methods of a class declaration are precisely the <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> for which there is an explicit
|
||
|
type signature
|
||
|
<span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> cx</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>
|
||
|
in <span
|
||
|
class="cmmi-10">cdecls</span>. Class methods share the top level namespace with variable bindings and field names; they
|
||
|
must not conflict with other top level bindings in scope. That is, a class method can not have the same
|
||
|
name as a top level definition, a field name, or another class method.
|
||
|
<p class="noindent"> The type of the top-level class method <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is:
|
||
|
<span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> <span
|
||
|
class="cmr-10">:: </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10">u,</span><span class="overline"><span
|
||
|
class="cmmi-10">w</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">Cu,cx</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmr-10">) </span><span
|
||
|
class="cmsy-10">⇒ </span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>
|
||
|
The <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> must mention <span
|
||
|
class="cmmi-10">u</span>; it may mention type variables <span class="overline"><span
|
||
|
class="cmmi-10">w</span></span> other than <span
|
||
|
class="cmmi-10">u</span>, in which case the type of <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is
|
||
|
polymorphic in both <span
|
||
|
class="cmmi-10">u</span> and <span class="overline"><span
|
||
|
class="cmmi-10">w</span></span>. The <span
|
||
|
class="cmmi-10">cx</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> may constrain only <span class="overline"><span
|
||
|
class="cmmi-10">w</span></span>; in particular, the <span
|
||
|
class="cmmi-10">cx</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> may not constrain <span
|
||
|
class="cmmi-10">u</span>. For
|
||
|
example:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-39">
|
||
|
  class Foo a where
|
||
|
 <br />    op :: Num b => a -> b -> a
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Here the type of <span
|
||
|
class="pcrr7t-">op</span> is <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a,</span><span
|
||
|
class="cmmi-10"> b.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="pcrr7t-">Foo</span><span
|
||
|
class="cmmi-10"> a,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="cmmi-10"> b</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> b</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span>.
|
||
|
</li>
|
||
|
<li class="itemize">The <span
|
||
|
class="cmmi-10">cdecls</span> may also contain a <span
|
||
|
class="ptmri7t-">fixity declaration </span>for any of the class methods (but for no other values).
|
||
|
<a
|
||
|
id="dx10-76010"></a>However, since class methods declare top-level values, the fixity declaration for a class method may
|
||
|
alternatively appear at top level, outside the class declaration.
|
||
|
</li>
|
||
|
<li class="itemize">Lastly, the <span
|
||
|
class="cmmi-10">cdecls</span> may contain a <span
|
||
|
class="ptmri7t-">default class method</span> <a
|
||
|
id="dx10-76011"></a>for any of the <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub>. The default class method for <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is used
|
||
|
if no binding for it is given in a particular <span
|
||
|
class="pcrr7t-">instance</span> declaration (see Section <a
|
||
|
href="#x10-770004.3.2">4.3.2<!--tex4ht:ref: instance-decls --></a>). The default method
|
||
|
declaration is a normal value definition, except that the left hand side may only be a variable or function
|
||
|
definition. For example:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-40">
|
||
|
  class Foo a where
|
||
|
 <br />    op1, op2 :: a -> a
|
||
|
 <br />    (op1, op2) = ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> is not permitted, because the left hand side of the default declaration is a pattern.</li></ul>
|
||
|
<p class="noindent"> Other than these cases, no other declarations are permitted in <span
|
||
|
class="cmmi-10">cdecls</span>.
|
||
|
<p class="noindent"> A <span
|
||
|
class="pcrr7t-">class</span> declaration with no <span
|
||
|
class="pcrr7t-">where</span> part <a
|
||
|
id="dx10-76012"></a>may be useful for combining a collection of classes into a larger one that
|
||
|
inherits all of the class methods in the original ones. For example:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-41">
|
||
|
  class  (Read a, Show a) => Textual a
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> In such a case, if a type is an instance of all superclasses,<a
|
||
|
id="dx10-76013"></a> it is not <span
|
||
|
class="ptmri7t-">automatically </span>an instance of the subclass, even
|
||
|
though the subclass has no immediate class methods. The <span
|
||
|
class="pcrr7t-">instance</span> declaration must be given explicitly with no
|
||
|
<span
|
||
|
class="pcrr7t-">where</span> part. <a
|
||
|
id="dx10-76014"></a>
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.3.2 </span> <a
|
||
|
id="x10-770004.3.2"></a>Instance Declarations</h4>
|
||
|
<a
|
||
|
id="dx10-77001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-68" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-68-1g"><col
|
||
|
id="TBL-68-1" /><col
|
||
|
id="TBL-68-2" /><col
|
||
|
id="TBL-68-3" /><col
|
||
|
id="TBL-68-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-68-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">instance</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">scontext</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> qtycls</span><span
|
||
|
class="cmmi-10"> inst</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> idecls</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-2-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">inst </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-68-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-2-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gtycon </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-3-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-68-3-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-3-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> gtycon</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-3-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> tyvars</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> distinct</span><span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-4-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-68-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-4-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-4-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">2</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> tyvars</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> distinct</span><span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-5-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-68-5-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-5-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">[</span><span
|
||
|
class="cmmi-10"> tyvar</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">]</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-6-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-68-6-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-6-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-6-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">tyvar</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> and</span><span
|
||
|
class="cmmi-10"> tyvar</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> distinct</span><span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-7-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">idecls </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-68-7-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-7-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> idecl</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">;</span><span
|
||
|
class="cmmi-10"> idecl</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-7-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-8-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">idecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-68-8-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-8-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> var</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> rhs </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-68-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-68-9-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-68-9-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-9-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-68-9-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">empty</span><span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-77002"></a>
|
||
|
<a
|
||
|
id="dx10-77003"></a>
|
||
|
<a
|
||
|
id="dx10-77004"></a>
|
||
|
<a
|
||
|
id="dx10-77005"></a>
|
||
|
<a
|
||
|
id="dx10-77006"></a>
|
||
|
<a
|
||
|
id="dx10-77007"></a>
|
||
|
<a
|
||
|
id="dx10-77008"></a>
|
||
|
<p class="noindent"> An <span
|
||
|
class="ptmri7t-">instance declaration </span>introduces an instance of a class. Let
|
||
|
|
||
|
|
||
|
|
||
|
<span
|
||
|
class="pcrr7t-">class</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> C</span><span
|
||
|
class="cmmi-10"> u</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> cbody</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span>
|
||
|
be a <span
|
||
|
class="pcrr7t-">class</span> declaration. The general form of the corresponding instance declaration is:
|
||
|
<span
|
||
|
class="pcrr7t-">instance</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmsy-10">′</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> C</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">{</span><span
|
||
|
class="cmmi-10"> d</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span>
|
||
|
where <span
|
||
|
class="cmmi-10">k </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0</span>. The type <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmr-10">)</span> must take the form of a type constructor <span
|
||
|
class="cmmi-10">T</span> applied to simple type variables
|
||
|
<span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub>; furthermore, <span
|
||
|
class="cmmi-10">T</span> must not be a type synonym<a
|
||
|
id="dx10-77009"></a>, and the <span
|
||
|
class="cmmi-10">u</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> must all be distinct.
|
||
|
<p class="noindent"> This prohibits instance declarations such as:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-42">
|
||
|
  instance C (a,a) where ...
|
||
|
 <br />  instance C (Int,a) where ...
|
||
|
 <br />  instance C [[a]] where ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The declarations <span
|
||
|
class="cmmi-10">d</span> may contain bindings only for the class methods<a
|
||
|
id="dx10-77010"></a> of <span
|
||
|
class="cmmi-10">C</span>. It is illegal to give a binding for a class
|
||
|
method that is not in scope, but the name under which it is in scope is immaterial; in particular, it may be a qualified
|
||
|
name. (This rule is identical to that used for subordinate names in export lists — Section <a
|
||
|
href="haskellch5.html#x11-1000005.2">5.2<!--tex4ht:ref: export --></a>.) For
|
||
|
example, this is legal, even though <span
|
||
|
class="pcrr7t-">range</span> is in scope only with the qualified name <span
|
||
|
class="pcrr7t-">Data.Ix.range</span>.
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-43">
|
||
|
  module A where
|
||
|
 <br />    import qualified Data.Ix
|
||
|
 <br />
|
||
|
 <br />    instance Data.Ix.Ix T where
|
||
|
 <br />      range = ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The declarations may not contain any type signatures or fixity declarations,<a
|
||
|
id="dx10-77011"></a><a
|
||
|
id="dx10-77012"></a> since these have already been given in
|
||
|
the <span
|
||
|
class="pcrr7t-">class</span> declaration. As in the case of default class methods <a
|
||
|
id="dx10-77013"></a>(Section <a
|
||
|
href="#x10-760004.3.1">4.3.1<!--tex4ht:ref: class-decls --></a>), the method declarations must take the
|
||
|
form of a variable or function definition.
|
||
|
<p class="noindent"> If no binding is given for some class method then the corresponding default class method <a
|
||
|
id="dx10-77014"></a>in the <span
|
||
|
class="pcrr7t-">class</span> declaration
|
||
|
is used (if present); if such a default does not exist then the class method of this instance is bound to <span
|
||
|
class="pcrr7t-">undefined</span>
|
||
|
and no compile-time error results.
|
||
|
<p class="noindent"> An <span
|
||
|
class="pcrr7t-">instance</span> declaration that makes the type <span
|
||
|
class="cmmi-10">T</span> to be an instance of class <span
|
||
|
class="cmmi-10">C</span> is called a <span
|
||
|
class="ptmri7t-">C-T instance declaration</span>
|
||
|
<a
|
||
|
id="dx10-77015"></a>and is subject to these static restrictions:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize">A type may not be declared as an instance of a particular class more than once in the program.
|
||
|
</li>
|
||
|
<li class="itemize">The class and type must have the same kind; this can be determined using kind inference as described
|
||
|
in Section <a
|
||
|
href="#x10-970004.6">4.6<!--tex4ht:ref: kindinference --></a><a
|
||
|
id="dx10-77016"></a><a
|
||
|
id="dx10-77017"></a>.
|
||
|
</li>
|
||
|
<li class="itemize">Assume that the type variables in the instance type <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> u</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmr-10">)</span> satisfy the constraints in the instance context
|
||
|
<span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmsy-10">′</span>. Under this assumption, the following two conditions must also be satisfied:
|
||
|
<ol class="enumerate1" >
|
||
|
<li
|
||
|
class="enumerate" id="x10-77019x1">The constraints expressed by the superclass context <span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmr-10">[(</span><span
|
||
|
class="cmmi-10">T</span><span
|
||
|
class="cmmi-10"> u</span><span
|
||
|
class="cmr-10">1</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> uk</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10">∕u</span><span
|
||
|
class="cmr-10">]</span> of <span
|
||
|
class="cmmi-10">C</span> must be satisfied.
|
||
|
In other words, <span
|
||
|
class="cmmi-10">T</span> must be an instance of each of <span
|
||
|
class="cmmi-10">C</span>’s superclasses and the contexts of all superclass
|
||
|
instances must be implied by <span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmsy-10">′</span>.
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-77021x2">Any constraints on the type variables in the instance type that are required for the class method
|
||
|
declarations in <span
|
||
|
class="cmmi-10">d</span> to be well-typed must also be satisfied.</li></ol>
|
||
|
<p class="noindent"> In fact, except in pathological cases it is possible to infer from the instance declaration the most general
|
||
|
instance context <span
|
||
|
class="cmmi-10">cx</span><span
|
||
|
class="cmsy-10">′</span> satisfying the above two constraints, but it is nevertheless mandatory to write an explicit
|
||
|
instance context.</li></ul>
|
||
|
<p class="noindent"> The following example illustrates the restrictions imposed by superclass instances:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-44">
|
||
|
  class Foo a => Bar a where ...
|
||
|
 <br />
|
||
|
 <br />  instance (Eq a, Show a) => Foo [a] where ...
|
||
|
 <br />
|
||
|
 <br />  instance Num a => Bar [a] where ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> This example is valid Haskell. Since <span
|
||
|
class="pcrr7t-">Foo</span> is a superclass of <span
|
||
|
class="pcrr7t-">Bar</span>, the second instance declaration is only valid if
|
||
|
<span
|
||
|
class="pcrr7t-">[a]</span> is an instance of <span
|
||
|
class="pcrr7t-">Foo</span> under the assumption <span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="pcrr7t-"> a</span>. The first instance declaration does indeed
|
||
|
say that <span
|
||
|
class="pcrr7t-">[a]</span> is an instance of <span
|
||
|
class="pcrr7t-">Foo</span> under this assumption, because <span
|
||
|
class="pcrr7t-">Eq</span> and <span
|
||
|
class="pcrr7t-">Show</span> are superclasses of
|
||
|
<span
|
||
|
class="pcrr7t-">Num</span>.
|
||
|
<p class="noindent"> If the two instance declarations instead read like this:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-45">
|
||
|
  instance Num a => Foo [a] where ...
|
||
|
 <br />
|
||
|
 <br />  instance (Eq a, Show a) => Bar [a] where ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> then the program would be invalid. The second instance declaration is valid only if <span
|
||
|
class="pcrr7t-">[a]</span> is an instance of <span
|
||
|
class="pcrr7t-">Foo</span> under
|
||
|
the assumptions <span
|
||
|
class="pcrr7t-">(Eq</span><span
|
||
|
class="pcrr7t-"> a,</span><span
|
||
|
class="pcrr7t-"> Show</span><span
|
||
|
class="pcrr7t-"> a)</span>. But this does not hold, since <span
|
||
|
class="pcrr7t-">[a]</span> is only an instance of <span
|
||
|
class="pcrr7t-">Foo</span> under the
|
||
|
stronger assumption <span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="pcrr7t-"> a</span>.
|
||
|
<p class="noindent"> Further examples of <span
|
||
|
class="pcrr7t-">instance</span> declarations may be found in Chapter <a
|
||
|
href="haskellch9.html#x16-1710009">9<!--tex4ht:ref: stdprelude --></a>.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.3.3 </span> <a
|
||
|
id="x10-780004.3.3"></a>Derived Instances</h4>
|
||
|
<a
|
||
|
id="dx10-78001"></a>
|
||
|
<p class="noindent"> As mentioned in Section <a
|
||
|
href="#x10-690004.2.1">4.2.1<!--tex4ht:ref: datatype-decls --></a>, <span
|
||
|
class="pcrr7t-">data</span> and <span
|
||
|
class="pcrr7t-">newtype</span> declarations contain an optional <span
|
||
|
class="pcrr7t-">deriving</span> form. If the form
|
||
|
is included, then <span
|
||
|
class="ptmri7t-">derived instance declarations </span>are automatically generated for the datatype in each of the named
|
||
|
classes. These instances are subject to the same restrictions as user-defined instances. When deriving a class <span
|
||
|
class="cmmi-10">C</span> for a
|
||
|
type <span
|
||
|
class="cmmi-10">T</span> , instances for all superclasses of <span
|
||
|
class="cmmi-10">C</span> must exist for <span
|
||
|
class="cmmi-10">T</span> , either via an explicit <span
|
||
|
class="pcrr7t-">instance</span> declaration or by
|
||
|
including the superclass in the <span
|
||
|
class="pcrr7t-">deriving</span> clause.
|
||
|
<p class="noindent"> Derived instances provide convenient commonly-used operations for user-defined datatypes. For example, derived
|
||
|
instances for datatypes in the class <span
|
||
|
class="pcrr7t-">Eq</span> define the operations <span
|
||
|
class="pcrr7t-">==</span> and <span
|
||
|
class="pcrr7t-">/=</span>, freeing the programmer from the need to
|
||
|
define them.
|
||
|
<p class="noindent"> The only classes in the Prelude for which derived instances are allowed are <span
|
||
|
class="pcrr7t-">Eq</span><a
|
||
|
id="dx10-78002"></a>, <span
|
||
|
class="pcrr7t-">Ord</span><a
|
||
|
id="dx10-78003"></a>, <span
|
||
|
class="pcrr7t-">Enum</span><a
|
||
|
id="dx10-78004"></a>, <span
|
||
|
class="pcrr7t-">Bounded</span><a
|
||
|
id="dx10-78005"></a>, <span
|
||
|
class="pcrr7t-">Show</span><a
|
||
|
id="dx10-78006"></a>, and
|
||
|
<span
|
||
|
class="pcrr7t-">Read</span><a
|
||
|
id="dx10-78007"></a>, all mentioned in Figure <a
|
||
|
href="haskellch6.html#x13-1270011">6.1<!--tex4ht:ref: standard-classes --></a>. The precise details of how the derived instances are generated for each of these
|
||
|
classes are provided in Chapter <a
|
||
|
href="haskellch11.html#x18-18200011">11<!--tex4ht:ref: derived-appendix --></a>, including a specification of when such derived instances are possible. Classes
|
||
|
defined by the standard libraries may also be derivable.
|
||
|
<p class="noindent"> A static error results if it is not possible to derive an <span
|
||
|
class="pcrr7t-">instance</span> declaration over a class named in a <span
|
||
|
class="pcrr7t-">deriving</span>
|
||
|
form. For example, not all datatypes can properly support class methods in <span
|
||
|
class="pcrr7t-">Enum</span>.<a
|
||
|
id="dx10-78008"></a> It is also a static error to give an
|
||
|
explicit <span
|
||
|
class="pcrr7t-">instance</span> declaration for a class that is also derived.
|
||
|
<p class="noindent"> If the <span
|
||
|
class="pcrr7t-">deriving</span> form is omitted from a <span
|
||
|
class="pcrr7t-">data</span> or <span
|
||
|
class="pcrr7t-">newtype</span> declaration, then <span
|
||
|
class="ptmri7t-">no </span>instance declarations are derived
|
||
|
for that datatype; that is, omitting a <span
|
||
|
class="pcrr7t-">deriving</span> form is equivalent to including an empty deriving form:
|
||
|
<span
|
||
|
class="pcrr7t-">deriving</span><span
|
||
|
class="pcrr7t-"> ()</span>.
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.3.4 </span> <a
|
||
|
id="x10-790004.3.4"></a>Ambiguous Types, and Defaults for Overloaded Numeric Operations</h4>
|
||
|
<a
|
||
|
id="dx10-79001"></a>
|
||
|
<a
|
||
|
id="dx10-79002"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-69" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-69-1g"><col
|
||
|
id="TBL-69-1" /><col
|
||
|
id="TBL-69-2" /><col
|
||
|
id="TBL-69-3" /><col
|
||
|
id="TBL-69-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-69-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-69-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">topdecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-69-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-69-1-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">default</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">type</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> type</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="pcrr7t-">)</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-69-1-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0) </span></td>
|
||
|
</tr></table>
|
||
|
</div></div>
|
||
|
<a
|
||
|
id="dx10-79003"></a>
|
||
|
<p class="noindent"> A problem inherent with Haskell-style overloading is the possibility of an <span
|
||
|
class="ptmri7t-">ambiguous type</span>. <a
|
||
|
id="dx10-79004"></a>For example, using the
|
||
|
<span
|
||
|
class="pcrr7t-">read</span> and <span
|
||
|
class="pcrr7t-">show</span> functions defined in Chapter <a
|
||
|
href="haskellch11.html#x18-18200011">11<!--tex4ht:ref: derived-appendix --></a>, and supposing that just <span
|
||
|
class="pcrr7t-">Int</span> and <span
|
||
|
class="pcrr7t-">Bool</span> are members of <span
|
||
|
class="pcrr7t-">Read</span> and
|
||
|
<span
|
||
|
class="pcrr7t-">Show</span>, then the expression
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-46">
|
||
|
  let x = read "..." in show x  -- invalid
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> is ambiguous, because the types for <span
|
||
|
class="pcrr7t-">show</span> and <span
|
||
|
class="pcrr7t-">read</span>,
|
||
|
<div class="array"> <table id="TBL-70" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-70-1g"><col
|
||
|
id="TBL-70-1" /><col
|
||
|
id="TBL-70-2" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">show</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmr-10">::</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Show</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">String</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">read</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmr-10">::</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Read</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">String</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span> </div></td>
|
||
|
</tr></table> </div>
|
||
|
could be satisfied by instantiating <span
|
||
|
class="pcrr7t-">a</span> as either <span
|
||
|
class="pcrr7t-">Int</span> in both cases, or <span
|
||
|
class="pcrr7t-">Bool</span>. Such expressions are considered ill-typed,
|
||
|
a static error.
|
||
|
<p class="noindent"> We say that an expression <span
|
||
|
class="pcrr7t-">e</span> has an <span
|
||
|
class="ptmri7t-">ambiguous type </span>if, in its type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span>, there is a type variable <span
|
||
|
class="cmmi-10">u</span> in <span class="overline"><span
|
||
|
class="cmmi-10">u</span></span> that
|
||
|
occurs in <span
|
||
|
class="cmmi-10">cx</span> but not in <span
|
||
|
class="cmmi-10">t</span>. Such types are invalid.
|
||
|
<p class="noindent"> For example, the earlier expression involving <span
|
||
|
class="pcrr7t-">show</span> and <span
|
||
|
class="pcrr7t-">read</span> has an ambiguous type since its type is
|
||
|
<span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Show</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Read</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">String</span>.
|
||
|
<p class="noindent"> Ambiguous types can only be circumvented by input from the user. One way is through the use of <span
|
||
|
class="ptmri7t-">expression</span>
|
||
|
<span
|
||
|
class="ptmri7t-">type-signatures</span> <a
|
||
|
id="dx10-79005"></a>as described in Section <a
|
||
|
href="haskellch3.html#x8-560003.16">3.16<!--tex4ht:ref: expression-type-sigs --></a>. For example, for the ambiguous expression given earlier, one could
|
||
|
write:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-47">
|
||
|
  let x = read "..." in show (x::Bool)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> which disambiguates the type.
|
||
|
<p class="noindent"> Occasionally, an otherwise ambiguous expression needs to be made the same type as some variable, rather than
|
||
|
being given a fixed type with an expression type-signature. This is the purpose of the function <span
|
||
|
class="pcrr7t-">asTypeOf</span>
|
||
|
(Chapter <a
|
||
|
href="haskellch9.html#x16-1710009">9<!--tex4ht:ref: stdprelude --></a>): <span
|
||
|
class="cmmi-10">x</span> <span
|
||
|
class="pcrr7t-">‘asTypeOf‘</span> <span
|
||
|
class="cmmi-10">y</span> has the value of <span
|
||
|
class="cmmi-10">x</span>, but <span
|
||
|
class="cmmi-10">x</span> and <span
|
||
|
class="cmmi-10">y</span> are forced to have the same type. For example,
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-48">
|
||
|
  approxSqrt x = encodeFloat 1 (exponent x ‘div‘ 2) ‘asTypeOf‘ x
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> (See Section <a
|
||
|
href="haskellch6.html#x13-1410006.4.6">6.4.6<!--tex4ht:ref: coercion --></a> for a description of <span
|
||
|
class="pcrr7t-">encodeFloat</span> and <span
|
||
|
class="pcrr7t-">exponent</span>.)
|
||
|
<p class="noindent"> Ambiguities in the class <span
|
||
|
class="pcrr7t-">Num</span><a
|
||
|
id="dx10-79006"></a> are most common, so Haskell provides another way to resolve them—with a <span
|
||
|
class="ptmri7t-">default</span>
|
||
|
<span
|
||
|
class="ptmri7t-">declaration</span>:
|
||
|
<span
|
||
|
class="pcrr7t-">default</span><span
|
||
|
class="pcrr7t-"> (</span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> t</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="pcrr7t-">)</span>
|
||
|
where <span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">0</span>, and each <span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> must be a type for which <span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">t</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> holds. In situations where an ambiguous type is
|
||
|
discovered, an ambiguous type variable, <span
|
||
|
class="cmmi-10">v</span>, is defaultable if:
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize"><span
|
||
|
class="cmmi-10">v</span> appears only in constraints of the form <span
|
||
|
class="cmmi-10">C</span><span
|
||
|
class="cmmi-10"> v</span>, where <span
|
||
|
class="cmmi-10">C</span> is a class, and
|
||
|
</li>
|
||
|
<li class="itemize">at least one of these classes is a numeric class, (that is, <span
|
||
|
class="pcrr7t-">Num</span> or a subclass of <span
|
||
|
class="pcrr7t-">Num</span>), and
|
||
|
</li>
|
||
|
<li class="itemize">all of these classes are defined in the Prelude or a standard library (Figures <a
|
||
|
href="haskellch6.html#x13-1350142">6.2<!--tex4ht:ref: basic-numeric-1 --></a>–<a
|
||
|
href="haskellch6.html#x13-1350573">6.3<!--tex4ht:ref: basic-numeric-2 --></a> show the numeric
|
||
|
classes, and Figure <a
|
||
|
href="haskellch6.html#x13-1270011">6.1<!--tex4ht:ref: standard-classes --></a> shows the classes defined in the Prelude.)</li></ul>
|
||
|
<p class="noindent"> Each defaultable variable is replaced by the first type in the default list that is an instance of all the ambiguous
|
||
|
variable’s classes. It is a static error if no such type is found.
|
||
|
<p class="noindent"> Only one default declaration is permitted per module, and its effect is limited to that module. If no default
|
||
|
declaration is given in a module then it assumed to be:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-49">
|
||
|
  default (Integer, Double)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The empty default declaration, <span
|
||
|
class="pcrr7t-">default</span><span
|
||
|
class="pcrr7t-"> ()</span>, turns off all defaults in a module.
|
||
|
<p class="noindent">
|
||
|
<h3 class="sectionHead"><span class="titlemark">4.4 </span> <a
|
||
|
id="x10-800004.4"></a>Nested Declarations</h3>
|
||
|
<p class="noindent"> The following declarations may be used in any declaration list, including the top level of a module.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.4.1 </span> <a
|
||
|
id="x10-810004.4.1"></a>Type Signatures</h4>
|
||
|
<a
|
||
|
id="dx10-81001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-71" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-71-1g"><col
|
||
|
id="TBL-71-1" /><col
|
||
|
id="TBL-71-2" /><col
|
||
|
id="TBL-71-3" /><col
|
||
|
id="TBL-71-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-71-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-71-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gendecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-71-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-71-1-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">vars</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">context</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> type </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-71-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-71-2-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">vars </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-71-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-71-2-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">var</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> var</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-71-2-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-81002"></a>
|
||
|
<a
|
||
|
id="dx10-81003"></a>
|
||
|
<p class="noindent"> A type signature specifies types for variables, possibly with respect to a context. A type signature has the
|
||
|
form:
|
||
|
|
||
|
|
||
|
|
||
|
<span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> v</span><sub><span
|
||
|
class="cmmi-7">n</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> t</span>
|
||
|
which is equivalent to asserting <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">::</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=></span><span
|
||
|
class="cmmi-10"> t</span> for each <span
|
||
|
class="cmmi-10">i</span> from <span
|
||
|
class="cmr-10">1</span> to <span
|
||
|
class="cmmi-10">n</span>. Each <span
|
||
|
class="cmmi-10">v</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> must have a value binding in the
|
||
|
same declaration list that contains the type signature; i.e. it is invalid to give a type signature for a variable bound in
|
||
|
an outer scope. Moreover, it is invalid to give more than one type signature for one variable, even if the signatures are
|
||
|
identical.
|
||
|
<p class="noindent"> As mentioned in Section <a
|
||
|
href="#x10-650004.1.2">4.1.2<!--tex4ht:ref: type-syntax --></a>, every type variable appearing in a signature is universally quantified over that
|
||
|
signature, and hence the scope of a type variable is limited to the type signature that contains it. For example, in the
|
||
|
following declarations
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-50">
|
||
|
  f :: a -> a
|
||
|
 <br />  f x = x :: a                  -- invalid
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> the <span
|
||
|
class="pcrr7t-">a</span>’s in the two type signatures are quite distinct. Indeed, these declarations contain a static error,
|
||
|
since <span
|
||
|
class="pcrr7t-">x</span> does not have type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> a</span>. (The type of <span
|
||
|
class="pcrr7t-">x</span> is dependent on the type of <span
|
||
|
class="pcrr7t-">f</span>; there is currently no
|
||
|
way in Haskell to specify a signature for a variable with a dependent type; this is explained in Section
|
||
|
<a
|
||
|
href="#x10-920004.5.4">4.5.4<!--tex4ht:ref: monomorphism --></a>.)
|
||
|
<p class="noindent"> If a given program includes a signature for a variable <span
|
||
|
class="cmmi-10">f</span>, then each use of <span
|
||
|
class="cmmi-10">f</span> is treated as having the
|
||
|
declared type. It is a static error if the same type cannot also be inferred for the defining occurrence of
|
||
|
<span
|
||
|
class="cmmi-10">f</span>.
|
||
|
<p class="noindent"> If a variable <span
|
||
|
class="cmmi-10">f</span> is defined without providing a corresponding type signature declaration, then each use of <span
|
||
|
class="cmmi-10">f</span> outside its
|
||
|
own declaration group (see Section <a
|
||
|
href="#x10-880004.5">4.5<!--tex4ht:ref: dependencyanalysis --></a>) is treated as having the corresponding inferred, or <span
|
||
|
class="ptmri7t-">principal </span>type <a
|
||
|
id="dx10-81004"></a>. However,
|
||
|
to ensure that type inference is still possible, the defining occurrence, and all uses of <span
|
||
|
class="cmmi-10">f</span> within its declaration group
|
||
|
must have the same monomorphic type (from which the principal type is obtained by generalization, as described in
|
||
|
Section <a
|
||
|
href="#x10-900004.5.2">4.5.2<!--tex4ht:ref: generalization --></a>).
|
||
|
<p class="noindent"> For example, if we define
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-51">
|
||
|
  sqr x  =  x⋆x
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> then the principal type is <span
|
||
|
class="pcrr7t-">sqr</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmr-10">::</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span>, which allows applications such as <span
|
||
|
class="pcrr7t-">sqr</span><span
|
||
|
class="pcrr7t-"> 5</span> or
|
||
|
<span
|
||
|
class="pcrr7t-">sqr</span><span
|
||
|
class="pcrr7t-"> 0.1</span>. It is also valid to declare a more specific type, such as
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-52">
|
||
|
  sqr :: Int -> Int
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> but now applications such as <span
|
||
|
class="pcrr7t-">sqr</span><span
|
||
|
class="pcrr7t-"> 0.1</span> are invalid. Type signatures such as
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-53">
|
||
|
  sqr :: (Num a, Num b) => a -> b     -- invalid
|
||
|
 <br />  sqr :: a -> a                       -- invalid
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> are invalid, as they are more general than the principal type of <span
|
||
|
class="pcrr7t-">sqr</span>.
|
||
|
<p class="noindent"> Type signatures can also be used to support <span
|
||
|
class="ptmri7t-">polymorphic recursion</span><a
|
||
|
id="dx10-81005"></a>. The following definition is pathological, but
|
||
|
illustrates how a type signature can be used to specify a type more general than the one that would be inferred:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-54">
|
||
|
  data T a  =  K (T Int) (T a)
|
||
|
 <br />  f         :: T a -> a
|
||
|
 <br />  f (K x y) =  if f x == 1 then f y else undefined
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> If we remove the signature declaration, the type of <span
|
||
|
class="pcrr7t-">f</span> will be inferred as <span
|
||
|
class="pcrr7t-">T</span><span
|
||
|
class="pcrr7t-"> Int</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> Int</span> due to the first recursive
|
||
|
call for which the argument to <span
|
||
|
class="pcrr7t-">f</span> is <span
|
||
|
class="pcrr7t-">T</span><span
|
||
|
class="pcrr7t-"> Int</span>. Polymorphic recursion allows the user to supply the more general type
|
||
|
signature, <span
|
||
|
class="pcrr7t-">T</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> a</span>.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.4.2 </span> <a
|
||
|
id="x10-820004.4.2"></a>Fixity Declarations</h4>
|
||
|
<a
|
||
|
id="dx10-82001"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-72" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-72-1g"><col
|
||
|
id="TBL-72-1" /><col
|
||
|
id="TBL-72-2" /><col
|
||
|
id="TBL-72-3" /><col
|
||
|
id="TBL-72-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-72-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-72-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gendecl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-72-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-72-1-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">fixity</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">integer</span><span
|
||
|
class="cmr-10">]</span><span
|
||
|
class="cmmi-10"> ops </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-72-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-72-2-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">fixity </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-72-2-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-72-2-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">infixl</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">infixr</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">infix</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-72-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-72-3-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">ops </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-72-3-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-72-3-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">op</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="cmmi-10"> op</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-72-3-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1) </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-72-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-72-4-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">op </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-72-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-72-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">varop</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> conop </span></td>
|
||
|
</tr></table></div></div>
|
||
|
<a
|
||
|
id="dx10-82002"></a>
|
||
|
<a
|
||
|
id="dx10-82003"></a>
|
||
|
<a
|
||
|
id="dx10-82004"></a>
|
||
|
<a
|
||
|
id="dx10-82005"></a>
|
||
|
<p class="noindent"> A fixity declaration gives the fixity and binding precedence of one or more operators. The <span
|
||
|
class="cmmi-10">integer</span> in a
|
||
|
fixity declaration must be in the range <span
|
||
|
class="cmr-10">0</span> to <span
|
||
|
class="cmr-10">9</span>. A fixity declaration may appear anywhere that a type
|
||
|
signature appears and, like a type signature, declares a property of a particular operator. Also like a type
|
||
|
signature, a fixity declaration can only occur in the same sequence of declarations as the declaration of
|
||
|
the operator itself, and at most one fixity declaration may be given for any operator. (Class methods
|
||
|
are a minor exception; their fixity declarations can occur either in the class declaration itself or at top
|
||
|
level.)
|
||
|
<p class="noindent"> There are three kinds of fixity, non-, left- and right-associativity (<span
|
||
|
class="pcrr7t-">infix</span>, <span
|
||
|
class="pcrr7t-">infixl</span>, and <span
|
||
|
class="pcrr7t-">infixr</span>, respectively), and
|
||
|
ten precedence levels, 0 to 9 inclusive (level 0 binds least tightly, and level 9 binds most tightly). If the <span
|
||
|
class="cmmi-10">digit</span> is
|
||
|
omitted, level 9 is assumed. Any operator lacking a fixity declaration is assumed to be <span
|
||
|
class="pcrr7t-">infixl</span><span
|
||
|
class="pcrr7t-"> 9</span> (See Section <a
|
||
|
href="haskellch3.html#x8-220003">3<!--tex4ht:ref: expressions --></a> for
|
||
|
more on the use of fixities). Table <a
|
||
|
href="#x10-820061">4.1<!--tex4ht:ref: prelude-fixities --></a> lists the fixities and precedences of the operators defined in the
|
||
|
Prelude.
|
||
|
<div class="table">
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent"> <a
|
||
|
id="x10-820061"></a><hr class="float" /><div class="float"
|
||
|
>
|
||
|
|
||
|
|
||
|
|
||
|
<div
|
||
|
class="centerline"> <!--tex4ht:inline--><div class="tabular"> <table id="TBL-73" class="tabular"
|
||
|
cellspacing="0" cellpadding="0" rules="groups"
|
||
|
><colgroup id="TBL-73-1g"><col
|
||
|
id="TBL-73-1" /></colgroup><colgroup id="TBL-73-2g"><col
|
||
|
id="TBL-73-2" /></colgroup><colgroup id="TBL-73-3g"><col
|
||
|
id="TBL-73-3" /></colgroup><colgroup id="TBL-73-4g"><col
|
||
|
id="TBL-73-4" /></colgroup><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-1-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-1-1"
|
||
|
class="td11"> Prec- </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-1-2"
|
||
|
class="td11"> Left associative </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-1-3"
|
||
|
class="td11"> Non-associative </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-1-4"
|
||
|
class="td11"> Right associative </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-2-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-2-1"
|
||
|
class="td11"> edence </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-2-2"
|
||
|
class="td11"> operators </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-2-3"
|
||
|
class="td11"> operators </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-2-4"
|
||
|
class="td11"> operators </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-3-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-3-1"
|
||
|
class="td11"> 9 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-3-2"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">!!</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-3-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-3-4"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">.</span> </td></tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-4-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-4-1"
|
||
|
class="td11"> 8 </td> <td style="white-space:nowrap; text-align:left;" id="TBL-73-4-2"
|
||
|
class="td11"> </td> <td style="white-space:nowrap; text-align:left;" id="TBL-73-4-3"
|
||
|
class="td11"> </td> <td style="white-space:nowrap; text-align:left;" id="TBL-73-4-4"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">^</span> , <span
|
||
|
class="pcrr7t-">^^</span> , <span
|
||
|
class="pcrr7t-">⋆⋆</span></td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-5-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-5-1"
|
||
|
class="td11"> 7 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-5-2"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">⋆</span>, <span
|
||
|
class="pcrr7t-">/</span>, <span
|
||
|
class="pcrr7t-">‘div‘</span>, </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-5-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-5-4"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-6-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-6-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-6-2"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">‘mod‘</span>, <span
|
||
|
class="pcrr7t-">‘rem‘</span>, <span
|
||
|
class="pcrr7t-">‘quot‘</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-6-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-6-4"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-7-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-7-1"
|
||
|
class="td11"> 6 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-7-2"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">+</span>, <span
|
||
|
class="pcrr7t-">-</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-7-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-7-4"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-8-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-8-1"
|
||
|
class="td11"> 5 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-8-2"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-8-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-8-4"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">:</span>, <span
|
||
|
class="pcrr7t-">++</span> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-9-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-9-1"
|
||
|
class="td11"> 4 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-9-2"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-9-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">==</span>, <span
|
||
|
class="pcrr7t-">/=</span>, <span
|
||
|
class="pcrr7t-"><</span>, <span
|
||
|
class="pcrr7t-"><=</span>, <span
|
||
|
class="pcrr7t-">></span>, <span
|
||
|
class="pcrr7t-">>=</span>, </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-9-4"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-10-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-10-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-10-2"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-10-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">‘elem‘</span>, <span
|
||
|
class="pcrr7t-">‘notElem‘</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-10-4"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-11-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-11-1"
|
||
|
class="td11"> 3 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-11-2"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-11-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-11-4"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">&&</span> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-12-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-12-1"
|
||
|
class="td11"> 2 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-12-2"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-12-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-12-4"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">||</span> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-13-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-13-1"
|
||
|
class="td11"> 1 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-13-2"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">>></span>, <span
|
||
|
class="pcrr7t-">>>=</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-13-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-13-4"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-14-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-14-1"
|
||
|
class="td11"> 0 </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-14-2"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-14-3"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:left;" id="TBL-73-14-4"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">$</span>, <span
|
||
|
class="pcrr7t-">$!</span>, <span
|
||
|
class="pcrr7t-">‘seq‘</span> </td>
|
||
|
</tr><tr
|
||
|
class="hline"><td><hr /></td><td><hr /></td><td><hr /></td><td><hr /></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-73-15-"><td style="white-space:nowrap; text-align:right;" id="TBL-73-15-1"
|
||
|
class="td11"> </td></tr></table> </div></div>
|
||
|
<br /><div class="caption"
|
||
|
><span class="id">Table 4.1: </span><span
|
||
|
class="content">Precedences and fixities of prelude operators</span></div><!--tex4ht:label?: x10-820061 -->
|
||
|
<a
|
||
|
id="dx10-82007"></a>
|
||
|
<a
|
||
|
id="dx10-82008"></a>
|
||
|
<a
|
||
|
id="dx10-82009"></a>
|
||
|
<a
|
||
|
id="dx10-82010"></a>
|
||
|
<a
|
||
|
id="dx10-82011"></a>
|
||
|
<a
|
||
|
id="dx10-82012"></a>
|
||
|
<a
|
||
|
id="dx10-82013"></a>
|
||
|
<a
|
||
|
id="dx10-82014"></a>
|
||
|
<a
|
||
|
id="dx10-82015"></a>
|
||
|
<a
|
||
|
id="dx10-82016"></a>
|
||
|
<a
|
||
|
id="dx10-82017"></a>
|
||
|
<a
|
||
|
id="dx10-82018"></a>
|
||
|
<a
|
||
|
id="dx10-82019"></a>
|
||
|
<a
|
||
|
id="dx10-82020"></a>
|
||
|
<a
|
||
|
id="dx10-82021"></a>
|
||
|
<a
|
||
|
id="dx10-82022"></a>
|
||
|
<a
|
||
|
id="dx10-82023"></a>
|
||
|
<a
|
||
|
id="dx10-82024"></a>
|
||
|
<a
|
||
|
id="dx10-82025"></a>
|
||
|
<a
|
||
|
id="dx10-82026"></a>
|
||
|
<a
|
||
|
id="dx10-82027"></a>
|
||
|
<a
|
||
|
id="dx10-82028"></a>
|
||
|
<a
|
||
|
id="dx10-82029"></a>
|
||
|
<a
|
||
|
id="dx10-82030"></a>
|
||
|
<a
|
||
|
id="dx10-82031"></a>
|
||
|
<a
|
||
|
id="dx10-82032"></a>
|
||
|
<a
|
||
|
id="dx10-82033"></a>
|
||
|
|
||
|
|
||
|
|
||
|
</div><hr class="endfloat" />
|
||
|
</div>
|
||
|
<p class="noindent"> Fixity is a property of a particular entity (constructor or variable), just like its type; fixity is not a property of that
|
||
|
entity’s <span
|
||
|
class="ptmri7t-">name</span>. For example:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-55">
|
||
|
  module Bar( op ) where
|
||
|
 <br />    infixr 7 ‘op‘
|
||
|
 <br />    op = ...
|
||
|
 <br />
|
||
|
 <br />  module Foo where
|
||
|
 <br />    import qualified Bar
|
||
|
 <br />    infix 3 ‘op‘
|
||
|
 <br />
|
||
|
 <br />    a ‘op‘ b = (a ‘Bar.op‘ b) + 1
|
||
|
 <br />
|
||
|
 <br />    f x = let
|
||
|
 <br />             p ‘op‘ q = (p ‘Foo.op‘ q) ⋆ 2
|
||
|
 <br />          in ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Here, <span
|
||
|
class="pcrr7t-">‘Bar.op‘</span> is <span
|
||
|
class="pcrr7t-">infixr</span><span
|
||
|
class="pcrr7t-"> 7</span>, <span
|
||
|
class="pcrr7t-">‘Foo.op‘</span> is <span
|
||
|
class="pcrr7t-">infix</span><span
|
||
|
class="pcrr7t-"> 3</span>, and the nested definition of <span
|
||
|
class="pcrr7t-">op</span> in <span
|
||
|
class="pcrr7t-">f</span>’s right-hand side
|
||
|
has the default fixity of <span
|
||
|
class="pcrr7t-">infixl</span><span
|
||
|
class="pcrr7t-"> 9</span>. (It would also be possible to give a fixity to the nested definition of <span
|
||
|
class="pcrr7t-">‘op‘</span> with a
|
||
|
nested fixity declaration.)
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.4.3 </span> <a
|
||
|
id="x10-830004.4.3"></a>Function and Pattern Bindings</h4>
|
||
|
<a
|
||
|
id="dx10-83001"></a>
|
||
|
<a
|
||
|
id="dx10-83002"></a>
|
||
|
<div class="flushleft"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<!--tex4ht:inline--><div class="tabular"> <table id="TBL-74" class="tabular"
|
||
|
cellspacing="0" cellpadding="0"
|
||
|
><colgroup id="TBL-74-1g"><col
|
||
|
id="TBL-74-1" /><col
|
||
|
id="TBL-74-2" /><col
|
||
|
id="TBL-74-3" /><col
|
||
|
id="TBL-74-4" /></colgroup><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-1-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">decl </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-74-1-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-1-3"
|
||
|
class="td11"> <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">pat</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10"> rhs</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-2-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-3-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-4-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">funlhs </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-74-4-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-4-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">var</span><span
|
||
|
class="cmmi-10"> apat</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">{</span><span
|
||
|
class="cmmi-10"> apat</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">} </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-5-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-5-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-5-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">pat</span><span
|
||
|
class="cmmi-10"> varop</span><span
|
||
|
class="cmmi-10"> pat</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-6-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-6-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-6-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10"> funlhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">)</span><span
|
||
|
class="cmmi-10"> apat</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">{</span><span
|
||
|
class="cmmi-10"> apat</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmsy-10">} </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-7-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td></tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-8-1"
|
||
|
class="td11"></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-9-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">rhs </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-74-9-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-9-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> exp</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> decls</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-10-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-10-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-10-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-10-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gdrhs</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="cmmi-10"> decls</span><span
|
||
|
class="cmr-10">] </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-11-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-11-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-12-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-12-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-13-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-13-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">gdrhs </span></td><td style="white-space:nowrap; text-align:center;" id="TBL-74-13-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-13-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">guards</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> exp</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">[</span><span
|
||
|
class="cmmi-10">gdrhs</span><span
|
||
|
class="cmr-10">]</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-14-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-14-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-15-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-15-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-16-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-16-1"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">guards</span> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-16-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-16-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> guard</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> guard</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-16-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1)</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-17-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-17-1"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-">  </span></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-18-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-18-1"
|
||
|
class="td11"> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-19-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-19-1"
|
||
|
class="td11"> <a
|
||
|
id="dx10-83003"></a><span
|
||
|
class="cmmi-10">guard</span> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-19-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">→</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-19-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">pat</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-"><-</span><span
|
||
|
class="cmmi-10"> infixexp</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-19-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>pattern guard<span
|
||
|
class="cmr-10">)</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-20-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-20-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-20-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-20-3"
|
||
|
class="td11"> <span
|
||
|
class="pcrr7t-">let</span><span
|
||
|
class="cmmi-10"> decls</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-20-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>local declaration<span
|
||
|
class="cmr-10">)</span> </td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;" id="TBL-74-21-"><td style="white-space:nowrap; text-align:left;" id="TBL-74-21-1"
|
||
|
class="td11"> </td><td style="white-space:nowrap; text-align:center;" id="TBL-74-21-2"
|
||
|
class="td11"> <span
|
||
|
class="cmsy-10">|</span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-74-21-3"
|
||
|
class="td11"> <span
|
||
|
class="cmmi-10">infixexp </span></td><td style="white-space:nowrap; text-align:left;" id="TBL-74-21-4"
|
||
|
class="td11"> <span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="ptmri7t-"> </span><span
|
||
|
class="cmr-10">(</span>boolean guard<span
|
||
|
class="cmr-10">) </span></td>
|
||
|
</tr></table></div></div>
|
||
|
|
||
|
|
||
|
|
||
|
<a
|
||
|
id="dx10-83004"></a>
|
||
|
<a
|
||
|
id="dx10-83005"></a>
|
||
|
<a
|
||
|
id="dx10-83006"></a>
|
||
|
<a
|
||
|
id="dx10-83007"></a>
|
||
|
<a
|
||
|
id="dx10-83008"></a>
|
||
|
<a
|
||
|
id="dx10-83009"></a>
|
||
|
<p class="noindent"> We distinguish two cases within this syntax: a <span
|
||
|
class="ptmri7t-">pattern binding </span>occurs when the left hand side is a <span
|
||
|
class="cmmi-10">pat</span>; otherwise, the
|
||
|
binding is called a <span
|
||
|
class="ptmri7t-">function binding</span>. Either binding may appear at the top-level of a module or within a <span
|
||
|
class="pcrr7t-">where</span> or
|
||
|
<span
|
||
|
class="pcrr7t-">let</span> construct.
|
||
|
<p class="noindent">
|
||
|
<h5 class="subsubsectionHead"><span class="titlemark">4.4.3.1 </span> <a
|
||
|
id="x10-840004.4.3.1"></a>Function bindings</h5>
|
||
|
<a
|
||
|
id="dx10-84001"></a>
|
||
|
<p class="noindent"> A function binding binds a variable to a function value. The general form of a function binding for variable <span
|
||
|
class="cmmi-10">x</span>
|
||
|
is:
|
||
|
<div class="array"> <table id="TBL-75" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-75-1g"><col
|
||
|
id="TBL-75-1" /><col
|
||
|
id="TBL-75-2" /><col
|
||
|
id="TBL-75-3" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">x</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">p</span><sub><span
|
||
|
class="cmr-7">11</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> p</span><sub><span
|
||
|
class="cmr-7">1</span><span
|
||
|
class="cmmi-7">k</span></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">match</span><sub><span
|
||
|
class="cmr-7">1</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">…</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">x</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">p</span><sub><span
|
||
|
class="cmmi-7">n</span><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> p</span><sub><span
|
||
|
class="cmmi-7">nk</span></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">match</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </div></td>
|
||
|
</tr></table> </div>
|
||
|
where each <span
|
||
|
class="cmmi-10">p</span><sub><span
|
||
|
class="cmmi-7">ij</span></sub> is a pattern, and where each <span
|
||
|
class="cmmi-10">match</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> is of the general form:
|
||
|
<div class="array"> <table id="TBL-76" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-76-1g"><col
|
||
|
id="TBL-76-1" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="pcrr7t-"> {</span><span
|
||
|
class="cmmi-10"> decls</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </div></td>
|
||
|
</tr></table> </div>
|
||
|
or
|
||
|
|
||
|
|
||
|
|
||
|
<div class="array"> <table id="TBL-77" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-77-1g"><col
|
||
|
id="TBL-77-1" /><col
|
||
|
id="TBL-77-2" /><col
|
||
|
id="TBL-77-3" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmmi-7">i</span><span
|
||
|
class="cmr-7">1</span></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmmi-7">i</span><span
|
||
|
class="cmr-7">1</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">…</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmmi-7">im</span><sub><span
|
||
|
class="cmmi-5">i</span></sub></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmmi-7">im</span><sub><span
|
||
|
class="cmmi-5">i</span></sub></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td colspan="2" style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <div class="multicolumn" style="white-space:nowrap; text-align:left;"><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="pcrr7t-"> {</span><span
|
||
|
class="cmmi-10"> decls</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span></div>
|
||
|
</div></td></tr></table> </div>
|
||
|
and where <span
|
||
|
class="cmmi-10">n </span><span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1</span>, <span
|
||
|
class="cmr-10">1 </span><span
|
||
|
class="cmsy-10">≤ </span><span
|
||
|
class="cmmi-10">i </span><span
|
||
|
class="cmsy-10">≤ </span><span
|
||
|
class="cmmi-10">n</span>, <span
|
||
|
class="cmmi-10">m</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> <span
|
||
|
class="cmsy-10">≥ </span><span
|
||
|
class="cmr-10">1</span>. The former is treated as shorthand for a particular case of the latter,
|
||
|
namely:
|
||
|
<div class="array"> <table id="TBL-78" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-78-1g"><col
|
||
|
id="TBL-78-1" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="pcrr7t-"> True</span><span
|
||
|
class="pcrr7t-"> =</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="pcrr7t-"> {</span><span
|
||
|
class="cmmi-10"> decls</span><sub><span
|
||
|
class="cmmi-7">i</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span> </div></td>
|
||
|
</tr></table> </div>
|
||
|
<p class="noindent"> Note that all clauses defining a function must be contiguous, and the number of patterns in each clause must be the
|
||
|
same. The set of patterns corresponding to each match must be <span
|
||
|
class="ptmri7t-">linear</span><a
|
||
|
id="dx10-84002"></a><a
|
||
|
id="dx10-84003"></a>—no variable is allowed to appear more than
|
||
|
once in the entire set.
|
||
|
<p class="noindent"> Alternative syntax is provided for binding functional values to infix operators. For example, these three function
|
||
|
definitions are all equivalent:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-56">
|
||
|
  plus x y z = x+y+z
|
||
|
 <br />  x ‘plus‘ y = \ z -> x+y+z
|
||
|
 <br />  (x ‘plus‘ y) z = x+y+z
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Note that fixity resolution applies to the infix variants of the function binding in the same way as for expressions
|
||
|
(Section <a
|
||
|
href="haskellch10.html#x17-18100010.6">10.6<!--tex4ht:ref: fixity-resolution --></a>). Applying fixity resolution to the left side of the equals in a function binding must leave the <span
|
||
|
class="cmmi-10">varop</span>
|
||
|
being defined at the top level. For example, if we are defining a new operator <span
|
||
|
class="pcrr7t-">##</span> with precedence 6, then this
|
||
|
definition would be illegal:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-57">
|
||
|
  a ## b : xs = exp
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> because <span
|
||
|
class="pcrr7t-">:</span> has precedence 5, so the left hand side resolves to <span
|
||
|
class="pcrr7t-">(a</span><span
|
||
|
class="pcrr7t-"> ##</span><span
|
||
|
class="pcrr7t-"> x)</span><span
|
||
|
class="pcrr7t-"> :</span><span
|
||
|
class="pcrr7t-"> xs</span>, and this cannot be a pattern binding
|
||
|
because <span
|
||
|
class="pcrr7t-">(a</span><span
|
||
|
class="pcrr7t-"> ##</span><span
|
||
|
class="pcrr7t-"> x)</span> is not a valid pattern.
|
||
|
<div class="center"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<div class="fbox"><div class="minipage"><p class="noindent"> <span class="likeparagraphHead"><a
|
||
|
id="x10-850004.4.3.1"></a>Translation:</span>
|
||
|
The general binding form for functions is semantically equivalent to the equation (i.e. simple pattern
|
||
|
binding):
|
||
|
<span
|
||
|
class="cmmi-10">x</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="pcrr7t-"> \</span><span
|
||
|
class="cmmi-10"> x</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10"> x</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">-></span><span
|
||
|
class="pcrr7t-"> case</span><span
|
||
|
class="pcrr7t-"> (</span><span
|
||
|
class="cmmi-10">x</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="pcrr7t-">,</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">x</span><sub><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="pcrr7t-">)</span><span
|
||
|
class="pcrr7t-"> of</span><div class="array"><table id="TBL-79" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-79-1g"><col
|
||
|
id="TBL-79-1" /><col
|
||
|
id="TBL-79-2" /><col
|
||
|
id="TBL-79-3" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">p</span><sub><span
|
||
|
class="cmr-7">11</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> p</span><sub><span
|
||
|
class="cmr-7">1</span><span
|
||
|
class="cmmi-7">k</span></sub><span
|
||
|
class="pcrr7t-">)</span><span
|
||
|
class="cmmi-10"> match</span><sub><span
|
||
|
class="cmr-7">1</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">…</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">(</span><span
|
||
|
class="cmmi-10">p</span><sub><span
|
||
|
class="cmmi-7">n</span><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">…</span><span
|
||
|
class="cmmi-10">,</span><span
|
||
|
class="cmmi-10"> p</span><sub><span
|
||
|
class="cmmi-7">nk</span></sub><span
|
||
|
class="pcrr7t-">)</span><span
|
||
|
class="cmmi-10"> match</span><sub><span
|
||
|
class="cmmi-7">n</span></sub> </div></td></tr></table> </div>
|
||
|
where the <span
|
||
|
class="cmmi-10">x</span><sub><span
|
||
|
class="cmmi-7">i</span></sub> are new identifiers. </div></div>
|
||
|
</div>
|
||
|
<p class="noindent">
|
||
|
<h5 class="subsubsectionHead"><span class="titlemark">4.4.3.2 </span> <a
|
||
|
id="x10-860004.4.3.2"></a>Pattern bindings</h5>
|
||
|
<a
|
||
|
id="dx10-86001"></a>
|
||
|
<p class="noindent"> A pattern binding binds variables to values. A <span
|
||
|
class="ptmri7t-">simple </span>pattern binding has form <span
|
||
|
class="cmmi-10">p</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmr-10">=</span> <span
|
||
|
class="cmmi-10"> e</span>. <a
|
||
|
id="dx10-86002"></a>The pattern <span
|
||
|
class="cmmi-10">p</span> is
|
||
|
matched “lazily” as an irrefutable pattern<a
|
||
|
id="dx10-86003"></a>, as if there were an implicit <span
|
||
|
class="pcrr7t-">~</span> in front of it. See the translation in
|
||
|
Section <a
|
||
|
href="haskellch3.html#x8-440003.12">3.12<!--tex4ht:ref: let-expressions --></a>.
|
||
|
<p class="noindent"> The <span
|
||
|
class="ptmri7t-">general </span>form of a pattern binding is <span
|
||
|
class="cmmi-10">p</span><span
|
||
|
class="cmmi-10"> match</span>, where a <span
|
||
|
class="cmmi-10">match</span> is the same structure as for function bindings
|
||
|
above; in other words, a pattern binding is:
|
||
|
|
||
|
|
||
|
|
||
|
<div class="array"> <table id="TBL-80" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-80-1g"><col
|
||
|
id="TBL-80-1" /><col
|
||
|
id="TBL-80-2" /><col
|
||
|
id="TBL-80-3" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:right;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">p</span> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmr-7">1</span></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmr-7">1</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:right;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmr-7">2</span></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmr-7">2</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:right;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">…</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:right;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">|</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmmi-7">m</span></sub> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span><span
|
||
|
class="cmmi-10"> e</span><sub><span
|
||
|
class="cmmi-7">m</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:right;"
|
||
|
><div class="td11"> </div></td><td colspan="2" style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <div class="multicolumn" style="white-space:nowrap; text-align:left;"><span
|
||
|
class="pcrr7t-">where</span><span
|
||
|
class="pcrr7t-"> {</span><span
|
||
|
class="cmmi-10"> decls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">}</span></div>
|
||
|
</div></td></tr></table> </div>
|
||
|
<div class="center"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<div class="fbox"><div class="minipage"><p class="noindent"><span class="likeparagraphHead"><a
|
||
|
id="x10-870004.4.3.2"></a>Translation:</span>
|
||
|
The pattern binding above is semantically equivalent to this simple pattern binding:
|
||
|
<div class="array"> <table id="TBL-81" class="array"
|
||
|
cellpadding="0" cellspacing="0"
|
||
|
><colgroup id="TBL-81-1g"><col
|
||
|
id="TBL-81-1" /><col
|
||
|
id="TBL-81-2" /><col
|
||
|
id="TBL-81-3" /></colgroup><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="cmmi-10">p</span> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">=</span> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">let</span><span
|
||
|
class="cmmi-10"> decls</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">in</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-">case</span><span
|
||
|
class="pcrr7t-"> ()</span><span
|
||
|
class="pcrr7t-"> of</span><span
|
||
|
class="pcrr7t-"> </span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> ()</span><span
|
||
|
class="pcrr7t-"> |</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmr-7">1</span></sub><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">e</span><sub><span
|
||
|
class="cmr-7">1</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> |</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmr-7">2</span></sub><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">e</span><sub><span
|
||
|
class="cmr-7">2</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">…</span> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> |</span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">gs</span><sub><span
|
||
|
class="cmmi-7">m</span></sub><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="cmmi-10">e</span><sub><span
|
||
|
class="cmmi-7">m</span></sub> </div></td>
|
||
|
</tr><tr
|
||
|
style="vertical-align:baseline;"><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:center;"
|
||
|
><div class="td11"> </div></td><td style="white-space:nowrap; text-align:left;"
|
||
|
><div class="td11"> <span
|
||
|
class="pcrr7t-"> </span><span
|
||
|
class="pcrr7t-"> _</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> error</span><span
|
||
|
class="pcrr7t-"> "Unmatched</span><span
|
||
|
class="pcrr7t-"> pattern"</span> </div></td></tr></table> </div></div></div>
|
||
|
</div>
|
||
|
<p class="noindent">
|
||
|
<h3 class="sectionHead"><span class="titlemark">4.5 </span> <a
|
||
|
id="x10-880004.5"></a>Static Semantics of Function and Pattern Bindings</h3>
|
||
|
<p class="noindent"> The static semantics of the function and pattern bindings of a <span
|
||
|
class="pcrr7t-">let</span> expression or <span
|
||
|
class="pcrr7t-">where</span> clause are discussed in this
|
||
|
section.
|
||
|
|
||
|
|
||
|
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.5.1 </span> <a
|
||
|
id="x10-890004.5.1"></a>Dependency Analysis</h4>
|
||
|
<p class="noindent"> In general the static semantics are given by applying the normal Hindley-Milner<a
|
||
|
id="dx10-89001"></a> inference rules. In order
|
||
|
to increase polymorphism, these rules are applied to groups of bindings identified by a <span
|
||
|
class="ptmri7t-">dependency</span>
|
||
|
<span
|
||
|
class="ptmri7t-">analysis</span>.
|
||
|
<p class="noindent"> A binding <span
|
||
|
class="cmmi-10">b</span><span
|
||
|
class="cmr-10">1</span> <span
|
||
|
class="ptmri7t-">depends </span>on a binding <span
|
||
|
class="cmmi-10">b</span><span
|
||
|
class="cmr-10">2</span> in the same list of declarations if either
|
||
|
<p class="noindent">
|
||
|
<ol class="enumerate1" >
|
||
|
<li
|
||
|
class="enumerate" id="x10-89003x1"><span
|
||
|
class="cmmi-10">b</span><span
|
||
|
class="cmr-10">1</span> contains a free identifier that has no type signature and is bound by <span
|
||
|
class="cmmi-10">b</span><span
|
||
|
class="cmr-10">2</span>, or
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-89005x2"><span
|
||
|
class="cmmi-10">b</span><span
|
||
|
class="cmr-10">1</span> depends on a binding that depends on <span
|
||
|
class="cmmi-10">b</span><span
|
||
|
class="cmr-10">2</span>.</li></ol>
|
||
|
<p class="noindent"> A <span
|
||
|
class="ptmri7t-">declaration group </span>is a minimal set of mutually dependent bindings. Hindley-Milner type inference is applied to
|
||
|
each declaration group in dependency order. The order of declarations in <span
|
||
|
class="pcrr7t-">where</span>/<span
|
||
|
class="pcrr7t-">let</span> constructs is
|
||
|
irrelevant.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.5.2 </span> <a
|
||
|
id="x10-900004.5.2"></a>Generalization</h4>
|
||
|
<p class="noindent"> The Hindley-Milner type system assigns types to a let-expression in two stages:
|
||
|
<p class="noindent">
|
||
|
<ol class="enumerate1" >
|
||
|
<li
|
||
|
class="enumerate" id="x10-90002x1">The declaration groups are considered in dependency order. For each group, a type with no universal
|
||
|
quantification is inferred for each variable bound in the group. Then, all type variables that occur
|
||
|
in these types are universally quantified unless they are associated with bound variables in the type
|
||
|
environment; this is called generalization.
|
||
|
</li>
|
||
|
<li
|
||
|
class="enumerate" id="x10-90004x2">Finally, the body of the let-expression is typed.</li></ol>
|
||
|
<p class="noindent"> For example, consider the declaration
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-58">
|
||
|
  f x = let g y = (y,y)
|
||
|
 <br />        in ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The type of <span
|
||
|
class="pcrr7t-">g</span>’s definition is <span
|
||
|
class="cmmi-10">a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">a,a</span><span
|
||
|
class="cmr-10">)</span>. The generalization step attributes to <span
|
||
|
class="pcrr7t-">g</span> the polymorphic type
|
||
|
<span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">a,a</span><span
|
||
|
class="cmr-10">)</span>, after which the typing of the “<span
|
||
|
class="pcrr7t-">...</span>” part can proceed.
|
||
|
<p class="noindent"> When typing overloaded definitions, all the overloading constraints from a single declaration group are collected
|
||
|
together, to form the context for the type of each variable declared in the group. For example, in the definition:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-59">
|
||
|
  f x = let g1 x y = if x>y then show x else g2 y x
|
||
|
 <br />            g2 p q = g1 q p
|
||
|
 <br />        in ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The types of the definitions of <span
|
||
|
class="pcrr7t-">g1</span> and <span
|
||
|
class="pcrr7t-">g2</span> are both <span
|
||
|
class="cmmi-10">a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">String</span>, and the accumulated constraints are
|
||
|
<span
|
||
|
class="pcrr7t-">Ord</span><span
|
||
|
class="cmmi-10"> a</span> (arising from the use of <span
|
||
|
class="pcrr7t-">></span>), and <span
|
||
|
class="pcrr7t-">Show</span><span
|
||
|
class="cmmi-10"> a</span> (arising from the use of <span
|
||
|
class="pcrr7t-">show</span>). The type variables appearing in this
|
||
|
collection of constraints are called the <span
|
||
|
class="ptmri7t-">constrained type variables</span>.
|
||
|
<p class="noindent"> The generalization step attributes to both <span
|
||
|
class="pcrr7t-">g1</span> and <span
|
||
|
class="pcrr7t-">g2</span> the type
|
||
|
<span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="pcrr7t-">Ord</span><span
|
||
|
class="cmmi-10"> a,</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Show</span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmr-10">)</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">String</span>
|
||
|
Notice that <span
|
||
|
class="pcrr7t-">g2</span> is overloaded in the same way as <span
|
||
|
class="pcrr7t-">g1</span> even though the occurrences of <span
|
||
|
class="pcrr7t-">></span> and <span
|
||
|
class="pcrr7t-">show</span> are in the definition
|
||
|
of <span
|
||
|
class="pcrr7t-">g1</span>.
|
||
|
<p class="noindent"> If the programmer supplies explicit type signatures for more than one variable in a declaration group, the contexts of
|
||
|
these signatures must be identical up to renaming of the type variables.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.5.3 </span> <a
|
||
|
id="x10-910004.5.3"></a>Context Reduction Errors</h4>
|
||
|
<a
|
||
|
id="dx10-91001"></a>
|
||
|
<p class="noindent"> As mentioned in Section <a
|
||
|
href="#x10-670004.1.4">4.1.4<!--tex4ht:ref: type-semantics --></a>, the context of a type may constrain only a type variable, or the application of a type
|
||
|
variable to one or more types. Hence, types produced by generalization must be expressed in a form in which all
|
||
|
context constraints have be reduced to this “head normal form”. Consider, for example, the definition:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-60">
|
||
|
  f xs y  =  xs == [y]
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Its type is given by
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-61">
|
||
|
  f :: Eq a => [a] -> a -> Bool
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> and not
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-62">
|
||
|
  f :: Eq [a] => [a] -> a -> Bool
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Even though the equality is taken at the list type, the context must be simplified, using the instance declaration for <span
|
||
|
class="pcrr7t-">Eq</span>
|
||
|
on lists, before generalization. If no such instance is in scope, a static error occurs.
|
||
|
<p class="noindent"> Here is an example that shows the need for a constraint of the form <span
|
||
|
class="cmmi-10">C</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">m</span><span
|
||
|
class="cmmi-10"> t</span><span
|
||
|
class="cmr-10">)</span> where m is one of the type variables
|
||
|
being generalized; that is, where the class <span
|
||
|
class="cmmi-10">C</span> applies to a type expression that is not a type variable or a type
|
||
|
constructor. Consider:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-63">
|
||
|
  f :: (Monad m, Eq (m a)) => a -> m a -> Bool
|
||
|
 <br />  f x y = return x == y
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The type of <span
|
||
|
class="pcrr7t-">return</span> is <span
|
||
|
class="pcrr7t-">Monad</span><span
|
||
|
class="pcrr7t-"> m</span><span
|
||
|
class="pcrr7t-"> =></span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> m</span><span
|
||
|
class="pcrr7t-"> a</span>; the type of <span
|
||
|
class="pcrr7t-">(==)</span> is <span
|
||
|
class="pcrr7t-">Eq</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> =></span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> Bool</span>. The type
|
||
|
of <span
|
||
|
class="pcrr7t-">f</span> should be therefore <span
|
||
|
class="pcrr7t-">(Monad</span><span
|
||
|
class="pcrr7t-"> m,</span><span
|
||
|
class="pcrr7t-"> Eq</span><span
|
||
|
class="pcrr7t-"> (m</span><span
|
||
|
class="pcrr7t-"> a))</span><span
|
||
|
class="pcrr7t-"> =></span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> m</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> -></span><span
|
||
|
class="pcrr7t-"> Bool</span>, and the context cannot be
|
||
|
simplified further.
|
||
|
<p class="noindent"> The instance declaration derived from a data type <span
|
||
|
class="pcrr7t-">deriving</span> clause (see Section <a
|
||
|
href="#x10-780004.3.3">4.3.3<!--tex4ht:ref: derived-decls --></a>) must, like any instance
|
||
|
declaration, have a <span
|
||
|
class="ptmri7t-">simple </span>context; that is, all the constraints must be of the form <span
|
||
|
class="cmmi-10">C</span><span
|
||
|
class="cmmi-10"> a</span>, where <span
|
||
|
class="cmmi-10">a</span> is a type variable. For
|
||
|
example, in the type
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-64">
|
||
|
  data Apply a b = App (a b)  deriving Show
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> the derived Show instance will produce a context <span
|
||
|
class="pcrr7t-">Show</span><span
|
||
|
class="pcrr7t-"> (a</span><span
|
||
|
class="pcrr7t-"> b)</span>, which cannot be reduced and is not simple; thus a
|
||
|
static error results.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.5.4 </span> <a
|
||
|
id="x10-920004.5.4"></a>Monomorphism</h4>
|
||
|
<p class="noindent"> Sometimes it is not possible to generalize over all the type variables used in the type of the definition. For example,
|
||
|
consider the declaration
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-65">
|
||
|
  f x = let g y z = ([x,y], z)
|
||
|
 <br />        in ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> In an environment where <span
|
||
|
class="pcrr7t-">x</span> has type <span
|
||
|
class="cmmi-10">a</span>, the type of <span
|
||
|
class="pcrr7t-">g</span>’s definition is <span
|
||
|
class="cmmi-10">a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> b</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">([</span><span
|
||
|
class="cmmi-10">a</span><span
|
||
|
class="pcrr7t-">]</span><span
|
||
|
class="cmmi-10">,b</span><span
|
||
|
class="pcrr7t-">)</span>. The generalization step
|
||
|
attributes to <span
|
||
|
class="pcrr7t-">g</span> the type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> b.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> b</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">→</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">([</span><span
|
||
|
class="cmmi-10">a</span><span
|
||
|
class="pcrr7t-">]</span><span
|
||
|
class="cmmi-10">,b</span><span
|
||
|
class="pcrr7t-">)</span>; only <span
|
||
|
class="cmmi-10">b</span> can be universally quantified because
|
||
|
<span
|
||
|
class="cmmi-10">a</span> occurs in the type environment. We say that the type of <span
|
||
|
class="pcrr7t-">g</span> is <span
|
||
|
class="ptmri7t-">monomorphic in the type variable</span> <span
|
||
|
class="cmmi-10">a</span>.
|
||
|
<a
|
||
|
id="dx10-92001"></a>
|
||
|
<p class="noindent"> The effect of such monomorphism is that the first argument of all applications of <span
|
||
|
class="pcrr7t-">g</span> must be of a single type. For
|
||
|
example, it would be valid for the “<span
|
||
|
class="pcrr7t-">...</span>” to be
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-66">
|
||
|
  (g True, g False)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> (which would, incidentally, force <span
|
||
|
class="pcrr7t-">x</span> to have type <span
|
||
|
class="pcrr7t-">Bool</span>) but invalid for it to be
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-67">
|
||
|
  (g True, g 'c')
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> In general, a type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span> is said to be <span
|
||
|
class="ptmri7t-">monomorphic</span> <a
|
||
|
id="dx10-92002"></a>in the type variable <span
|
||
|
class="cmmi-10">a</span> if <span
|
||
|
class="cmmi-10">a</span> is free in <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> </span><span class="overline"><span
|
||
|
class="cmmi-10">u</span></span><span
|
||
|
class="cmmi-10">.</span><span
|
||
|
class="cmmi-10"> cx</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> t</span>.
|
||
|
<p class="noindent"> It is worth noting that the explicit type signatures provided by Haskell are not powerful enough to express types that
|
||
|
include monomorphic type variables. For example, we cannot write
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-68">
|
||
|
  f x = let
|
||
|
 <br />          g :: a -> b -> ([a],b)
|
||
|
 <br />          g y z = ([x,y], z)
|
||
|
 <br />        in ...
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> because that would claim that <span
|
||
|
class="pcrr7t-">g</span> was polymorphic in both <span
|
||
|
class="pcrr7t-">a</span> and <span
|
||
|
class="pcrr7t-">b</span> (Section <a
|
||
|
href="#x10-810004.4.1">4.4.1<!--tex4ht:ref: type-signatures --></a>). In this program, <span
|
||
|
class="pcrr7t-">g</span> can only be
|
||
|
given a type signature if its first argument is restricted to a type not involving type variables; for example
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-69">
|
||
|
  g :: Int -> b -> ([Int],b)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> This signature would also cause <span
|
||
|
class="pcrr7t-">x</span> to have type <span
|
||
|
class="pcrr7t-">Int</span>.
|
||
|
<p class="noindent">
|
||
|
<h4 class="subsectionHead"><span class="titlemark">4.5.5 </span> <a
|
||
|
id="x10-930004.5.5"></a>The Monomorphism Restriction</h4>
|
||
|
<a
|
||
|
id="dx10-93001"></a>
|
||
|
<p class="noindent"> Haskell places certain extra restrictions on the generalization step, beyond the standard Hindley-Milner restriction
|
||
|
described above, which further reduces polymorphism in particular cases.
|
||
|
<p class="noindent"> The monomorphism restriction depends on the binding syntax of a variable. Recall that a variable is bound by either
|
||
|
a <span
|
||
|
class="ptmri7t-">function binding </span>or a <span
|
||
|
class="ptmri7t-">pattern binding</span>, and that a <span
|
||
|
class="ptmri7t-">simple </span>pattern binding is a pattern binding in which the pattern
|
||
|
consists of only a single variable (Section <a
|
||
|
href="#x10-830004.4.3">4.4.3<!--tex4ht:ref: pattern-bindings --></a>).
|
||
|
<p class="noindent"> The following two rules define the monomorphism restriction:
|
||
|
<div class="center"
|
||
|
>
|
||
|
<p class="noindent">
|
||
|
<div class="fbox"><div class="minipage"><p class="noindent"> <span class="likeparagraphHead"><a
|
||
|
id="x10-940004.5.5"></a>The monomorphism restriction</span>
|
||
|
<dl class="description"><dt class="description">
|
||
|
<span
|
||
|
class="ptmb7t-">Rule 1.</span> </dt><dd
|
||
|
class="description">We say that a given declaration group is <span
|
||
|
class="ptmri7t-">unrestricted </span>if and only if:
|
||
|
<dl class="description"><dt class="description">
|
||
|
<span
|
||
|
class="ptmb7t-">(a):</span> </dt><dd
|
||
|
class="description">every variable in the group is bound by a function binding or a simple pattern binding<a
|
||
|
id="dx10-94001"></a>
|
||
|
(Section <a
|
||
|
href="#x10-860004.4.3.2">4.4.3.2<!--tex4ht:ref: patbind --></a>), <span
|
||
|
class="ptmri7t-">and</span>
|
||
|
</dd><dt class="description">
|
||
|
<span
|
||
|
class="ptmb7t-">(b):</span> </dt><dd
|
||
|
class="description">an explicit type signature is given for every variable in the group that is bound by simple
|
||
|
pattern binding.</dd></dl>
|
||
|
<p class="noindent"> The usual Hindley-Milner restriction on polymorphism is that only type variables that do not
|
||
|
occur free in the environment may be generalized. In addition, <span
|
||
|
class="ptmri7t-">the constrained type variables</span>
|
||
|
<span
|
||
|
class="ptmri7t-">of a restricted declaration group may not be generalized </span>in the generalization step for that
|
||
|
group. (Recall that a type variable is constrained if it must belong to some type class; see
|
||
|
Section <a
|
||
|
href="#x10-900004.5.2">4.5.2<!--tex4ht:ref: generalization --></a>.)
|
||
|
</dd><dt class="description">
|
||
|
<span
|
||
|
class="ptmb7t-">Rule 2.</span> </dt><dd
|
||
|
class="description">Any monomorphic type variables that remain when type inference for an entire module is complete,
|
||
|
are considered <span
|
||
|
class="ptmri7t-">ambiguous</span><a
|
||
|
id="dx10-94002"></a>, and are resolved to particular types using the defaulting rules
|
||
|
(Section <a
|
||
|
href="#x10-790004.3.4">4.3.4<!--tex4ht:ref: default-decls --></a>).</dd></dl> </div></div>
|
||
|
|
||
|
|
||
|
|
||
|
</div>
|
||
|
<p class="noindent"> <span class="likeparagraphHead"><a
|
||
|
id="x10-950004.5.5"></a>Motivation</span>
|
||
|
Rule 1 is required for two reasons, both of which are fairly subtle.
|
||
|
<ul class="itemize1">
|
||
|
<li class="itemize"><span
|
||
|
class="ptmri7t-">Rule 1 prevents computations from being unexpectedly repeated. </span>For example, <span
|
||
|
class="pcrr7t-">genericLength</span> is a standard
|
||
|
function (in library <span
|
||
|
class="pcrr7t-">Data.List</span>) whose type is given by
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-70">
|
||
|
  genericLength :: Num a => [b] -> a
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Now consider the following expression:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-71">
|
||
|
  let { len = genericLength xs } in (len, len)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> It looks as if <span
|
||
|
class="pcrr7t-">len</span> should be computed only once, but without Rule 1 it might be computed twice, once at each
|
||
|
of two different overloadings. If the programmer does actually wish the computation to be repeated, an explicit
|
||
|
type signature may be added:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-72">
|
||
|
  let { len :: Num a => a; len = genericLength xs } in (len, len)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
</li>
|
||
|
<li class="itemize"><span
|
||
|
class="ptmri7t-">Rule</span><span
|
||
|
class="ptmri7t-"> 1 prevents ambiguity. </span>For example, consider the declaration group
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-73">
|
||
|
  [(n,s)] = reads t
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Recall that <span
|
||
|
class="pcrr7t-">reads</span> is a standard function whose type is given by the signature
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-74">
|
||
|
  reads :: (Read a) => String -> [(a,String)]
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Without Rule 1, <span
|
||
|
class="pcrr7t-">n</span> would be assigned the type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span><span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">Read</span><span
|
||
|
class="cmmi-10"> a</span><span
|
||
|
class="cmmi-10">  </span><span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> a</span> and <span
|
||
|
class="pcrr7t-">s</span> the type <span
|
||
|
class="cmsy-10">∀</span><span
|
||
|
class="cmmi-10"> a.</span> <span
|
||
|
class="pcrr7t-">Read</span><span
|
||
|
class="cmmi-10"> a</span>
|
||
|
<span
|
||
|
class="cmsy-10">⇒</span> <span
|
||
|
class="cmmi-10"> </span><span
|
||
|
class="pcrr7t-">String</span>. The latter is an invalid type, because it is inherently ambiguous. It is not possible to determine at
|
||
|
what overloading to use <span
|
||
|
class="pcrr7t-">s</span>, nor can this be solved by adding a type signature for <span
|
||
|
class="pcrr7t-">s</span>. Hence, when <span
|
||
|
class="ptmri7t-">non-simple</span>
|
||
|
pattern bindings<a
|
||
|
id="dx10-95001"></a> are used (Section <a
|
||
|
href="#x10-860004.4.3.2">4.4.3.2<!--tex4ht:ref: patbind --></a>), the types inferred are always monomorphic in their constrained
|
||
|
type variables, irrespective of whether a type signature is provided. In this case, both <span
|
||
|
class="pcrr7t-">n</span> and <span
|
||
|
class="pcrr7t-">s</span> are monomorphic
|
||
|
in <span
|
||
|
class="cmmi-10">a</span>.
|
||
|
<p class="noindent"> The same constraint applies to pattern-bound functions. For example, in
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-75">
|
||
|
  (f,g) = ((+),(-))
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> both <span
|
||
|
class="pcrr7t-">f</span> and <span
|
||
|
class="pcrr7t-">g</span> are monomorphic regardless of any type signatures supplied for <span
|
||
|
class="pcrr7t-">f</span> or <span
|
||
|
class="pcrr7t-">g</span>.</li></ul>
|
||
|
<p class="noindent"> Rule 2 is required because there is no way to enforce monomorphic use of an <span
|
||
|
class="ptmri7t-">exported </span>binding, except by
|
||
|
performing type inference on modules outside the current module. Rule 2 states that the exact types of all the
|
||
|
variables bound in a module must be determined by that module alone, and not by any modules that import it.
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-76">
|
||
|
  module M1(len1) where
|
||
|
 <br />    default( Int, Double )
|
||
|
 <br />    len1 = genericLength "Hello"
|
||
|
 <br />
|
||
|
 <br />  module M2 where
|
||
|
 <br />    import M1(len1)
|
||
|
 <br />    len2 = (2⋆len1) :: Rational
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> When type inference on module <span
|
||
|
class="pcrr7t-">M1</span> is complete, <span
|
||
|
class="pcrr7t-">len1</span> has the monomorphic type <span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> =></span><span
|
||
|
class="pcrr7t-"> a</span> (by Rule 1). Rule
|
||
|
2 now states that the monomorphic type variable <span
|
||
|
class="pcrr7t-">a</span> is ambiguous, and must be resolved using the defaulting rules of
|
||
|
Section <a
|
||
|
href="#x10-790004.3.4">4.3.4<!--tex4ht:ref: default-decls --></a>. Hence, <span
|
||
|
class="pcrr7t-">len1</span> gets type <span
|
||
|
class="pcrr7t-">Int</span>, and its use in <span
|
||
|
class="pcrr7t-">len2</span> is type-incorrect. (If the above code is actually what
|
||
|
is wanted, a type signature on <span
|
||
|
class="pcrr7t-">len1</span> would solve the problem.)
|
||
|
<p class="noindent"> This issue does not arise for nested bindings, because their entire scope is visible to the compiler.
|
||
|
<p class="noindent"> <span class="likeparagraphHead"><a
|
||
|
id="x10-960004.5.5"></a>Consequences</span>
|
||
|
The monomorphism rule has a number of consequences for the programmer. Anything defined with function syntax
|
||
|
usually generalizes as a function is expected to. Thus in
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-77">
|
||
|
  f x y = x+y
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> the function <span
|
||
|
class="pcrr7t-">f</span> may be used at any overloading in class <span
|
||
|
class="pcrr7t-">Num</span>. There is no danger of recomputation here. However, the
|
||
|
same function defined with pattern syntax:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-78">
|
||
|
  f = \x -> \y -> x+y
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> requires a type signature if <span
|
||
|
class="pcrr7t-">f</span> is to be fully overloaded. Many functions are most naturally defined using simple
|
||
|
pattern bindings; the user must be careful to affix these with type signatures to retain full overloading. The standard
|
||
|
prelude contains many examples of this:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-79">
|
||
|
  sum  :: (Num a) => [a] -> a
|
||
|
 <br />  sum  =  foldl (+) 0  
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Rule 1 applies to both top-level and nested definitions. Consider
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-80">
|
||
|
  module M where
|
||
|
 <br />    len1 = genericLength "Hello"
|
||
|
 <br />    len2 = (2⋆len1) :: Rational
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> Here, type inference finds that <span
|
||
|
class="pcrr7t-">len1</span> has the monomorphic type (<span
|
||
|
class="pcrr7t-">Num</span><span
|
||
|
class="pcrr7t-"> a</span><span
|
||
|
class="pcrr7t-"> =></span><span
|
||
|
class="pcrr7t-"> a</span>); and the type variable <span
|
||
|
class="pcrr7t-">a</span> is resolved
|
||
|
to <span
|
||
|
class="pcrr7t-">Rational</span> when performing type inference on <span
|
||
|
class="pcrr7t-">len2</span>.
|
||
|
<p class="noindent">
|
||
|
<h3 class="sectionHead"><span class="titlemark">4.6 </span> <a
|
||
|
id="x10-970004.6"></a>Kind Inference</h3>
|
||
|
<a
|
||
|
id="dx10-97001"></a>
|
||
|
<a
|
||
|
id="dx10-97002"></a>
|
||
|
<p class="noindent"> This section describes the rules that are used to perform <span
|
||
|
class="ptmri7t-">kind inference</span>, i.e. to calculate a suitable kind for each type
|
||
|
constructor and class appearing in a given program.
|
||
|
<p class="noindent"> The first step in the kind inference process is to arrange the set of datatype, synonym, and class definitions into
|
||
|
dependency groups. This can be achieved in much the same way as the dependency analysis for value declarations
|
||
|
that was described in Section <a
|
||
|
href="#x10-880004.5">4.5<!--tex4ht:ref: dependencyanalysis --></a>. For example, the following program fragment includes the definition of a datatype
|
||
|
constructor <span
|
||
|
class="pcrr7t-">D</span>, a synonym <span
|
||
|
class="pcrr7t-">S</span> and a class <span
|
||
|
class="pcrr7t-">C</span>, all of which would be included in the same dependency group:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-81">
|
||
|
  data C a => D a = Foo (S a)
|
||
|
 <br />  type S a = [D a]
|
||
|
 <br />  class C a where
|
||
|
 <br />      bar :: a -> D a -> Bool
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> The kinds of variables, constructors, and classes within each group are determined using standard techniques of type
|
||
|
inference and kind-preserving unification <span class="cite">[<a
|
||
|
href="haskellli3.html#Xjones:cclasses">8</a>]</span>. For example, in the definitions above, the parameter <span
|
||
|
class="pcrr7t-">a</span> appears
|
||
|
as an argument of the function constructor <span
|
||
|
class="pcrr7t-">(->)</span> in the type of <span
|
||
|
class="pcrr7t-">bar</span> and hence must have kind <span
|
||
|
class="cmsy-10">∗</span>. It
|
||
|
follows that both <span
|
||
|
class="pcrr7t-">D</span> and <span
|
||
|
class="pcrr7t-">S</span> must have kind <span
|
||
|
class="cmsy-10">∗→∗ </span>and that every instance of class <span
|
||
|
class="pcrr7t-">C</span> must have kind
|
||
|
<span
|
||
|
class="cmsy-10">∗</span>.
|
||
|
<p class="noindent"> It is possible that some parts of an inferred kind may not be fully determined by the corresponding definitions; in
|
||
|
such cases, a default of <span
|
||
|
class="cmsy-10">∗ </span>is assumed. For example, we could assume an arbitrary kind <span
|
||
|
class="cmmi-10">κ </span>for the <span
|
||
|
class="pcrr7t-">a</span> parameter in each
|
||
|
of the following examples:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-82">
|
||
|
  data App f a = A (f a)
|
||
|
 <br />  data Tree a  = Leaf | Fork (Tree a) (Tree a)
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> This would give kinds <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmmi-10">κ </span><span
|
||
|
class="cmsy-10">→∗</span><span
|
||
|
class="cmr-10">) </span><span
|
||
|
class="cmsy-10">→ </span><span
|
||
|
class="cmmi-10">κ </span><span
|
||
|
class="cmsy-10">→∗ </span>and <span
|
||
|
class="cmmi-10">κ </span><span
|
||
|
class="cmsy-10">→∗ </span>for <span
|
||
|
class="pcrr7t-">App</span> and <span
|
||
|
class="pcrr7t-">Tree</span>, respectively, for any kind <span
|
||
|
class="cmmi-10">κ</span>, and would
|
||
|
require an extension to allow polymorphic kinds. Instead, using the default binding <span
|
||
|
class="cmmi-10">κ </span><span
|
||
|
class="cmr-10">= </span><span
|
||
|
class="cmsy-10">∗</span>, the actual kinds for these
|
||
|
two constructors are <span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmsy-10">∗→∗</span><span
|
||
|
class="cmr-10">) </span><span
|
||
|
class="cmsy-10">→∗→∗ </span>and <span
|
||
|
class="cmsy-10">∗→∗</span>, respectively.
|
||
|
<p class="noindent"> Defaults are applied to each dependency group without consideration of the ways in which particular type
|
||
|
constructor constants or classes are used in later dependency groups or elsewhere in the program. For example,
|
||
|
adding the following definition to those above does not influence the kind inferred for <span
|
||
|
class="pcrr7t-">Tree</span> (by changing it to
|
||
|
<span
|
||
|
class="cmr-10">(</span><span
|
||
|
class="cmsy-10">∗→∗</span><span
|
||
|
class="cmr-10">) </span><span
|
||
|
class="cmsy-10">→∗</span>, for instance), and instead generates a static error because the kind of <span
|
||
|
class="pcrr7t-">[]</span>, <span
|
||
|
class="cmsy-10">∗→∗</span>, does not match the
|
||
|
kind <span
|
||
|
class="cmsy-10">∗ </span>that is expected for an argument of <span
|
||
|
class="pcrr7t-">Tree</span>:
|
||
|
<div class="quote">
|
||
|
|
||
|
|
||
|
|
||
|
<div class="verbatim" id="verbatim-83">
|
||
|
  type FunnyTree = Tree []     -- invalid
|
||
|
</div>
|
||
|
<p class="noindent"></div>
|
||
|
<p class="noindent"> This is important because it ensures that each constructor and class are used consistently with the same kind
|
||
|
whenever they are in scope.
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<!--l. 7--><div class="crosslinks"><p class="noindent">[<a
|
||
|
href="haskellch5.html" >next</a>] [<a
|
||
|
href="haskellch3.html" >prev</a>] [<a
|
||
|
href="haskellch3.html#tailhaskellch3.html" >prev-tail</a>] [<a
|
||
|
href="haskellch4.html" >front</a>] [<a
|
||
|
href="haskellpa1.html#haskellch4.html" >up</a>] </p></div>
|
||
|
<p class="noindent"> <a
|
||
|
id="tailhaskellch4.html"></a>
|
||
|
</body></html>
|