likes
comments
collection
share

函数式编程的数学基础(二)邱奇对,邱奇数减法

作者站长头像
站长
· 阅读数 67

邱奇数的加法和乘法并不难理解。它们仅仅是在函数调用的基础上进行叠加。那么,是否有方法实现邱奇数的减法呢?

假设给我们一个邱奇数n,我们几乎没办法知道它的内部结构,我们能够对它做的操作仅有“调用”。

那么,倘若邱奇数可以实现减法,那么奥秘一定在于给邱奇数传入了特殊的参数。

邱奇数的减法实现较为繁琐,而且有多种思路。我们这里挑选其中较为容易理解的一种来讲解。

要实现邱奇数减法,实现一个减一运算是至关重要的。那么如何实现减一呢?

我们设想,假如我们传给邱奇数的函数f,能够接受和存储上一次调用的结果,即实现这样一个函数:

[a, b] => [b, b + 1]

那么,把它传给邱奇数调用n次之后,就可以得到n-1的结果了。

但是,在我们面前还有待解决的问题:lambda演算中并没有数组这样的数据结构,哪怕我们只需要存储2个邱奇数。那么我们就要考虑一下,如何实现这样的一种数据结构了。

邱奇对

存储2个函数(经典lambda演算中函数既是数据,又是操作)的数据结构被称作邱奇对。

我们首先考虑,假设有这么一种邱奇对,我们该如何使用它。

因为lambda演算中一切数据没有除了调用以外的方法,那么,邱奇对大体的使用方法可能,邱奇对p接受一个函数s,s能够接收到p中存储的数据x和y

s=λx.λy.(......)(p s)s = \lambda x.\lambda y.(......) \\ (p\ s)s=λx.λy.(......)(p s)

所以邱奇对应该是一个这样形状的一个函数:

λs.(s x y)\lambda s.(s\ x\ y)λs.(s x y)

所以构造邱奇对的函数应该是这样的:

pair=λx.λy.λs.(s x y)pair = \lambda x.\lambda y.\lambda s.(s\ x\ y)pair=λx.λy.λs.(s x y)

为了方便使用,我们可以实现一些常见的操作邱奇对的方法,比如取第一个first和取第二个second:

first=λp.(p λx.λy.x))second=λp.(p λx.λy.y))first = \lambda p.(p\ \lambda x.\lambda y.x))\\ second = \lambda p.(p\ \lambda x.\lambda y.y))first=λp.(p λx.λy.x))second=λp.(p λx.λy.y))

实际使用的时候,如果已经比较熟练,也可以不用first、second这些名称,直接写其内容。有了邱奇对,我们可以考虑实现减法了。

邱奇数的前一个数(减一运算)

"前一个"的英文是predecessor,我们可以利用前面的邱奇对实现这一函数。首先我们实现前文所讲的函数f,即:

const f = [a, b] => [b, b + 1]

这个函数的lambda版需要邱奇对和加一运算。加一运算的英文是successor,我们把函数名简写为succ。succ的实现很简单简单得多,我们这里不展开讲解了。

succ=λn.λf.λx.(f(n f x))succ = \lambda n.\lambda f.\lambda x.(f (n\ f\ x))succ=λn.λf.λx.(f(n f x))

接下来我们实现这个f。

f=λp.(pair (second p) (succ (second p)))f = \lambda p.(pair\ (second\ p)\ (succ\ (second\ p)))\\f=λp.(pair (second p) (succ (second p)))

有了这个f,我们只需要把它对邱奇对<0,1>执行n次,就可以得到n - 1的值。

pred=λn.(first ((nf) (pair ZERO ONE)))pred = \lambda n.(first\ ((n f)\ (pair\ ZERO\ ONE)))pred=λn.(first ((nf) (pair ZERO ONE)))

其中,ZEROZEROZEROONEONEONE的定义可以看上一篇。

有了succsuccsucc函数,我们可以轻易实现邱奇数减法。

minus=λm.λn.(n pred m)minus = \lambda m.\lambda n.(n\ pred\ m)minus=λm.λn.(n pred m)

其它思路

除了利用邱奇对,pred函数还有其它思路,它形式上更简洁,但推导过程更具有技巧性,此处我们仅仅给出其形式,供大家自行研究:

pred=λn.λf.λx.(n (λa.λb.(a (b x)) (λu.x) (λu.u))pred = \lambda n.\lambda f.\lambda x.(n\ (\lambda a.\lambda b.(a\ (b\ x))\ (\lambda u.x)\ (\lambda u.u))pred=λn.λf.λx.(n (λa.λb.(a (b x)) (λu.x) (λu.u))

结语

到此,我们已经在lambda体系中实现了一个基础数据结构邱奇对和邱奇数的减法,四则运算中我们仅剩下除法运算还没有实现。

在接下来的几篇中,我们将会继续补全邱奇数的基本运算和一些编程所需的结构。

转载自:https://juejin.cn/post/7249664547219701815
评论
请登录