(一)
这里先不列出λ项的正式定义,只记住λ表达式语义上的构造方式为:
  1. x
一个单独的变量名是一个λ项表达式;
  1. (λx.M)
该λ表示一个函数。其中 M 是这个函数的函数体,M 本身也是一个 λ项。
除了 x 之外,M 中可能还有其他变量名,λ 这个符号用于指示函数体 M 的参数为 x。
了便于理解,可以将 M 看作函数体,x 看作形参,即变量名。
 
例如:λx.x+3 即表示一个函数 f(x) = x+3,该函数会返回x与3相加的结果
要注意的是,我这里的写法并不规范,在λ表达式中,二元运算符是作为前缀的。x+3 应该写作 (+ x 3)。所以这个表达式的正规写法是 λx.(+ x 3)。至于为什么,我们之后再讲。
  1. (M N)
其中 M,N 均为λ项表达式。
如果 M 本身是一个函数,我们说将函数 M 应用于 N。如果 M 不是函数,不接受参数,N 将在求值的过程中被忽略。
例如:(λx.(+ x 3) 4),其中M为表达式 λx.x+3,N 为 4。这个表达式表示将函数应用于 4,即f(4) 
 
所以一个典型的λ表达式具有如下形式:
 (λx.M) N,为了方便去掉括号写作 λx.M N
 
其中 M 是函数体,x 可以看作形参,即变量名, N 可以看作实参,即变量值。
 
函数本身也可以作为参数,例如(λx.x)(λx.(+x 3)),  表达式左边就是一个函数,这个函数将返回它自己的参数,将这个函数应用于我们之前说的函数 f,参数是 f,那么这个函数将返回 f。
 
如此一来,第一种形式的λ表达式代表一个变量;
第二种表达式代表一个函数;
第三种表达式则代表将函数应用于一个值,即一次函数调用。
 
(二)归约
第一种表达式的值即它本身;
第二种表达式的值表示这个函数本身;
因此,在讨论求值时,我们只关心第三种,即将一个函数应用于另一个λ表达式时,如何计算它的值。
 
如上所述,λ表达式的应用等效于一次函数调用。我们知道,调用函数的时候,会将所有的形参替换用实参的值,并返回计算结果。因此,我们说在表达式 λx.M N 中,函数体 M 里的 x 与表达式 N 绑定,M 中剩下未绑定的变量则是自由变量。
 
对 λx.M N 进行求值时,M 中所有的 x 都将被替换为 N。这一过程称为归约,归约后得到简化的λ表达式,可以进一步归约直至无法再归约,此时的表达式就是对原表达式进行求值的结果。
 
考虑一个函数 f(x)=x+3,写作λ表达式就是 (λx.(+x 3))。
如前所述,当我们想计算 f(4) 时,将函数应用于 4,表达式为 λx.(+ x 3) 4。
按照归约的法则,函数体 (+ x 3) 中的 x 被 4 替换,函数表达式变为 (+ 4 3),结果为 7。
 
考虑另一个函数 g(y)=y*2,λ表达式 λy.(* y 2)。
如果我们想将函数 g 应用于 f(4) 的计算结果,即 g(f(4)),我们可以将 g 的λ表达式应用于上述表达式,即 λy.(* y 2)  (λx.(+ x 3) 4)
 
然后我们进行归约,这里有两种归约顺序。
 
一种是同之前一样,先计算右边表达式的值,即归约为 λy.(* y 2) 7。
然后将函数体 (* y 2) 中的 y 替换为 7,得到 (* 7 2)。
最终结果是 14。
 
另一种归约顺序是先计算最外层的应用,即将y替换为右边的表达式(λx.(+ x 3) 4),得到归约后的表达式(* (λx.(+ x 3) 4) 2)。
再归约内层的应用,替换 x 得到 (* (+ 4 3) 2)。
最终结果为(* 7 2)=14。
 
在这个例子中,不同的归约顺序得出了相同的结果,然而,这并不是普遍现象。这里面暗藏了一个计算机程序中常见的概念:作用域。
 
 

Lambda演算(二)归约!归约!归约!的更多相关文章

  1. 简单易懂的程序语言入门小册子(1.5):基于文本替换的解释器,递归定义与lambda演算的一些额外说明

    这一篇接在第一篇lambda演算的后面.讲讲一些数学知识. 经常有些看似很容易理解的东西,一旦要描述得准确无误,就会变得极为麻烦. 软件工程里也有类似情况:20%的代码实现了核心功能,剩下80%的代码 ...

  2. Lambda演算(一)大道至简

    从选择信息专业开始到回炉读书为止,四舍五入码了八年代码.对于计算机科学的认知仅限于: 1)使用不同语言实现特定功能 2)实现不同算法以增进系统性能 3)搭建不同架构进行组织管理   但从未思考一些本质 ...

  3. [学习] 从 函数式编程 到 lambda演算 到 函数的本质 到 组合子逻辑

    函数式编程 阮一峰 <函数式编程初探>,阮一峰是<黑客与画家>的译者. wiki <函数编程语言> 一本好书,<计算机程序的构造与解释>有讲到schem ...

  4. 简单易懂的程序语言入门小册子(1):基于文本替换的解释器,lambda演算

    最近比较闲,打算整理一下之前学习的关于程序语言的知识.主要的内容其实就是一边设计程序语言一边写解释器实现它.这些知识基本上来自Programming Languages and Lambda Calc ...

  5. lambda演算

    先了解下相关的知识点(以下都只用先了解简单的概念,建议wiki): BNF范式,上下文无关文法,函数柯里化. lambda读书笔记演算: http://www.blogjava.net/wxb_nud ...

  6. Lambda演算 - 简述Y组合子的作用

    Y组合子:\f.(\x.f(xx))(\x.f(xx)),接受一个函数,返回一个高阶函数 Y组合子用于生成匿名递归函数. 什么叫匿名递归函数,考虑以下C语言递归函数 int sum(int n) { ...

  7. [摘录] 图灵机与lambda演算的关系

    在阅读函数式编程相关资料时,看到如下一段话.感觉说的很好,可以帮助我这种学渣一点点的建立起整个知识体系. 以下片段,摘抄自豆瓣网友 赛义甫 的豆列 “逻辑与计算” 中的一段介绍. 莱布尼兹曾经有两个梦 ...

  8. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  9. 我的最爱Lambda演算——开篇

    (在这个帖子的原始版本里,我试图用一个JavaScript工具来生成MathML.但不太顺利:有几个浏览器没法正确的渲染,在RSS feed里也显示的不好.所以我只好从头开始,用简单的文本格式重新写一 ...

随机推荐

  1. BZOJ day8

    好吧,, 补一天题解. 1001  狼抓兔子 妥妥的网络流啊,难度仅次于草地排水,边都给出来了.就是注意反向边也要有流量就行. 1007 水平可见直线 这个题按斜率排序(注意不是绝对值),然后将直线入 ...

  2. [HNOI2003]消防局的设立 (贪心)

    [HNOI2003]消防局的设立 题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达, ...

  3. js中的Map对象的简单示例

    es6提供一个对象Map, 其功能类似于java中的Map, 下面是java中的Map和js中的Map的简单对比: js中的Map.set()相当于java中的Map.put(), js中的Map.s ...

  4. mysql删除id最小的条目

    DELETE FROM 表1 WHERE Mid in (select Mid from (SELECT Min(Mid) Mid FROM 表1 c1) t1);

  5. bzoj 3456 城市规划 多项式求逆+分治FFT

    城市规划 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1091  Solved: 629[Submit][Status][Discuss] Desc ...

  6. 前端面试:什么是css reset

    HTML标签在浏览器中都有默认的样式,不同的浏览器的默认样式之间存在差别.例如ul默认带有缩进样式,在IE下,它的缩进是由margin实现的,而在Firefox下却是由padding实现的.开发时浏览 ...

  7. kettle基础操作

    ETL:抽取(extract).转换(transform).加载(load)至目的端的过程: Kettle是ETL工具代表之一,是pentaho中的一个数据整合的一个组件.Kettle里包括多个Job ...

  8. 基于MapReduce的手机流量统计分析

    1,代码 package mr; import java.io.IOException; import org.apache.commons.lang.StringUtils; import org. ...

  9. windows主机控制

    一.开关机控制 using System.Runtime.InteropServices; //注销.关机.重启 class shutdown { [StructLayout(LayoutKind.S ...

  10. 如何使主机和虚拟机IP处于同一网段(内网渗透专用)

    先说一下正常流程: 1.打开虚拟机网络设置选项,选择桥接模式(Bridged)[如果是Kali 2.0的话,执行第一步后就OK了(90%)] 2.打开Kali里面的网络设置 3.设置一个ip4或者ip ...