丘奇编码计数(Chruch Encoding)的易懂理解

一. Chruch Encoding为了解决什么问题??

lambda y.x*2
lambda 中的自然数 2 无法表示如何解决??
为此,就有了Church Encoding

二. Church Encodeing 简介

是 Church 发明的一种用 λ \lambda λ expression 表示自然数的方法.
通过函数的嵌套层数来表示!!!

三. 本质

f(x) 嵌套0次: x,     表示0
f(x) 嵌套1次: f(x),  表示1
f(x) 嵌套2次: f(f(x)),  表示2
...
f(x) 嵌套n次: f^n(x) 表示n

四. python 表示

为了便于理解,我们可以先用 Python 表示.
根据其本质,我们可以用函数表示chruch encoding.

def zero(x):
	return x #嵌套层数为0表示0
def one(f,x):
	return f(x) #嵌套层数为1,表示1
def two(f,x):
	return f(f(x)) #嵌套层数为2,表示2

1.为什么必须有参数呢???
  因为 λ \lambda λ expression 是匿名函数,如果没有参数(因变量),函数就没有意义(数学意义上).
2.zero 为什么要有两个参数???
  对于 zero 而言其实只需要一个参数 x. 但为了接口标准化,还是加上f这个参数(这也是为了方便后续操作).

def zero(f, x): #即使不需要参数f,还是用出于接口通用化,将其引入.
	return x #嵌套0层表示0

五. lambda expression 表示

我们都知道 lambda expression 是一个匿名函数.
在 lambda calculs 中, 的最基本的元素页必须是一个 lambda expression.
所以 x 要表示为 λ \lambda λx.x

  • 0 表示为:    λ \lambda λ x.x --接口标准化–> λ \lambda λ fx.x

  • 1 表示为:   λ \lambda λ fx.f(x)

  • 2表示为:    λ \lambda λfx.f(f(x))

  • 3表示为:   λ \lambda λfx.f(f(f(x)))

  • n表示为:    λ \lambda λ fx.f^n(x)

注意,这里的()属于嵌套标识符,而不是应用标识符

5.1 successor

0 的后继为 1. n 的后继数为 n+1.
successor 的功能为: 给定一个 Chruch Number, 可以推出其后继数.

实现思路:
  1. 后继数比前一个数要多一层 f()的嵌套
  2. 如何实现??? 答: 给变量n外面包裹一层 f()即可.
    successor = λ \lambda λnfx.f(n)
    其中变量 n 为要进行操作的 chruch number.
 		zero = λfx.x
 		one = successor(zero) = λfx.f(zero) = λfx.f(λfx.x)
 		并不是我们所期待的 one = λfx.f(x)
  1. 怎么解决??? 对传进来的 lambda expression作 应用操作,消去其头部即可.
    successor = λ \lambda λnfx.f(n (f)(x))
    其中变量 n 为要进行操作的 chruch number(本身也属于λ表达式).
    最内层的 (f)(x) 分别 n (λ表达式)的应用
		zero = λx.x
		one = successor(zero) = λfx.f(λfx.x (f)(x))
		one = λnfx.f(x)    # λfx.x(f)(x) 成功完成 β规约(替换) 更新为 x

所以我们得出:
  successor = λnfx.f(n (f)(x))
其中n(f)(x) 中的

  • n是一个lambda expression 也是一个 church number
  • (f)(x) 是用来应用于n这个lambda表达式 完成 β 规约的
额外的验证

eg:

one = λfx.f(x)
succ = λnfx.f(n (f)(x))

two = succ(one) 
=> λfx.f(one (f)(x))
=> λfx.f(λfx.f(x) (f)(x))  #n被替换为 λfx.f(x)
=> λnfx.f(f(x))		

5.2 add_church(m, n):

对两个church number 做加法

m 和n的接口都为 (f, x), 只不过每个数嵌套的层数不同

m = λfx.f(f(f(x))) #3
n = λfx.f(f(x))    #2

 那么加法实际上很好理解,将 m 中的 x 变量替换为 n 即实现层数相加(丘奇数的相加).

m+n = λfx.f(f(f(  f(f(x)) ))) #5

以上操作等价为以下操作:

m+n
= m(f)(n(f)(x))  #将 m 函数的因变量 x, 替换为n函数.并去掉n函数的头部(对n进行$\beta$规约)
= f(f(f( n (f)(x) )))
= f(f(f( λfx.f(f(x)) (f)(x) )))
= f(f(f( f(f(x))  )))
此时可以看出结果为 5 层.
给其加上头部即可: λmnfx.f(f(f(f(f(x)))))

所以,加法expression为 : λfx.m(f)( n(f)(x) )

5.3 mul_church(m, n):

对两个church number 做乘法
λmnfx.m(n(f))(x)

m = λfx.f(f(x))    #2
n = λfx.f(f(f(x))) #3

两个 church number 相加,实际上是将 m 中的每一层 f 都扩充为 n层f.

 m*n = λfx.f(f(f(f(f(f(x)))))) #2*3=6

如何实现呢???

  1. 首先毋庸置疑的是,m中的x变量不用改变.
    m()(x)
  2. 那对于 m 中的每个f, 都要对其进行替换( β \beta β规约)
    m(n)(x)
  3. 但很明显,传进去的n是 λfx.xxx 这样形式的,我们不期望其 head 存在, 如何解决???
		m = λfx.f(f(x))    #2
	=>  λfx.f(f(f(x))) ( λfx.f(f(f(x))) (x))    #2
  1. 我们已经很明显的发现了,当替换完m中的f变量后,原式m中的的 (x) 正好可以协助现在式子完成 β \beta β 规约,消去 λx
	=>  λfx.f(f(f(x))) ( λf.f(f(f(x))) )    #2
  1. 但 λf 无法消去,所以原式子跟改为
	m(n(f))(x)
=>  λx.f(f(f(x))) ( λx.f(f(f(x))) (x))  # (x) 协助完成规约
=>  λx.f(f(f(x))) ( f(f(f(x))) )	#  f(f(f(x))) 协助完成规约
=>  f(f(f(f(f(f(x))))))   #替换完全完成

5.4 pow_church

这里还没有搞清楚,比较模糊与是如何替换的.

将 church_number 转换为 int 数字

> 即,如何统计 f(x) 嵌套的层数呢??
  正常人类的思路都会从 0 开始计数,那么如何实现这一点呢??

four = λfx.f(f(f(f(x))))

如图所示,此 λ expression 有两个参数 f x. 其中,

  • (x) 是函数 f 的应用.
  • 函数 f 是递推公式.

如此一来,只需要将 x 作为初始值 0 .
f 设置为 λx.x+1

依靠 f 这个递推公式不断的递推即可.

	λfλx.f(f(f(f(x))))  (λx.x+1)(0)
=>  λf.f(f(f(f(0)))) (λx.x+1) #将全部x替换为了0,同时去掉了头部的 λx
=>  λx.x+1(λx.x+1(λx.x+1( λx.x+1(0) ))) #将f全部替换为 λx.x+1,同时去掉了头部的 λf
=>  λx.x+1(λx.x+1(λx.x+1( 1 ))) #β规约
=>  λx.x+1(λx.x+1( 2 )) #β规约
=>  λx.x+1(3) #β规约
=>  4 #β规约

给包裹一层函数外壳即:

λn.n(λx.x+1)(0)lambda n: n(lambda x: x+1)(0)def chruch_to_int(n):
	return n(lambda x:x+1)(0)

可以将 chruch number 转换为 int.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值