﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-馒头</title><link>http://www.blogjava.net/sizilove/</link><description /><language>zh-cn</language><lastBuildDate>Thu, 07 May 2026 06:32:49 GMT</lastBuildDate><pubDate>Thu, 07 May 2026 06:32:49 GMT</pubDate><ttl>60</ttl><item><title>lambda演算笔记（转载）</title><link>http://www.blogjava.net/sizilove/archive/2007/07/16/130611.html</link><dc:creator>馒头</dc:creator><author>馒头</author><pubDate>Mon, 16 Jul 2007 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/sizilove/archive/2007/07/16/130611.html</guid><wfw:comment>http://www.blogjava.net/sizilove/comments/130611.html</wfw:comment><comments>http://www.blogjava.net/sizilove/archive/2007/07/16/130611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sizilove/comments/commentRss/130611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sizilove/services/trackbacks/130611.html</trackback:ping><description><![CDATA[<h1 align=center><font style="FONT-SIZE: 24px">简单&#955;演算</font></h1>
<h1><font style="FONT-SIZE: 22px"><font face="Courier New">Lambda演算</font>简介：</font></h1>
<p><font color=#ff00ff><strong>Wikipedia</strong><strong>（维基百科全书）中关于</strong><strong>lambda</strong><strong>演算的解释如下：</strong></font></p>
<p>The lambda calculus is a <a title="Formal system" href="http://en.wikipedia.org/wiki/Formal_system"><u><font color=#000033>formal system</font></u></a> designed to investigate <a title="Function (mathematics)" href="http://en.wikipedia.org/wiki/Function_%28mathematics%29"><u><font color=#000033>function</font></u></a> definition, function application, and <a title=Recursion href="http://en.wikipedia.org/wiki/Recursion"><u><font color=#000033>recursion</font></u></a>. It was introduced by <a title="Alonzo Church" href="http://en.wikipedia.org/wiki/Alonzo_Church"><u><font color=#000033>Alonzo Church</font></u></a> and <a title="Stephen Cole Kleene" href="http://en.wikipedia.org/wiki/Stephen_Cole_Kleene"><u><font color=#000033>Stephen Cole Kleene</font></u></a> in the 1930s; Church used the lambda calculus in 1936 to give a negative answer to the <a title=Entscheidungsproblem href="http://en.wikipedia.org/wiki/Entscheidungsproblem"><u><font color=#000033>Entscheidungsproblem</font></u></a>. The calculus can be used to cleanly define what a <a title="Computable function" href="http://en.wikipedia.org/wiki/Computable_function"><u><font color=#000033>computable function</font></u></a> is. The question of whether two lambda calculus expressions are equivalent cannot be solved by a general algorithm, and this was the first question, even before the <a title="Halting problem" href="http://en.wikipedia.org/wiki/Halting_problem"><u><font color=#000033>halting problem</font></u></a>, for which undecidability could be proved. Lambda calculus has greatly influenced <a title="Functional programming" href="http://en.wikipedia.org/wiki/Functional_programming"><u><font color=#000033>functional programming languages</font></u></a>, especially <a title="Lisp programming language" href="http://en.wikipedia.org/wiki/Lisp_programming_language"><u><font color=#000033>Lisp</font></u></a>.</p>
<p><strong>&#955;</strong><strong>演算</strong>是一套用于研究<a title=函数 href="http://www.wikilib.com/wiki/%E5%87%BD%E6%95%B0"><u><font color=#000033>函数</font></u></a>定义、函数应用和<a title=递归 href="http://www.wikilib.com/wiki/%E9%80%92%E5%BD%92"><u><font color=#000033>递归</font></u></a>的<a title=形式系统 href="http://www.wikilib.com/wiki?title=%E5%BD%A2%E5%BC%8F%E7%B3%BB%E7%BB%9F&amp;action=edit"><u><font color=#000033>形式系统</font></u></a>。它由 <a title="Alonzo Church" href="http://www.wikilib.com/wiki/Alonzo_Church"><u><font color=#000033>Alonzo Church</font></u></a> 和 <a title="Stephen Cole Kleene" href="http://www.wikilib.com/wiki?title=Stephen_Cole_Kleene&amp;action=edit"><u><font color=#000033>Stephen Cole Kleene</font></u></a> 在 20 世纪三十年代引入，Church 运用 lambda 演算在 1936 年给出 <a title=判定性问题 href="http://www.wikilib.com/wiki?title=%E5%88%A4%E5%AE%9A%E6%80%A7%E9%97%AE%E9%A2%98&amp;action=edit"><u><font color=#000033>判定性问题</font></u></a> (Entscheidungsproblem) 的一个否定的答案。这种演算可以用来清晰地定义什么是一个<a title=可计算函数 href="http://www.wikilib.com/wiki/%E5%8F%AF%E8%AE%A1%E7%AE%97%E5%87%BD%E6%95%B0"><u><font color=#000033>可计算函数</font></u></a>。关于两个 lambda 演算表达式是否等价的命题无法通过一个通用的算法来解决，这是不可判定性能够证明的头一个问题，甚至还在<a title=停机问题 href="http://www.wikilib.com/wiki/%E5%81%9C%E6%9C%BA%E9%97%AE%E9%A2%98"><u><font color=#000033>停机问题</font></u></a>之先。Lambda 演算对<a title=函數式編程 href="http://www.wikilib.com/wiki/%E5%87%BD%E6%95%B8%E5%BC%8F%E7%B7%A8%E7%A8%8B"><u><font color=#000033>函数式编程</font></u></a>有巨大的影响，特别是<a title=Lisp href="http://www.wikilib.com/wiki/Lisp"><u><font color=#000033>Lisp 语言</font></u></a>。</p>
<p><font color=#ff00ff><strong>同时，数理逻辑中对于</strong><strong>lambda</strong><strong>演算的介绍就简单得多：</strong></font></p>
<p>&#955;-演算可以说是最简单、最小的一个形式系统。它是在二十世纪三十年代由<a title="Alonzo Church" href="http://en.wikipedia.org/wiki/Alonzo_Church"><u><font color=#000033>Alonzo Church</font></u></a> 和 <a title="Stephen Cole Kleene" href="http://en.wikipedia.org/wiki/Stephen_Cole_Kleene"><u><font color=#000033>Stephen Cole Kleene</font></u></a>发明的。至今，在欧洲得到了广泛的发展。可以说，欧洲的计算机科学是从&#955;-演算开始的，而现在仍然是欧洲计算机科学的基础，首先它是函数式程序理论的基础，而后，在&#955;-演算的基础上，发展起来的&#960;-演算、&#967;-演算，成为近年来的并发程序的理论工具之一，许多经典的并发程序模型就是以&#960;-演算为框架的。</p>
<p>Lambda 演算可以被称为最小的通用程序设计语言。它包括一条变换规则 (变量替换) 和一条函数定义方式，Lambda 演算之通用在于，任何一个可计算函数都能用这种形式来表达和求值。因而，它是等价于<a title=图灵机 href="http://www.wikilib.com/wiki/%E5%9B%BE%E7%81%B5%E6%9C%BA"><u><font color=#000033>图灵机</font></u></a>的。尽管如此，Lambda 演算强调的是变换规则的运用，而非实现它们的具体机器。可以认为这是一种更接近软件而非硬件的方式。 Lambda演算表达了两个计算机计算中最基本的概念&#8220;代入&#8221;和&#8220;置换&#8221;。&#8220;代入&#8221;我们一般理解为函数调用，或者是用实参代替函数中的形参；&#8220;置换&#8221;我们一般理解为变量换名规则。后面会讲到，&#8220;代入&#8221;就是用lambda演算中的&#946;-归约概念。而&#8220;替换&#8221;就是lambda演算中的&#945;-变换。</p>
<div>
<table cellPadding=0 border=0>
    <tbody>
        <tr>
            <td width=539>
            <h2>目录</h2>
            <ul type=disc>
                <li>1 历史
                <li>2 非形式化的描述
                <li>3 形式化的定义
                <li style="LIST-STYLE-TYPE: none">
                <ul type=circle>
                    <li>3.1字母表
                    <li>3.2 &#955;-项
                    <li>3.3 公式
                    <li>3.4 &#955;-项中的变量自由出现法则
                    <li>3.5 &#955; x的控制域 </li>
                </ul>
                <li>4 变换与等价关系
                <li style="LIST-STYLE-TYPE: none">
                <ul type=circle>
                    <li>4.1 &#945;-变换
                    <li>4.2<a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#.CE.B2-.E5.BD.92.E7.BA.A6"></a> &#946;-归约
                    <li>4.3 等价关系
                    <li>4.4 &#951;-变换 </li>
                </ul>
                <li>5 &#955;演算的操作语义
                <li>6 &#955;演算的公理化和定理
                <li style="LIST-STYLE-TYPE: none">
                <ul type=circle>
                    <li>6.1 &#955;演算的公理<a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#.CE.B1-.E5.8F.98.E6.8D.A2"></a>
                    <li>6.2 不动点理论
                    <li>6.3 Church-Rosser定理及其等价定理 </li>
                </ul>
                <li>7 lambda 演算中的程序设计<a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#lambda_.E6.BC.94.E7.AE.97.E4.B8.AD.E7.9A.84.E8.BF.90.E7.AE.97"></a>
                <li style="LIST-STYLE-TYPE: none">
                <ul type=circle>
                    <li>7.1 自然数与运算
                    <li>7.2 逻辑与断言
                    <li>7.3 递归 </li>
                </ul>
                <li>8 参考文献和外部链接 </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
</div>
<h2><a name=.E5.8E.86.E5.8F.B2></a>1 历史</h2>
<p>最开始，Church 试图创制一套完整的形式系统作为数学的基础，当他发现这个系统易受<a title=罗素悖论 href="http://www.wikilib.com/wiki/%E7%BD%97%E7%B4%A0%E6%82%96%E8%AE%BA"><u><font color=#000033>罗素悖论</font></u></a>的影响时，就把 lambda 演算单独分离出来，用于研究<a title=可计算性 href="http://www.wikilib.com/wiki/%E5%8F%AF%E8%AE%A1%E7%AE%97%E6%80%A7"><u><font color=#000033>可计算性</font></u></a>，最终导致了他对<a title=判定性问题 href="http://www.wikilib.com/wiki?title=%E5%88%A4%E5%AE%9A%E6%80%A7%E9%97%AE%E9%A2%98&amp;action=edit"><u><font color=#000033>判定性问题</font></u></a>的否定回答。</p>
<h2><a name=.E9.9D.9E.E5.BD.A2.E5.BC.8F.E5.8C.96.E7.></a>2 非形式化的描述</h2>
<p>在 lambda 演算中，每个表达式都代表一个只有单独参数的函数，这个函数的参数本身也是一个只有单一参数的函数，同时，函数的值是又一个只有单一参数的函数。函数是通过 lambda 表达式匿名地定义的，这个表达式说明了此函数将对其参数进行什么操作。例如，&#8220;加 2&#8221;函数 <em>f</em>(<em>x</em>) = <em>x</em> + 2 可以用 lambda 演算表示为 &#955; <em>x</em>. <em>x</em> + 2 (&#955; <em>y</em>. <em>y</em> + 2 也是一样的，参数的取名无关紧要) 而 <em>f</em>(3) 的值可以写作 (&#955; <em>x</em>. <em>x</em> + 2) 3。函数的作用 (application) 是<a title=左结合 href="http://www.wikilib.com/wiki?title=%E5%B7%A6%E7%BB%93%E5%90%88&amp;action=edit"><u><font color=#000033>左结合</font></u></a>的：<em>f</em> <em>x</em> <em>y</em> = (<em>f</em> <em>x</em>) <em>y</em>。考虑这么一个函数：它把一个函数作为参数，这个函数将被作用在 3 上：&#955; <em>f</em>. <em>f</em> 3。如果把这个 (用函数作参数的) 函数作用于我们先前的&#8220;加 2&#8221;函数上：(&#955; <em>f</em>. <em>f</em> 3) (&#955; <em>x</em>. <em>x</em>+2)，则明显地，下述三个表达式：</p>
<p>(&#955; <em>f</em>. <em>f</em> 3) (&#955; <em>x</em>. <em>x</em>+2)&nbsp;&nbsp; 与 &nbsp;&nbsp; (&#955; <em>x</em>. <em>x</em> + 2) 3 &nbsp;&nbsp; 与 &nbsp;&nbsp; 3 + 2</p>
<p>是等价的。有两个参数的函数可以通过 lambda 演算这么表达：一个单一参数的函数的返回值又是一个单一参数的函数 (参见 <a title=Currying href="http://www.wikilib.com/wiki/Currying"><u><font color=#000033>Currying</font></u></a>)。例如，函数 <em>f</em>(<em>x</em>, <em>y</em>) = <em>x</em> - <em>y</em> 可以写作 &#955; <em>x</em>. &#955; <em>y</em>. <em>x</em> - <em>y</em>。下述三个表达式：</p>
<p>(&#955; <em>x</em>. &#955; <em>y</em>. <em>x</em> - <em>y</em>) 7 2 &nbsp;&nbsp; 与 &nbsp;&nbsp; (&#955; <em>y</em>. 7 - <em>y</em>) 2 &nbsp;&nbsp; 与 &nbsp;&nbsp; 7 - 2</p>
<p>也是等价的。然而这种 lambda 表达式之间的等价性无法找到一个通用的函数来判定。</p>
<p>并非所有的 lambda 表达式都可以规约至上述那样的确定值，考虑</p>
<p>(&#955; <em>x</em>. <em>x</em> <em>x</em>) (&#955; <em>x</em>. <em>x</em> <em>x</em>)</p>
<p>或</p>
<p>(&#955; <em>x</em>. <em>x</em> <em>x</em> <em>x</em>) (&#955; <em>x</em>. <em>x</em> <em>x</em> <em>x</em>)</p>
<p>然后试图把第一个函数作用在它的参数上。 (&#955; <em>x</em>. <em>x</em> <em>x</em>) 被称为 &#969; <a title=组合子逻辑 href="http://www.wikilib.com/wiki/%E7%BB%84%E5%90%88%E5%AD%90%E9%80%BB%E8%BE%91"><u><font color=#000033>组合子</font></u></a>，((&#955; <em>x</em>. <em>x</em> <em>x</em>) (&#955; <em>x</em>. <em>x</em> <em>x</em>)) 被称为 &#937;，而 ((&#955; <em>x</em>. <em>x</em> <em>x</em> <em>x</em>) (&#955; <em>x</em>. <em>x</em> <em>x</em> <em>x</em>)) 被称为 &#937;<sub>2</sub>，以此类推。</p>
<p>若仅形式化函数作用的概念而不允许 lambda 表达式，就得到了<a title=组合子逻辑 href="http://www.wikilib.com/wiki/%E7%BB%84%E5%90%88%E5%AD%90%E9%80%BB%E8%BE%91"><u><font color=#000033>组合子逻辑</font></u></a>。</p>
<h2><a name=.E5.BD.A2.E5.BC.8F.E5.8C.96.E5.AE.9A.E4.></a>3 形式化的定义</h2>
<h3>3.1字母表</h3>
<p>lambda演算系统中合法的字符如下：</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;标识符 (identifier) 的<a title=可数无穷 href="http://www.wikilib.com/wiki/%E5%8F%AF%E6%95%B0%E6%97%A0%E7%A9%B7"><u><font color=#000033>可数无穷</font></u></a><a title=集合 href="http://www.wikilib.com/wiki/%E9%9B%86%E5%90%88"><u><font color=#000033>集合</font></u></a>：{ x1，x2，x3，&#8230;}变元（变元的数量是无穷的，不能在有限步骤内穷举，这个很重要，后面有定理是根据这一点证明的）</p>
<p>2.&nbsp;&nbsp;&nbsp; &#224; 归约</p>
<p>3.&nbsp;&nbsp;&nbsp; &nbsp;等价</p>
<p>4.&nbsp;&nbsp;&nbsp; &#955;，（，）&nbsp; （辅助工具符号，一共有三个，&#955;和左括号右括号）</p>
<h2><font style="FONT-SIZE: 18px; FONT-FAMILY: 宋体">&nbsp;&nbsp;&nbsp; 所有能够在lambda演算系统中出现的合法符号只有以上四种，其他符号都是非法的。例如&#955;x.x+2，如果没有其他对于＋符号的说明，那么这就是一个非法的&#955;演算表达式。</font></h2>
<h2>3.2 &#955;-项</h2>
<p>&#955;-项在一些文章中也称为&#955;表达式（lambda expression），它是由上面字母表中的合法字符组成的表达式，合法的表达式组成规则如下：</p>
<p>1.&nbsp;&nbsp;&nbsp;任一个变元是一个项</p>
<p>2.&nbsp;&nbsp;&nbsp;若M，N是项，则（MN）也是一个项&nbsp; （function application，函数应用）</p>
<p>3.&nbsp;&nbsp;&nbsp;若M是一个项，而x是一个变元，则（&#955;x.M）也是一个项&nbsp; （function abstraction，函数抽象）</p>
<p>4.&nbsp;&nbsp;&nbsp;仅仅由以上规则归纳定义得到的符号串是项</p>
<p>则所有的 lambda 表达式可以通过下述以 <a title=巴科斯范式 href="http://www.wikilib.com/wiki/%E5%B7%B4%E7%A7%91%E6%96%AF%E8%8C%83%E5%BC%8F"><u><font color=#000033>BNF</font></u></a> 范式表达的<a title=上下文无关文法 href="http://www.wikilib.com/wiki/%E4%B8%8A%E4%B8%8B%E6%96%87%E6%97%A0%E5%85%B3%E6%96%87%E6%B3%95"><u><font color=#000033>上下文无关文法</font></u></a>描述：</p>
<ol type=1>
    <li>&lt;expr&gt;&nbsp;::= &lt;identifier&gt;
    <li>&lt;expr&gt;&nbsp;::= (&#955; &lt;identifier&gt; . &lt;expr&gt;)
    <li>&lt;expr&gt;&nbsp;::= (&lt;expr&gt; &lt;expr&gt;) </li>
</ol>
<p>说明1：通常，lambda 抽象 (规则 2) 和函数作用 (规则 3) 中的括号在不会产生歧义的情况下可以省略。如下假定保证了不会产生歧义：</p>
<p>(1) 函数的作用是左结合的。</p>
<p>&nbsp;(2) lambda 操作符被绑定到它后面的整个表达式。</p>
<p>例如，表达式 ((&#955; <em>x</em>. (<em>x</em> <em>x</em>)) (&#955; <em>y</em>. <em>y</em>)) 可以简写成 (&#955; <em>x</em>. <em>x</em> <em>x</em>) &#955; <em>y</em>.<em>y</em>。</p>
<p>说明2：(&#955;x.M)这样的&#955;-项被称为函数抽象，原因是它常常就是一个函数的定义，函数的参数就是变量x，函数体就是M，而函数名称则是匿名的。用一个不恰当的比喻来说，我们通常认为的函数f(x)=x+2，可以被表达为&#955;x.x+2。因为＋是未定义的，所以这个比喻只是为了方便理解而已。</p>
<p>说明3：MN这样的&#955;-项被称为函数应用，原因是它表达了将M这个函数应用到N这个概念。沿用上面的例子f(x)=x+2，那么f(2)=2+2；同样的&#955;x.x+2表达了f(x)的概念，那么（&#955;x.x+2）2表达了f(2)的概念。其中M＝&#955;x.x+2，N＝2，所以MN＝（&#955;x.x+2）2。</p>
<p>说明4：注意说明3只是为了方便理解，但是还存在很多与直观理解不符合的地方。例如xy也是一个合法的&#955;-项，它们也是MN形式的，不过x和y都仅仅是一个变量而已，谈不上函数代入。</p>
<p>说明4：这里的另一难点就是要区分变量和元变量，如：M＝&#955;x.x，这里x为变量，是我们在语法系统中定义了的，而M为元变量，没有在语法系统中定义，是我们用来表示的助记符。我们必须根据上下文来区分谁是变量，谁是元变量。</p>
<p>上面是&#955;-项的形式化定义，有一些是可以与函数理论直观联系的，而另一些只是说明这个&#955;-项是合法的，不一定有直观的字面意义。</p>
<h2>3.3 公式</h2>
<p>若M，N是&#955;-项，则M&#224;N，M N是公式。</p>
<h2>3.4 &#955;-项中的变量自由出现法则</h2>
<p>类似 &#955; x. (x y) 这样的 lambda 表达式并未定义一个函数，因为变量 y 的出现是自由的，即它并没有被绑定到表达式中的任何一个 &#955; 上。在一个&#955;-项中，变量要么是自由出现的，要么是被一个&#955;符号绑定的。还是以函数的方式来理解变量的自由出现和绑定。例如f(x)=xy这个函数，我们知道x是和函数f相关的，因为它是f的形参，而y则是和f无关的。那么在&#955;x.xy这个&#955;-项中，x就是被&#955;绑定的，而y则是自由出现的变量。</p>
<p>直观的理解，被绑定的变量就是作为某个函数形参的变量，而自由变量则是不作为任何函数形参的变量。</p>
<p>Lambda变量绑定规则：</p>
<p>1.&nbsp;&nbsp;&nbsp;在表达式x中，如果x本身就是一个变量，那么x就是一个单独的自由出现。</p>
<p>2.&nbsp;&nbsp;&nbsp;在表达式&#955; x. E中，自由出现就是E中所有的除了x的自由出现。这种情况下在E中所有x的出现都称为被表达式中x前面的那个&#955;所绑定。</p>
<p>3.&nbsp;&nbsp;&nbsp;在表达式(MN )中，变量的自由出现就是M和N中所有变量的自由出现。</p>
<p>另一种关于变量的自由出现的规则也许更直接：</p>
<p>1.&nbsp;&nbsp;&nbsp;free(x) = x</p>
<p>2.&nbsp;&nbsp; free(MN) = free(M) 萛\nfree(N)</p>
<p>3.&nbsp;&nbsp; free(lx " M) = free(M) &#8211; {x}</p>
<p>为什么要花大力气来给出变量自由出现的规则，是因为后面的很多地方要用到变量的自由出现的概念。例如&#945;-变换和&#946;-归约。</p>
<p>例子：分析&#955;f.&#955;x.fx中变量的自由出现和绑定状况。</p>
<p>&#955;f.&#955;x.fx =&#955;f.E, E=&#955;x.fx</p>
<p>E=&#955;x.A, A=A1A2, A1=f, A2=x</p>
<p>所以在A中f和x都是自由出现的，</p>
<p>所以E中x是绑定&#955; x</p>
<p>所以整个公式中f是绑定第一个&#955; f的。</p>
<p>一个不含自由变量的项称为封闭项；封闭项也称为组合子。最简单的组合子，称为恒等函数：id=&#955;x.x</p>
<h3>3.5 &#955; x的控制域</h3>
<p>来看两个&#955;-项，&#955;x.xx和&#955;x.(xx)有何不同？根据左结合的法则，&#955;x.xx＝(&#955;x.x)x，其中第一个x是被&#955;绑定的，而第二个x则是自由出现的。而&#955;x.(xx)中两个x都是被&#955;绑定的。这表明了两个&#955;-项中&#955;x的控制域是不同的。</p>
<div>我们知道谓词演算中量词也是有控制域的，&#955;x的控制域与它们类似，这里就不给出详细的定义了。其实也很直观。<br></div>
<div>&nbsp;
<p><strong><a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#.E9.9D.9E.E5.BD.A2.E5.BC.8F.E5.8C.96.E7.9A.84.E6.8F.8F.E8.BF.B0"><font style="FONT-SIZE: 20px" color=#000033><u>4 变换与等价关系</u></font></a></strong></p>
<h3><a name=.CE.B1-.E5.8F.98.E6.8D.A2></a>4.1 &#945;-变换</h3>
<p>&#945;-变换规则表达的是，被绑定变量的名称是不重要的。比如说 &#955;<em>x</em>.<em>x</em> 和 &#955;<em>y</em>.<em>y</em> 是同一个函数。因此，将某个函数中的所有约束变量全部换名是可以的。尽管如此，这条规则并非像它看起来这么简单，关于被绑定的变量能否由另一个替换有一系列的限制需要遵循。</p>
<p>首先是一个说明：如果M，N是&#955;-项，x在M中有自由出现，若以N置换M中所有x的自由出现（M中可能含有x的约束出现），我们得到另一个&#955;-项，记为M[x/N]。</p>
<p>&#945;-变换规则如下：</p>
<p>&#955;x.M≌&#955;y.M[x/y]&nbsp; 如果y没有在M中自由出现，并且只要y替换M中的x，都不会被M中的一个&#955;绑定。即：替换的变元不能在M中自由出现，并且也只替换M中的自由变元</p>
<p>这条规则告诉我们，例如 &#955; x. (&#955; x. x) x 这样的表达式和 &#955; y. (&#955; x. x) y 是一样的。</p>
<p>注意：M[x/N]定义出来只是一种记号，它不等于&#945;-变换。既M！≌ M[x/y]</p>
<p>例子：&#955;x.( &#955;x.x)x≌&#955;y.(&#955;x.x)y&nbsp; 但是 ( &#955;x.x)x！≌(&#955;x.x)y</p>
<p>&#945;-变换主要用来表达函数中的变量换名规则，需要注意的是被换名的只能是M（函数体）中变量的自由出现。</p>
<h3><a name=.CE.B2-.E5.BD.92.E7.BA.A6></a>4.2<a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#.CE.B2-.E5.BD.92.E7.BA.A6"></a> &#946;-归约</h3>
<p>&#946;-归约表达的是函数应用或者函数代入的概念。前面提到MN是合法的&#955;-项，那么MN的含义是将M应用到N，通俗的说是将N作为实参代替M中的约束变量，也就是形参。&#946;-归约的规则如下：</p>
<p>(&#955;x.M)N &#224; M[x/N] 如果N中所有变量的自由出现都在M[x/N]中保持自由出现</p>
<p>注意： (lx. ly.(y x))y ?ly.(y y)是错的，应为y在ly.(y x)中不自由出现，这时要归约就应该先用&#945;-变换把ly.(y x)中的y换成其他变元</p>
<p>&#946;-归约是&#955;演算中最重要的概念和规则，它是函数代入这个概念的形式化表示。</p>
<p>一些例子如下：</p>
<p>(lx.ly.y x)(lz.u) ?ly.y(lz.u)</p>
<p>(lx. x x)(lz.u) ?(lz.u) (lz.u)</p>
<p>(ly.y a)((lx. x)(lz.(lu.u) z)) ?(ly.y a)(lz.(lu.u) z)</p>
<p>(ly.y a)((lx. x)(lz.(lu.u) z)) ?(ly.y a)((lx. x)(lz. z))</p>
<p>(ly.y a)((lx. x)(lz.(lu.u) z)) ?((lx. x)(lz.(lu.u) z)) a</p>
<p>需要多加练习才能习惯这种归约。</p>
<p>4.3 等价关系</p>
<p>在 lambda 表达式的集合上定义了一个<a title=等价关系 href="http://www.wikilib.com/wiki/%E7%AD%89%E4%BB%B7%E5%85%B3%E7%B3%BB"><u><font color=#000033>等价关系</font></u></a> (在此用 &nbsp;标注)，&#8220;两个表达式其实表示的是同一个函数&#8221;这样的直觉性判断即由此表述，这种等价关系是通过所谓的&#8220;alpha-变换规则&#8221;和&#8220;beta-归约规则&#8221;得到的。</p>
<p>f g:当且仅当（1）g≌f ;(2)g甪 or f甮 ;(3)存在h，f h且h g之一成立。</p>
<p>&nbsp;关系被定义为满足上述规则的最小等价关系 (即在这个等价关系中减去任何一个映射，它将不再是一个等价关系)。</p>
<h3><a name=.CE.B7-.E5.8F.98.E6.8D.A2></a>4.4 &#951;-变换</h3>
<p>前两条规则之后，还可以加入第三条规则，&#951;-变换，来形成一个新的等价关系。&#951;-变换表达的是<a title=外延性 href="http://www.wikilib.com/wiki/%E5%A4%96%E5%BB%B6%E6%80%A7"><u><font color=#000033>外延性</font></u></a>的概念，在这里外延性指的是，两个函数对于所有的参数得到的结果都一致，当且仅当它们是同一个函数。</p>
<p>&#951;-变换：&#955; <em>x</em> . <em>f</em> <em>x</em> &nbsp;<em>f</em>，只要 <em>x</em> 不是 <em>f</em> 中的自由出现。</p>
<p>f 与 g 外延的等价：对任意lambda 表达式 a，如果有f a &nbsp;g a成立，则f &nbsp;g也成立。</p>
<p>下面说明了为何这条规则和外延性是等价的：（即由&#951;-变换可以证明外延等价，相反由外延等价也可以证明&#951;-变换）</p>
<p><em>f</em> <em>a</em> &nbsp;<em>g</em> <em>a</em> 对所有的 lambda 表达式 <em>a</em> 成立，则当取 <em>a</em> 为在 <em>f</em> 中不是自由出现的变量 <em>x</em> 时，我们有 <em>f</em> <em>x</em> &nbsp;<em>g</em> <em>x</em>，因此 &#955; <em>x</em> . <em>f</em> <em>x</em> &nbsp;&#955; <em>x</em> . <em>g</em> <em>x</em>，由 &#951;-变换 <em>f</em> &nbsp;<em>g</em>。所以只要 &#951;-变换是有效的，会得到外延性也是有效的。</p>
<p>相反地，若外延性是有效的，则由&#946;-归约，对所有的 <em>y</em> 有 (&#955; <em>x</em> . <em>f</em> <em>x</em>) <em>y</em> &nbsp;<em>f</em> <em>y</em>，可得 &#955; <em>x</em> . <em>f</em> <em>x</em> &nbsp;<em>f</em>，即 &#951;-变换也是有效的</p>
<p><strong><a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#.E9.9D.9E.E5.BD.A2.E5.BC.8F.E5.8C.96.E7.9A.84.E6.8F.8F.E8.BF.B0"><font style="FONT-SIZE: 20px" color=#000033><u>5 &#955;演算的操作语义</u></font></a></strong></p>
<p>如果一个&#955;-项M中不含有任何形为((&#955;x.N1)N2)的子项，则称M是一个范式，简记为n.f.。如果一个&#955;-项M通过有穷步&#946;-归约后，得到一个范式，则称M有n.f.，没有n.f.的&#955;-项称为n.n.f.。</p>
<p>&nbsp;&nbsp;&nbsp; 通俗的说法是，将一个&#955;-项进行&#946;-归约，也就是进行实参代入形参的过程，如果通过有穷步代入，可以得到一个不能够再进行代入的&#955;-项，那么这就是它的范式。如果无论怎样代入，总存在可以继续代入的子项，那么它就没有范式。</p>
<p>例子</p>
<p>M = &#955;x.(x((&#955;y.y)x))y，则M&#224; y((&#955;y.y)y) &#224; yy。M有一个n.f.。</p>
<p>例子</p>
<p>M =&#955;x.(xx) &#955;x.(xx)，则M&#224;&#955;x.(xx) &#955;x.(xx)=M。注意到M的归约只有唯一的一个可能路径，所以M不可能归约到n.f.。所以M是n.n.f.。</p>
<p>注意这个&#955;x.(xx) &#955;x.(xx)在&#955;演算的协调性研究中是一个比较经典的项。((&#955; x. x x) (&#955; x. x x))被称为&#937;, ((&#955; x. x x x) (&#955; x. x x x))被称为 &#937;2。</p>
<p>一般的把一个&#955;-项规约为范式的过程称为求值，范式也叫做值。在《类型和程序设计语言》一书中，作者给出了&#955;-演算中的几种不同的求值策略。每个策略确定一个项在下一步求值中激活哪一个约式或几个约式。</p>
<p>注意到在求值的过程中是左结合，并且当且仅当左边以是值了才能对右边的项进一步求值&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p><strong><a href="http://www.wikilib.com/wiki/%CE%9B%E6%BC%94%E7%AE%97#.E9.9D.9E.E5.BD.A2.E5.BC.8F.E5.8C.96.E7.9A.84.E6.8F.8F.E8.BF.B0"><font style="FONT-SIZE: 20px" color=#000033><u>6 &#955;演算的公理化和定理</u></font></a></strong></p>
<h2>6.1 &#955;演算的公理</h2>
<p>这一段来自《数理逻辑与集合论》（第二版 清华大学出版社）。</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (&#955;x.M)N &#224; M[x/N] 如果N中所有变量的自由出现都在M[x/N]中保持自由出现</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M&#224;M</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M&#224;N, N&#224;L =&gt; M&#224;L&nbsp;</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M&#224;M&#8217;=&gt;ZM&#224;ZM&#8217;</p>
<p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M&#224;M&#8217;=&gt;MZ&#224;M&#8217;Z</p>
<p>6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M&#224;M&#8217;=&gt;&#955;x. M &#224;&#955;x. M&#8217;</p>
<p>7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M&#224;M&#8217;=&gt;M M&#8217;&nbsp;</p>
<p>8.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;M M&#8217;=&gt;M&#8217; M</p>
<p>9.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M N,N L=&gt;M L</p>
<p>10.&nbsp;&nbsp;&nbsp;&nbsp; M M&#8217; =&gt; ZM &nbsp;ZM&#8217;</p>
<p>11.&nbsp;&nbsp;&nbsp;&nbsp; M M&#8217; =&gt; MZ &nbsp;M&#8217;Z</p>
<p>12.&nbsp;&nbsp;&nbsp;&nbsp; M M&#8217; =&gt;&#955;x. M &#955;x. M&#8217;</p>
<p>13．M≌N =&gt; M&#224;N 如果y没有在M中自由出现，并且只要y替换M中的x，都不会被M中的一个&#955;绑定。</p>
<p>如果某一公式M&#224;N或者M N可以用以上的公理推出，则记为&#955;├M&#224;N和&#955;├M N。</p>
<p>规则13可以加也可以不要，要了表示是考虑&#945;-变换的系统</p>
<h2>6.2 不动点理论</h2>
<p>&#923;表示所有的&#955;-项组成的集合。</p>
<p>定理：对于每一个F&#8712;&#923;，存在M&#8712;&#923;，使得&#955;├FM=M。</p>
<p>证明：定义w＝&#955;x.F(xx)，又令M＝ww，则有&#955;├M＝ww＝(&#955;x.F(xx))w＝F(ww)=FM。</p>
<p>证明是非常巧妙的，对于每个F，构造出的这个ww刚好是可以通过一次&#946;-归约得到F(ww)＝FM，如果再归约一次就得到F(FM)，这样可以无限次的归约下去得到F(F(F(F&#8230;(FM)&#8230;)))。</p>
<h2>6.3 Church-Rosser定理及其等价定理</h2>
<p>这两个定理告诉我们这样一个事实：如果M有一个n.f.，则这个n.f.是唯一的，任何&#946;-归约的路径都将终止，并且终止到这个n.f.。</p>
<p>Church-Rosser定理：如果&#955;├M N，则对某一个Z，&#955;├M&#224;Z并且&#955;├N&#224;Z。</p>
<p>与之等价的定理如下，</p>
<p>Diamond Property定理：如果M&#224;N1,M&#224;N2，则存在某一Z，使得N1&#224;Z，N2&#224;Z。（规约的合流性）</p>
<p>推论：M&#224;N1,M&#224;N2 且N1,N2都是范式 则N1≌N2 (范式在&#945;-变换下的唯一性)</p>
<p>&nbsp;关系被定义为满足上述两条规则的最小等价关系 (即在这个等价关系中减去任何一个映射，它将不再是一个等价关系)。</p>
<p>对上述等价关系的一个更具操作性的定义可以这样获得：只允许从左至右来应用规则。不允许任何 beta 归约的 lambda 表达式被称为<em>范式</em>。并非所有的 lambda 表达式都存在与之等价的范式，若存在，则对于相同的形式参数命名而言是唯一的。此外，有一个算法用来计算范式，不断地把最左边的形式参数替换为实际参数，直到无法再作任何可能的规约为止。这个算法当且仅当 lambda 表达式存在一个范式时才会停止。<a title="Church-Rosser 定理" href="http://www.wikilib.com/wiki?title=Church-Rosser_%E5%AE%9A%E7%90%86&amp;action=edit"><u><font color=#000033>Church-Rosser 定理</font></u></a> 说明了，当且仅当两个表达式等价时，它们会在形式参数换名后得到同一个范式。</p>
<h2><a id=lambda_.E6.BC.94.E7.AE.97.E4.B8.AD.E7.9A name=lambda_.E6.BC.94.E7.AE.97.E4.B8.AD.E7.9A></a><font style="FONT-SIZE: 20px" color=#990099><u>7 lambda 演算中的程序设计</u></font></h2>
<h2>7.1 自然数与运算</h2>
<p>在 lambda 演算中有许多方式都可以定义<a title=自然数 href="http://www.wikilib.com/wiki/%E8%87%AA%E7%84%B6%E6%95%B0"><u><font color=#000033>自然数</font></u></a>，但最常见的还是<a title=邱奇数 href="http://www.wikilib.com/wiki/%E9%82%B1%E5%A5%87%E6%95%B0"><u><font color=#000033>邱奇数</font></u></a>，下面是它们的定义：</p>
<p>0 = &#955; <em>s</em>. &#955; <em>z</em>. <em>z</em></p>
<p>1 =&#955; <em>s</em>. &#955; <em>z</em>.. s z</p>
<p>2 =&#955; <em>s</em>. &#955; <em>z</em>. <em>s</em> (<em>s z</em>)</p>
<p>3 =&#955; <em>s</em>. &#955; <em>z</em>. <em>s</em> (<em>s</em> (<em>s z</em>))</p>
<p>以此类推。直观地说，lambda 演算中的数字 <em>n</em> 就是一个把函数 <em>f</em> 作为参数并以 <em>f</em> 的 <em>n</em> 次幂为返回值的函数。换句话说，Church 整数是一个<a title=高阶函数 href="http://www.wikilib.com/wiki/%E9%AB%98%E9%98%B6%E5%87%BD%E6%95%B0"><u><font color=#000033>高阶函数</font></u></a> -- 以单一参数函数 <em>f</em> 为参数，返回另一个单一参数的函数。</p>
<p>(注意在 Church 原来的 lambda 演算中，lambda 表达式的形式参数在函数体中至少出现一次，这使得我们无法像上面那样定义 0) 在 Church 整数定义的基础上，我们可以定义一个后继函数，它以 <em>n</em> 为参数，返回 <em>n</em> + 1：</p>
<p>SUCC1 = &#955; <em>n</em>. &#955; <em>s</em>. &#955; <em>z</em>. <em>s</em>(<em>n</em> s <em>z</em>)</p>
<p>SUCC2 = &nbsp;&#955; <em>n</em>. &#955; <em>s</em>. &#955; <em>z</em>. <em>n</em> s(s <em>z</em>)</p>
<p>加法是这样定义的：</p>
<p>PLUS = &#955; <em>m</em>. &#955; <em>n</em>. &#955; <em>s</em>. &#955; <em>z</em>. <em>m</em> <em>s</em> (<em>n</em> <em>s</em> z)</p>
<p>PLUS 可以被看作以两个自然数为参数的函数，它返回的也是一个自然数。你可以试验证</p>
<p>PLUS 2 3 &nbsp;&nbsp; 与 &nbsp;&nbsp; 5</p>
<p>是否等价。乘法可以这样定义：</p>
<p>MULT = &#955; m. &#955; n. m (PLUS n) 0,</p>
<p>MULT2 =&#955; m. &#955; n. &#955; s. &#955; z. m (n s) z</p>
<p>即 <em>m</em> 乘以 <em>n</em> 等于在零的基础上 <em>n</em> 次加 <em>m</em>。更简洁的一种方式是</p>
<p>MULT3 = &#955; m. &#955; n. &#955; s. m (n s)</p>
<p>幂的定义：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POWER1 = &#955; m. &#955; n. m (MULT n) 1</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; POWER2 = &#955; m. &#955; n. m n&nbsp; (可能有点问题，我验证了好象不正确)</p>
<p>正整数 <em>n</em> 的前驱元 (predecessesor) PRED <em>n</em> = <em>n</em> - 1 要复杂一些：</p>
<p>PRED = &#955; <em>n</em>. &#955; <em>f</em>. &#955; <em>x</em>. <em>n</em> (&#955; <em>g</em>. &#955; <em>h</em>. <em>h</em> (<em>g</em> <em>f</em>)) (&#955; <em>u</em>. <em>x</em>) (&#955; <em>u</em>. <em>u</em>)</p>
<p>或者</p>
<p>PRED = &#955; <em>n</em>. <em>n</em> (&#955; <em>g</em>. &#955; <em>k</em>. (<em>g</em> 1) (&#955; <em>u</em>. PLUS (<em>g</em> <em>k</em>) 1) <em>k</em>) (&#955; <em>l</em>. 0) 0</p>
<p>注意 (<em>g</em> 1) (&#955; <em>u</em>. PLUS (<em>g</em> <em>k</em>) 1) <em>k</em> 表示的是，当 <em>g</em>(1) 是零时，表达式的值是 <em>k</em>，否则是 <em>g</em>(<em>k</em>) + 1。</p>
<p>&nbsp;&nbsp; 在《类型和程序设计语言》一书中作者对于数和各种运算的编码描述得比较清晰，强烈建议看以下，并且作者还介绍了直接基于原始的布尔类型和数型的系统，简称为&#955;NB，并给出了这两套系统之间的转换。</p>
<h2><a name=.E9.80.BB.E8.BE.91.E4.B8.8E.E6.96.AD.E8.></a>7.2 逻辑与断言</h2>
<p>习惯上，下述两个定义 (称为 Church 布尔值) 被用作 TRUE 和 FALSE 这样的布尔值：</p>
<p>tru = &#955; <em>u</em>. &#955; <em>v</em>. <em>u</em></p>
<p>fls = &#955; <em>u</em>. &#955; <em>v</em>. <em>v</em></p>
<p>这样我们可以定义一个组合式test=&#955;l.&#955;m.&#955; n.lmn，使得b为tru时，test b v w规约为v，而当b为fls时，test b v w规约为w。</p>
<p>并且我们还可以定义逻辑连接词：</p>
<p>and = &#955;b. &#955;c. b c fls</p>
<p>or =&#955;b. &#955;c. b c tru</p>
<p>not =&#955;b. b fls tru</p>
<p>断言是指返回布尔值的函数。最基本的一个断言 ISZERO，当且仅当其参数为零时返回真：</p>
<p>ISZERO = &#955; <em>n</em>. <em>n</em> (&#955; <em>x</em>. fls) tru</p>
<p>断言的运用与上述 TRUE 和 FALSE 的定义，使得 "if-then-else" 这类语句很容易用 lambda 演算写出。</p>
<p align=left><a name=.E9.81.9E.E6.AD.B8></a>7.3 递归 <strong>&nbsp;</strong></p>
<p><a title=递归 href="http://www.wikilib.com/wiki/%E9%80%92%E5%BD%92"><u><font color=#000033>递归</font></u></a>是一种以函数自身迭代自身变元的算法，一般是通过函数自身来定义函数的方式实现。表面看来 lambda 演算不允许递归，其实这是一种对递归的误解。考虑<a title=階乘 href="http://www.wikilib.com/wiki/%E9%9A%8E%E4%B9%98"><u><font color=#000033>阶乘</font></u></a>函数 <em>f</em>(<em>n</em>) 一般这样递归地定义：</p>
<p><em>f</em>(<em>n</em>) = 1, 若 <em>n</em> = 0; <em>n</em>&#183;<em>f</em>(<em>n</em>-1), 若 <em>n</em>&gt;0.</p>
<p>&#955;语言：</p>
<p>FACT = &#955; <em>n</em>. <em>n</em> (&#955; <em>u</em>. MULT <em>n</em> (FACT (PRED <em>n</em>))) 1</p>
<p>用 Y-组合子 在 &#955;语言 中合法地定义：</p>
<p>FACT = Y (&#955; <em>g</em>. &#955; <em>n</em>. <em>n</em> (&#955; <em>u</em>. MULT <em>n</em> (<em>g</em> (PRED <em>n</em>))) 1)</p>
<p>Y = &#955; <em>f</em>. ((&#955; <em>x</em>. <em>f</em> (<em>x</em> <em>x</em>)) (&#955; <em>x</em>. <em>f</em> (<em>x</em> <em>x</em>)))</p>
<p>这一节我也没分析透彻，只能原本引用，并且以上的内容也只能当作一个不严格的了解，暂时还不知道其有没有错，不过一点可以肯定的是上面定义的Y-组合子只能用于按名调用的情况，在按值调用的形式中是无用的，因为对任何g，表达式Yg发散。想要深入理解还是参看一下《类型和程序设计语言》这本书，不过书中也没深入的具体分析按值和按名调用的作用方式。其实这涉及到不同的操作语义的定义。想要在这里弄透还得找找论文看看。</p>
<p><font style="FONT-SIZE: 20px" color=#990099><u>8&nbsp;参考文献和外部连接</u></font></p>
<ul type=disc>
    <li>School of Computer Science and Software Engineering, Faculty of Information Technology, Monash University, Australia 3800这个大学的FP课程中的Lambda演算相关部分<a href="http://www.csse.monash.edu.au/~lloyd/tildeFP/Lambda/Ch/"><u><font color=#000033>http://www.csse.monash.edu.au/~lloyd/tildeFP/Lambda/Ch/</font></u></a>
    <li>wikipedia中lambda演算相关介绍<a href="http://en.wikipedia.org/wiki/Lambda_calculus"><u><font color=#000033>http://en.wikipedia.org/wiki/Lambda_calculus</font></u></a>（维基百科好象被封了，中国有关方面应该开放点），不过可以访问<a href="http://en.wikilib.com/wiki/Lambda_calculus"><u><font color=#000033>http://en.wikilib.com/wiki/Lambda_calculus</font></u></a>（是一个镜像站点，有中文和英文版）
    <li>《数理逻辑与集合论》第二版 清华大学出版社
    <li>《类型和程序设计语言》BC.Pierce 电子工业出版社（个人认为写得很好，很值得一看）
    <li>一个blog <a href="http://www.blogjava.net/wxb_nudt/archive/2005/05/15/4311.aspx" target=_blank><font face="Courier New" color=#000033><u>http://www.blogjava.net/wxb_nudt/archive/2005/05/15/4311.aspx</u></font></a> </li>
</ul>
</div>
<a href="http://www.blogjava.net/sizilove"></a>
<img src ="http://www.blogjava.net/sizilove/aggbug/130611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sizilove/" target="_blank">馒头</a> 2007-07-16 16:43 <a href="http://www.blogjava.net/sizilove/archive/2007/07/16/130611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>