{"componentChunkName":"component---src-templates-post-tsx","path":"/bottom-type-in-haskell","result":{"data":{"markdownRemark":{"html":"<p>今天偶然遇到了一个奇怪的符号 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">⊥</mi></mrow><annotation encoding=\"application/x-tex\">\\bot</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord\">⊥</span></span></span></span>，仔细查找了一下才发现这是 Haskell 中的一个特殊类型的值，其作用是用于表达<ruby>发散项<rp>(</rp><rt>divergent term</rt><rp>)</rp></ruby>，也可以理解为不可计算的项。我之前在《<ruby>类型与程序设计语言<rp>(</rp><rt>Types and Programming Lanuages</rt><rp>)</rp></ruby>》上见过这个词，感觉可以在这里解释，干脆就把原文引用过来。</p>\n<blockquote>\n<p>Recall that a term that cannot take a step under the evaluation relation is called a <strong>normal form</strong>. Interestingly, some terms cannot be evaluated to a normal form. For example, the divergent combinator <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ω</mi><mo>=</mo><mo stretchy=\"false\">(</mo><mi>λ</mi><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>x</mi><mi>x</mi><mo stretchy=\"false\">)</mo><mo stretchy=\"false\">(</mo><mi>λ</mi><mi>x</mi><mi mathvariant=\"normal\">.</mi><mi>x</mi><mi>x</mi><mo stretchy=\"false\">)</mo></mrow><annotation encoding=\"application/x-tex\">\\omega = (\\lambda x. x x) (\\lambda x. x x)</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">ω</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2777777777777778em;\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em;\"></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">λ</span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">λ</span><span class=\"mord mathnormal\">x</span><span class=\"mord\">.</span><span class=\"mord mathnormal\">x</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span></span></span></span> contains just one redex, and reducing this redex yields exactly <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>ω</mi></mrow><annotation encoding=\"application/x-tex\">\\omega</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.43056em;vertical-align:0em;\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.03588em;\">ω</span></span></span></span> again! Terms with no normal form are said to diverge.</p>\n</blockquote>\n<p>至于为什么不能表达，<a href=\"https://wiki.haskell.org/Bottom\" target=\"_blank\" rel=\"noopener noreferrer\">Haskell Wiki 上的解释</a>是如果可以表达这样的项，那么编译器就可以解决<a href=\"https://en.wikipedia.org/wiki/Halting_problem\" target=\"_blank\" rel=\"noopener noreferrer\">停机问题</a>了（我感觉这个证明应该会比较简单，改天水一篇博客文章）。下面是 <span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">⊥</mi></mrow><annotation encoding=\"application/x-tex\">\\bot</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord\">⊥</span></span></span></span> 的一个常见定义。</p>\n<div class=\"gatsby-highlight\" data-language=\"haskell\"><pre class=\"language-haskell\"><code class=\"language-haskell\"><span class=\"token hvariable\">bottom</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">bottom</span></code></pre></div>\n<p>因为它不断引用自身，所以在 GHCi 中打印 <code class=\"language-text\">bottom</code> 会进入死循环。手头有 GHCi 的读者可以试一下。同时，<span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi mathvariant=\"normal\">⊥</mi></mrow><annotation encoding=\"application/x-tex\">\\bot</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.69444em;vertical-align:0em;\"></span><span class=\"mord\">⊥</span></span></span></span> 是可以转换为任何类型的，这一点上和 <code class=\"language-text\">undefined</code> 类似。</p>","frontmatter":{"title":"Bottom Type in Haskell","date":"March 12, 2019","tags":["Haskell","type-system","functional-programming"],"language":"zh-Hans"}},"site":{"siteMetadata":{"title":"Luyu Cheng"}}},"pageContext":{"id":"2ba016f0-da15-540d-bffb-762a6ebaaeea"}},"staticQueryHashes":["3649515864","63159454","684267432"]}