λ演算 (Lambda Calculus) 一 : 定义与函数式编程

最近在学习计算理论方面的内容,这一系列文章主要介绍λ演算,这需要一些基本的离散数学如集合的知识,写的过程难免有错误欢迎大家指出。

1. 什么是λ演算 (Lambda Calculus)?

λ演算是数学家邱奇(Alonzo Church)在20世纪30年代发表的一种计算模型,以变量绑定和替换的规则,每个输入参数用一个字母 λ (lambda)来表示,研究函数如何抽象化定义,函数如何被应用以及递归,最终形成的一套函数化计算规则,被广泛的运用于函数式编程的理论基础。

2. 什么是函数式编程 (Functional Programming)?

函数式编程是实现λ演算的一次实践,比如: Lisp, Scheme, Haskell...

其核心思想就是所有的计算都是基于函数

近些年来,许多过程式编程语言(非函数式编程语言Lisp等)都内置了λ演算或是函数式编程方法。Java 8 中就引入了λ演算

// 代表接受一个值,并返回其2倍的值 

//通常写法
public int mult_Two(int x){
    return 2*x;
}

//Lambda Calculus写法
(int x) -> { return 2 * x;}

3. λ演算法则

λ演算中只有以下三种合法的表示方式:

· 变量(variable)

就是我们所熟知的变量,没有类型限制,可以代表一个字符,可以是字符串,甚至是一个列表

例如:x、y、a、b、c

· 应用(application)

第一种演算方式

例如:(F · A)

代表将一个输入A应用到一些算法F中。比如A是3,F是函数 x → x + 1,(F · A)的最简式就是4。通常我们可以省略点和括号写成FA。

应用是从左到右的关联方式例如:

× (+ 1 2) 3 = × 3 3 = 9

· 抽象(abstraction)

第二种演算方式

例如:λx.M[x]

代表函数 x → M[x]。 具体的来说M中所有的自由变量x将被替换成一个输入值。比如 λx.x 代表 x → x。

多个抽象可以合并只用一个λ,比如λx.λy(xy) = λxy.(xy)

抽象是从右到左的关联方式例如:

(λxyz. + (+ x z ) y ) 1 2 3 = ((((λx.(λy.(λz.((+ · ((+ · x ) · z )) · y)))) · 1) · 2) · 3) = ((+ · ((+ · 1) · 3)) · 2) = 6

4. 自由变量(Free)和绑定变量(Binding)

自由变量就是不受输入约束的变量,相反绑定变量就是由输入的值决定的,下面举几个例子来看一下:

  • λx.(y · x)
  1. λx是一个x的抽象
  2. y是自由变量因为它不在任何的λy的绑定范围内,也就是它的外面没有λy
  3. x是绑定变量,因为它在λx的绑定范围内
  • (λx.(x · (λx.(x · x )))
  1. 第一个x是绑定在第一个λx上的
  2. 第二个x是绑定在第二个λx上的
  3. 第三个x也是绑定在第二个λx上的
  • ((λx.(y · x )) · x )
  1. 第一个x是绑定在第一个λx上的
  2. 第二个x是自由变量
  3. y也是自由变量

5. α 、β、η 归约()

  • α归约

α归约也叫重命名化简,一种转换变量名的方法。我们先看一个例子

//第一种
int x = 0;
{int x = 9; System.out.println(x);}
System.out.println(x);
//第二种
int x = 0;
{int y = 9; System.out.println(y);}
System.out.println(x);
//第三种
int x = 0;
{int z = 9; System.out.println(z);}
System.out.println(x);

第一种代码肯定是会报错的,因为我们发现x在程序开始就被定义了。所以我们把大括号内的x改成y就行了。那么我们一定要修改成y吗?不一定,我们还可以修改成其他任何不是x的变量名。这就是α归约的原理。

可以将任何自由变量修改成不与其他变量冲突的变量名。比如:

  1. ((λx.(y · x )) · x ) = ((λz.(y · z )) · x )
  2. ((λx.(x · (λx.x )) · x ) · x ) = ((λy.(y · (λz.z )) · y) · x )
  • β归约

β归约的表达形式: (λx.M ) · N = M [x := N ]

意思是将M中所有的自由变量x换成N,举几个例子:

  1. ((λx.(x · y)) · z ) = ((λx.(x · y)) · z ) = (z · y)
  2. ((λx.((λx.x ) · x ) · z ) = ((λx.x ) · z )   (注意最里面的x是绑定变量)
  • η 归约

η归约的表达形式:如果M中没有x的自由变量,那么 λx.Mx = M

同时还有一个变形:如果M中没有x的自由变量,那么 (λx.Mx )N = Mx [x := N ] = MN

举个例子:

  1. λf.(λx.(λy.f · x · y)) = λf.(λx.f · x) = λf.f

Lambda Calculus的基本计算方式就是这些,下面一章会写编码方式和计算也就是如何用我们刚刚讲的这些来实现编程

原文地址:https://www.cnblogs.com/qianyexi/p/12154478.html

时间: 2024-11-12 05:28:02

λ演算 (Lambda Calculus) 一 : 定义与函数式编程的相关文章

Lambda演算 Lambda Calculus 的简单理解

Lambda演算 在λ演算中,每个表达式都代表一个函数,这个函数有一个参数,并且返回一个值.不论是参数和返回值,也都是一个单参的函数.可以这么说,λ演算中,只有一种"类型",那就是这种单参函数. 函数是通过λ表达式匿名地定义的,这个表达式说明了此函数将对其参数进行什么操作.例如,"加2"函数f(x)= x + 2可以用lambda演算表示为λx.x + 2 (或者λy.y + 2,参数的取名无关紧要)而f(3)的值可以写作(λx.x + 2) 3.函数的应用(app

Java函数式编程和lambda表达式

为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于某种语法或调用API去进行编程.例如,我们现在需要从一组数字中,找出最小的那个数字,若使用用命令式编程实现这个需求的话,那么所编写的代码如下: public static void main(String[] args) { int[] nums = new int[]{1, 2, 3, 4, 5,

函数式编程与面向对象编程的比较

函数式编程作为结构化编程的一种,正在受到越来越多的重视.工程中不在只是面向对象编程,更多的人尝试着开始使用函数式编程来解决软件工程中遇到的问题. 什么是函数式编程?在维基百科中给出了详细的定义,函数式编程(英语:functional programming)或称函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象.函数编程语言最重要的基础是λ演算(lambda calculus).而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值

Python基础函数之函数式编程

一. 匿名函数 匿名函数就是不需要显示的指定函数,只要运行过一次后就立马释放内存空间. 主要表现形式为: lambda 形参:具体功能 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = lambda n:n**n print(calc(10)) 你也许会说,用上这个东西没感觉有毛方便呀, ....呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下 res = map(lambda x:x**2,[1,5

python函数与函数式编程

https://www.cnblogs.com/evablogs/p/6699515.html 在理解函数式编程之前,我还是对函数的调用,参数传递以及函数的嵌套调用一头雾水,还是花了点时间整理了写思绪,以便我后面对装饰器复杂的参数传递和函数的调用的理解. 函数的定义 def 函数名(): 代码块 例如: 1 2 3 def func_name():      block      return value                                     #return语句

001 java为什么需要函数式编程

一 .概述 集合是我们java程序员每天都需要的工具,没有了集合,java程序员几乎不能干任何的事情,我们每天的工作也是在对集合进行不同的操作. 尽管集合的功能已经足够强大,但是当我们面对复杂的业务问题的时候,利用原始的集合操作就会变得让人恶心. 于是在java8之中出现了lambda和stream的API,为我们以一种更加优雅的方式使用集合. 没错,就是集合,当我们现在使用NOSQL,各种日志分析,等等的大数据操作的时候,我们不可能使用原始的数据库的sql操作帮助我们完成如排序,求和,分组等操

Scala 函数式编程(一) 什么是函数式编程?

为什么我们需要学习函数式编程?或者说函数式编程有什么优势?这个系列中我会用 scala 给你讲述函数式编程中的优势,以及一些函数式的哲学.不懂 scala 也没关系,scala 和 java 是类似的,在每篇的开头我也会先说明这节中用到的 scala 语法. 为什么函数式编程这几年火起来 如 Python 一样,函数式编程(FP,即Functional Programming)也是近几年才逐渐为人们所知,但它并不是一个多么新的概念.它拥有和面向对象编程(OOP)几乎等长的历史.但纵观每件事的脉络

函数式编程之根-λ表达式(lambda expression)

学习函数式编程的大图(big map)/鸟瞰图,并在没有掌握Scheme的各种语言细节之前,给出Scheme代码.这意味着我们不需要看懂源代码,而是将这里的介绍作为后续学习的大图,使自己知道身在何处: 1930s初,普林斯顿大学的逻辑学家阿伦佐·丘奇 (Alonzo Church,1903-1995) 开发出了一种新的形式系统(formal system),即拉姆达运算/演算 (λ-calculus .lambda calculus ,lambda即希腊字母λ). λ运算的核心是λ表达式,以此形

Java8函数式编程 (一) 数据流和lambda表达式

JDK 1.8中引入了函数式编程(functional programming,FP),如果您已习惯OOP,一定会感到困惑:什么是函数式编程?这样的编程模式有什么好处? 本文将通过简单的实例令读者对函数式编程有一个大体的了解. 我们知道OOP是以类为基础的,程序中必须首先抽象和定义class.那么FP创建的基础是什么?或者说在Java 8中,至少需要了解什么知识点才能实现基本的函数式编程呢? 本文将首先介绍在Java 8中使用FP所需的基本知识点: Lambda表达式 数据流 基本实例 Map<