邱奇编码 是把数据和运算符嵌入到lambda演算 内的一种方式,最常见的形式即邱奇数,它使用lambda符号表示自然数。方法得名于阿隆佐·邱奇 ,他首先以这种方法把数据编码到lambda演算中。
透过邱奇编码,在其他符号系统中通常被认定为基本的项(比如整数、布尔值、有序对、列表和tagged unions)都会被映射到高阶函数 。在无型别lambda演算 ,函数是唯一的原始型别 。
邱奇编码本身并非用来实践原始型别,而是透过它来展现我们不须额外原始型别即可表达计算。
很多学数学的学生熟悉可计算函数 集合的哥德尔编号 ;邱奇编码是定义在lambda抽象 而不是自然数上的等价运算。
直接实现邱奇编码会将某些访问操作的时间复杂度从
O
(
1
)
{\displaystyle O(1)}
降低到
O
(
n
)
{\displaystyle O(n)}
(其中
n
{\displaystyle n}
是数据结构的大小),这使得该编码方式在实际应用中受到限制。[ 1] 研究表明可以通过针对性优化解决这个问题,但大多数函数式编程 语言选择扩展其中间表示以包含代数数据类型 。[ 2]
尽管如此,邱奇编码仍常用于理论论证,因为它在部分求值 和定理证明 中具有自然表示优势。[ 1] 通过使用高阶类型 可以对操作进行类型标注,[ 3] 并能便捷地实现原始递归 。[ 1] 由于函数被假定为唯一的原始数据类型,这种设定简化了许多证明过程。
邱奇编码具有表示完整性但仅限于表征层面。需要额外函数将这种表示转换为通用数据类型以供人工解读。由于邱奇定理 中等价性不可判定 ,通常无法判断两个函数是否具有外延等价性 。转换过程可能需要通过某种方式应用函数来提取其表征值,或者以λ项字面量的形式查找其值。λ演算通常被解释为使用内涵等价性 。由于等价性的内涵定义与外延定义存在差异,在结果解释方面可能存在潜在问题 。
邱奇数 为使用邱奇编码的自然数 表示法,而用以表示自然数
n
{\displaystyle n}
的高阶函数 是个任意函数
f
{\displaystyle f}
映射到它自身的n 重函数复合 之函数,简言之,数的“值”即等价于参数被函数包裹的次数。
f
∘
n
=
f
∘
f
∘
⋯
∘
f
⏟
n
次
.
{\displaystyle f^{\circ n}=\underbrace {f\circ f\circ \cdots \circ f} _{n{\text{ 次}}}.\,}
不论邱奇数为何,其都是接受两个参数的函数。邱奇数0 、1 、2 、... 在λ演算 中的定义如下:
从 0 不应用函数开始, 1 应用函数一次, 2 应用函数两次, 3 应用函数三次,依此类推 :
自 然 數
函 數 定 義
lambda 表 達 式
0
0
f
x
=
x
0
=
λ
f
.
λ
x
.
x
1
1
f
x
=
f
x
1
=
λ
f
.
λ
x
.
f
x
2
2
f
x
=
f
(
f
x
)
2
=
λ
f
.
λ
x
.
f
(
f
x
)
3
3
f
x
=
f
(
f
(
f
x
)
)
3
=
λ
f
.
λ
x
.
f
(
f
(
f
x
)
)
⋮
⋮
⋮
n
n
f
x
=
f
n
x
n
=
λ
f
.
λ
x
.
f
∘
n
x
{\displaystyle {\begin{array}{r|l|l}{\text{ 自 然 數}}&{\text{函 數 定 義}}&{\text{lambda 表 達 式}}\\\hline 0&0\ f\ x=x&0=\lambda f.\lambda x.x\\1&1\ f\ x=f\ x&1=\lambda f.\lambda x.f\ x\\2&2\ f\ x=f\ (f\ x)&2=\lambda f.\lambda x.f\ (f\ x)\\3&3\ f\ x=f\ (f\ (f\ x))&3=\lambda f.\lambda x.f\ (f\ (f\ x))\\\vdots &\vdots &\vdots \\n&n\ f\ x=f^{n}\ x&n=\lambda f.\lambda x.f^{\circ n}\ x\end{array}}}
邱奇数3 表示对任意给定函数应用三次的操作。当输入函数被提供时,首先应用于初始参数,然后连续应用于自身结果。最终结果并非数字3(除非初始参数恰好为0且函数为后继函数 )。邱奇数3 的本质是函数的应用次数,而非计算结果本身。其核心意义在于“重复三次”的动作,这正是“三次”概念的直观体现 。
就是说,自然数
n
{\displaystyle n}
被表示为邱奇数n ,它对于任何lambda-项F
和X
有着性质:
n F X
=β Fn X
。
在 lambda 演算中,数值函数被表示为在邱奇数上的相应函数。这些函数在大多数函数式语言中可以通过 lambda 项的直接变换来实现(服从于类型约束)(请参阅将lambda表达式转换为函数 )。
加法函数
plus
(
m
,
n
)
=
m
+
n
{\displaystyle {\text{plus}}(m,n)=m+n}
利用了恒等式
f
∘
(
m
+
n
)
(
x
)
=
f
∘
m
(
f
∘
n
(
x
)
)
{\displaystyle f^{\circ (m+n)}(x)=f^{\circ m}(f^{\circ n}(x))}
。
plus
≡
λ
m
.
λ
n
.
λ
f
.
λ
x
.
m
f
(
n
f
x
)
{\displaystyle \operatorname {plus} \equiv \lambda m.\lambda n.\lambda f.\lambda x.m\ f\ (n\ f\ x)}
后继函数
succ
(
n
)
=
n
+
1
{\displaystyle {\text{succ}}(n)=n+1}
β-等价 于(plus 1 )。
succ
≡
λ
n
.
λ
f
.
λ
x
.
f
(
n
f
x
)
{\displaystyle \operatorname {succ} \equiv \lambda n.\lambda f.\lambda x.f\ (n\ f\ x)}
乘法函数
mult
(
m
,
n
)
=
m
×
n
{\displaystyle {\text{mult}}(m,n)=m\times n}
利用了恒等式
f
∘
(
m
×
n
)
=
(
f
∘
n
)
∘
m
(
x
)
{\displaystyle f^{\circ (m\times n)}=(f^{\circ n})^{\circ m}(x)}
。
mult
≡
λ
m
.
λ
n
.
λ
f
.
λ
x
.
m
(
n
f
)
x
{\displaystyle \operatorname {mult} \equiv \lambda m.\lambda n.\lambda f.\lambda x.m\ (n\ f)\ x}
指数函数
exp
(
b
,
n
)
=
b
n
{\displaystyle \exp(b,n)=b^{n}}
通过邱奇数定义给出:将定义中的
h
→
b
{\displaystyle h\to b}
和
x
→
f
{\displaystyle x\to f}
代入
n
h
x
=
h
n
x
{\displaystyle n\ h\ x=h^{n}\ x}
可得
n
b
f
=
b
n
f
{\displaystyle n\ b\ f=b^{n}\ f}
,因此:
exp
b
n
=
b
n
=
n
b
{\displaystyle \operatorname {exp} \ b\ n=b^{n}=n\ b}
对应的lambda表达式为:
exp
≡
λ
b
.
λ
n
.
n
b
{\displaystyle \operatorname {exp} \equiv \lambda b.\lambda n.n\ b}
前驱函数
pred
(
n
)
{\displaystyle {\text{pred}}(n)}
的实现较为复杂:
pred
≡
λ
n
.
λ
f
.
λ
x
.
n
(
λ
g
.
λ
h
.
h
(
g
f
)
)
(
λ
u
.
x
)
(
λ
u
.
u
)
{\displaystyle \operatorname {pred} \equiv \lambda n.\lambda f.\lambda x.n\ (\lambda g.\lambda h.h\ (g\ f))\ (\lambda u.x)\ (\lambda u.u)}
邱奇数通过n 次应用函数来运作。前驱函数需要返回一个应用参数n-1 次的函数。这通过构建包含f 和x 的容器来实现,该容器以省略第一次函数应用的方式初始化(详见前驱函数推导 )。
基于前驱函数可定义减法函数:
minus
≡
λ
m
.
λ
n
.
(
n
pred
)
m
{\displaystyle \operatorname {minus} \equiv \lambda m.\lambda n.(n\operatorname {pred} )\ m}
注意 :
^ 此公式是邱奇数 n 的定义,其中
f
→
b
,
x
→
f
{\displaystyle f\to b,x\to f}
。
^ 2.0 2.1 在邱奇编码中,
pred
(
0
)
=
0
{\displaystyle \operatorname {pred} (0)=0}
m
≤
n
→
m
−
n
=
0
{\displaystyle m\leq n\to m-n=0}
邱奇编码中使用的前驱函数定义为:
pred
(
n
)
=
{
0
若
n
=
0
,
n
−
1
否 则
{\displaystyle \operatorname {pred} (n)={\begin{cases}0&{\mbox{ 若 }}n=0,\\n-1&{\mbox{ 否 则 }}\end{cases}}}
为了减少一次函数应用次数来构造前驱函数,需采用容器函数封装值。定义新函数 inc 和 init 替代原函数f 和参数x ,其中容器函数称为value 。下表左侧展示了邱奇数n 作用于inc 和init 的情况:
邱 奇 数
使 用 init
使 用 const
0
init
=
value
x
1
inc
init
=
value
(
f
x
)
inc
const
=
value
x
2
inc
(
inc
init
)
=
value
(
f
(
f
x
)
)
inc
(
inc
const
)
=
value
(
f
x
)
3
inc
(
inc
(
inc
init
)
)
=
value
(
f
(
f
(
f
x
)
)
)
inc
(
inc
(
inc
const
)
)
=
value
(
f
(
f
x
)
)
⋮
⋮
⋮
n
n
inc
init
=
value
(
f
n
x
)
=
value
(
n
f
x
)
n
inc
const
=
value
(
f
n
−
1
x
)
=
value
(
(
n
−
1
)
f
x
)
{\displaystyle {\begin{array}{r|r|r}{\text{ 邱 奇 数 }}&{\text{ 使 用 init}}&{\text{ 使 用 const}}\\\hline 0&\operatorname {init} =\operatorname {value} \ x&\\1&\operatorname {inc} \ \operatorname {init} =\operatorname {value} \ (f\ x)&\operatorname {inc} \ \operatorname {const} =\operatorname {value} \ x\\2&\operatorname {inc} \ (\operatorname {inc} \ \operatorname {init} )=\operatorname {value} \ (f\ (f\ x))&\operatorname {inc} \ (\operatorname {inc} \ \operatorname {const} )=\operatorname {value} \ (f\ x)\\3&\operatorname {inc} \ (\operatorname {inc} \ (\operatorname {inc} \ \operatorname {init} ))=\operatorname {value} \ (f\ (f\ (f\ x)))&\operatorname {inc} \ (\operatorname {inc} \ (\operatorname {inc} \ \operatorname {const} ))=\operatorname {value} \ (f\ (f\ x))\\\vdots &\vdots &\vdots \\n&n\operatorname {inc} \ \operatorname {init} =\operatorname {value} \ (f^{n}\ x)=\operatorname {value} \ (n\ f\ x)&n\operatorname {inc} \ \operatorname {const} =\operatorname {value} \ (f^{n-1}\ x)=\operatorname {value} \ ((n-1)\ f\ x)\\\end{array}}}
通用递归规则为:
inc
(
value
v
)
=
value
(
f
v
)
{\displaystyle \operatorname {inc} \ (\operatorname {value} \ v)=\operatorname {value} \ (f\ v)}
若定义从容器中提取值的函数extract :
extract
(
value
v
)
=
v
{\displaystyle \operatorname {extract} \ (\operatorname {value} \ v)=v}
则可构造同数函数samenum :
samenum
=
λ
n
.
λ
f
.
λ
x
.
extract
(
n
inc
init
)
=
λ
n
.
λ
f
.
λ
x
.
extract
(
value
(
n
f
x
)
)
=
λ
n
.
λ
f
.
λ
x
.
n
f
x
=
λ
n
.
n
{\displaystyle \operatorname {samenum} =\lambda n.\lambda f.\lambda x.\operatorname {extract} \ (n\operatorname {inc} \operatorname {init} )=\lambda n.\lambda f.\lambda x.\operatorname {extract} \ (\operatorname {value} \ (n\ f\ x))=\lambda n.\lambda f.\lambda x.n\ f\ x=\lambda n.n}
通过将init 替换为特殊容器const (该容器首次调用时忽略参数以跳过第一次函数应用),可推导前驱函数:
pred
=
λ
n
.
λ
f
.
λ
x
.
extract
(
n
inc
const
)
=
λ
n
.
λ
f
.
λ
x
.
extract
(
value
(
(
n
−
1
)
f
x
)
)
=
λ
n
.
λ
f
.
λ
x
.
(
n
−
1
)
f
x
=
λ
n
.
(
n
−
1
)
{\displaystyle \operatorname {pred} =\lambda n.\lambda f.\lambda x.\operatorname {extract} \ (n\operatorname {inc} \operatorname {const} )=\lambda n.\lambda f.\lambda x.\operatorname {extract} \ (\operatorname {value} \ ((n-1)\ f\ x))=\lambda n.\lambda f.\lambda x.(n-1)\ f\ x=\lambda n.(n-1)}
具体函数定义如下:
value
=
λ
v
.
(
λ
h
.
h
v
)
extract
k
=
k
λ
u
.
u
inc
=
λ
g
.
λ
h
.
h
(
g
f
)
init
=
λ
h
.
h
x
const
=
λ
u
.
x
{\displaystyle {\begin{aligned}\operatorname {value} &=\lambda v.(\lambda h.h\ v)\\\operatorname {extract} k&=k\ \lambda u.u\\\operatorname {inc} &=\lambda g.\lambda h.h\ (g\ f)\\\operatorname {init} &=\lambda h.h\ x\\\operatorname {const} &=\lambda u.x\end{aligned}}}
最终得到前驱函数的lambda表达式:
pred
=
λ
n
.
λ
f
.
λ
x
.
n
(
λ
g
.
λ
h
.
h
(
g
f
)
)
(
λ
u
.
x
)
(
λ
u
.
u
)
{\displaystyle \operatorname {pred} =\lambda n.\lambda f.\lambda x.n\ (\lambda g.\lambda h.h\ (g\ f))\ (\lambda u.x)\ (\lambda u.u)}
值容器将函数作用于其内部值,定义为:
value
v
h
=
h
v
{\displaystyle \operatorname {value} \ v\ h=h\ v}
即:
value
=
λ
v
.
(
λ
h
.
h
v
)
{\displaystyle \operatorname {value} =\lambda v.(\lambda h.h\ v)}
inc 函数需接收包含v 的容器,返回包含f v 的新容器:
inc
(
value
v
)
=
value
(
f
v
)
{\displaystyle \operatorname {inc} \ (\operatorname {value} \ v)=\operatorname {value} \ (f\ v)}
设g 为值容器:
g
=
value
v
{\displaystyle g=\operatorname {value} \ v}
则:
g
f
=
value
v
f
=
f
v
{\displaystyle g\ f=\operatorname {value} \ v\ f=f\ v}
因此:
inc
g
=
value
(
g
f
)
{\displaystyle \operatorname {inc} \ g=\operatorname {value} \ (g\ f)}
inc
=
λ
g
.
λ
h
.
h
(
g
f
)
{\displaystyle \operatorname {inc} =\lambda g.\lambda h.h\ (g\ f)}
通过应用恒等函数提取值:
I
=
λ
u
.
u
{\displaystyle I=\lambda u.u}
利用I 可得:
value
v
I
=
v
{\displaystyle \operatorname {value} \ v\ I=v}
故:
extract
k
=
k
I
{\displaystyle \operatorname {extract} \ k=k\ I}
为实现pred 函数,需将init 替换为不应用f 的const 容器。该容器需满足:
inc
const
=
value
x
{\displaystyle \operatorname {inc} \ \operatorname {const} =\operatorname {value} \ x}
λ
h
.
h
(
const
f
)
=
λ
h
.
h
x
{\displaystyle \lambda h.h\ (\operatorname {const} \ f)=\lambda h.h\ x}
当满足条件:
const
f
=
x
{\displaystyle \operatorname {const} \ f=x}
对应的lambda表达式为:
const
=
λ
u
.
x
{\displaystyle \operatorname {const} =\lambda u.x}
使用组合子符号可简化前驱函数的解释:
K
x
y
=
x
{\displaystyle Kxy=x}
I
x
=
x
{\displaystyle Ix=x}
X
f
r
i
=
i
(
r
f
)
{\displaystyle Xfri=i(rf)}
P
r
e
d
n
f
x
=
n
(
X
f
)
(
K
x
)
I
{\displaystyle Pred\ nfx=n(Xf)(Kx)I}
通过下列推导可验证其正确性:
P
r
e
d
(
S
u
c
c
n
)
f
x
=
S
u
c
c
n
(
X
f
)
(
K
x
)
I
=
X
f
(
n
(
X
f
)
(
K
x
)
)
I
{\displaystyle Pred\ (Succ\ n)fx=Succ\ n(Xf)(Kx)I=Xf(n(Xf)(Kx))I}
=
I
(
n
(
X
f
)
(
K
x
)
f
)
=
.
.
.
=
I
(
f
(
f
.
.
.
(
f
(
K
x
f
)
)
.
.
.
)
)
=
I
(
n
f
x
)
=
n
f
x
{\displaystyle \ \ \ \ =I(n(Xf)(Kx)f)=\ ...\ =I(f(f...(f(Kxf))...))=I(nfx)=nfx}
P
r
e
d
Z
e
r
o
f
x
=
Z
e
r
o
(
X
f
)
(
K
x
)
I
=
K
x
I
=
x
=
Z
e
r
o
f
x
{\displaystyle Pred\ Zero\ fx=\ Zero(Xf)(Kx)I=\ KxI=\ x=\ Zero\ fx}
通过eta-归约和归纳法可得:
P
r
e
d
(
S
u
c
c
n
)
=
n
{\displaystyle Pred\ (Succ\ n)=n}
P
r
e
d
Z
e
r
o
=
Z
e
r
o
{\displaystyle Pred\ Zero=Zero}
P
r
e
d
(
P
r
e
d
Z
e
r
o
)
=
P
r
e
d
Z
e
r
o
=
Z
e
r
o
{\displaystyle Pred\ (Pred\ Zero)=\ Pred\ Zero=\ Zero}
使用序对可定义前驱函数:
f
=
λ
p
.
pair
(
second
p
)
(
succ
(
second
p
)
)
zero
=
(
λ
f
.
λ
x
.
x
)
pc0
=
pair
zero
zero
pred
=
λ
n
.
first
(
n
f
pc0
)
{\displaystyle {\begin{aligned}\operatorname {f} =&\ \lambda p.\ \operatorname {pair} \ (\operatorname {second} \ p)\ (\operatorname {succ} \ (\operatorname {second} \ p))\\\operatorname {zero} =&\ (\lambda f.\lambda x.\ x)\\\operatorname {pc0} =&\ \operatorname {pair} \ \operatorname {zero} \ \operatorname {zero} \\\operatorname {pred} =&\ \lambda n.\ \operatorname {first} \ (n\ \operatorname {f} \ \operatorname {pc0} )\\\end{aligned}}}
此定义虽简洁但展开式较复杂,以
pred
three
{\displaystyle \operatorname {pred} \operatorname {three} }
为例:
pred
three
=
first
(
f
(
f
(
f
(
pair
zero
zero
)
)
)
)
=
first
(
f
(
f
(
pair
zero
one
)
)
)
=
first
(
f
(
pair
one
two
)
)
=
first
(
pair
two
three
)
=
two
{\displaystyle {\begin{aligned}\operatorname {pred} \operatorname {three} =&\ \operatorname {first} \ (\operatorname {f} \ (\operatorname {f} \ (\operatorname {f} \ (\operatorname {pair} \ \operatorname {zero} \ \operatorname {zero} ))))\\=&\ \operatorname {first} \ (\operatorname {f} \ (\operatorname {f} \ (\operatorname {pair} \ \operatorname {zero} \ \operatorname {one} )))\\=&\ \operatorname {first} \ (\operatorname {f} \ (\operatorname {pair} \ \operatorname {one} \ \operatorname {two} ))\\=&\ \operatorname {first} \ (\operatorname {pair} \ \operatorname {two} \ \operatorname {three} )\\=&\ \operatorname {two} \end{aligned}}}
自然数除法 可通过以下方式实现:[ 4]
n
/
m
=
if
n
≥
m
then
1
+
(
n
−
m
)
/
m
else
0
{\displaystyle n/m=\operatorname {if} \ n\geq m\ \operatorname {then} \ 1+(n-m)/m\ \operatorname {else} \ 0}
计算
n
−
m
{\displaystyle n-m}
需要多次beta归约。除非手动进行归约,否则这并不重要,但最好避免重复计算。最简单的数值检测谓词是IsZero ,故考虑条件:
IsZero
(
minus
n
m
)
{\displaystyle \operatorname {IsZero} \ (\operatorname {minus} \ n\ m)}
此条件等价于
n
≤
m
{\displaystyle n\leq m}
而非
n
<
m
{\displaystyle n<m}
。若采用该条件,则上述数学定义可转化为邱奇数函数:
divide1
n
m
f
x
=
(
λ
d
.
IsZero
d
(
0
f
x
)
(
f
(
divide1
d
m
f
x
)
)
)
(
minus
n
m
)
{\displaystyle \operatorname {divide1} \ n\ m\ f\ x=(\lambda d.\operatorname {IsZero} \ d\ (0\ f\ x)\ (f\ (\operatorname {divide1} \ d\ m\ f\ x)))\ (\operatorname {minus} \ n\ m)}
此定义仅调用一次
minus
n
m
{\displaystyle \operatorname {minus} \ n\ m}
,但结果为此公式给出的是
(
n
−
1
)
/
m
{\displaystyle (n-1)/m}
的值。
通过给n 加1后调用divide 可修正该问题,定义式为:
divide
n
=
divide1
(
succ
n
)
{\displaystyle \operatorname {divide} \ n=\operatorname {divide1} \ (\operatorname {succ} \ n)}
divide1 为递归定义,需用Y组合子 实现递归。通过以下步骤创建新函数div :
左侧替换:
divide1
→
div
c
{\displaystyle \operatorname {divide1} \rightarrow \operatorname {div} \ c}
右侧替换:
divide1
→
c
{\displaystyle \operatorname {divide1} \rightarrow c}
得到:
div
=
λ
c
.
λ
n
.
λ
m
.
λ
f
.
λ
x
.
(
λ
d
.
IsZero
d
(
0
f
x
)
(
f
(
c
d
m
f
x
)
)
)
(
minus
n
m
)
{\displaystyle \operatorname {div} =\lambda c.\lambda n.\lambda m.\lambda f.\lambda x.(\lambda d.\operatorname {IsZero} \ d\ (0\ f\ x)\ (f\ (c\ d\ m\ f\ x)))\ (\operatorname {minus} \ n\ m)}
完整定义式为:
divide
=
λ
n
.
divide1
(
succ
n
)
{\displaystyle \operatorname {divide} =\lambda n.\operatorname {divide1} \ (\operatorname {succ} \ n)}
其中:
divide1
=
Y
div
succ
=
λ
n
.
λ
f
.
λ
x
.
f
(
n
f
x
)
Y
=
λ
f
.
(
λ
x
.
f
(
x
x
)
)
(
λ
x
.
f
(
x
x
)
)
0
=
λ
f
.
λ
x
.
x
IsZero
=
λ
n
.
n
(
λ
x
.
false
)
true
{\displaystyle {\begin{aligned}\operatorname {divide1} &=Y\ \operatorname {div} \\\operatorname {succ} &=\lambda n.\lambda f.\lambda x.f\ (n\ f\ x)\\Y&=\lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))\\0&=\lambda f.\lambda x.x\\\operatorname {IsZero} &=\lambda n.n\ (\lambda x.\operatorname {false} )\ \operatorname {true} \end{aligned}}}
true
≡
λ
a
.
λ
b
.
a
false
≡
λ
a
.
λ
b
.
b
{\displaystyle {\begin{aligned}\operatorname {true} &\equiv \lambda a.\lambda b.a\\\operatorname {false} &\equiv \lambda a.\lambda b.b\end{aligned}}}
minus
=
λ
m
.
λ
n
.
n
pred
m
pred
=
λ
n
.
λ
f
.
λ
x
.
n
(
λ
g
.
λ
h
.
h
(
g
f
)
)
(
λ
u
.
x
)
(
λ
u
.
u
)
{\displaystyle {\begin{aligned}\operatorname {minus} &=\lambda m.\lambda n.n\operatorname {pred} m\\\operatorname {pred} &=\lambda n.\lambda f.\lambda x.n\ (\lambda g.\lambda h.h\ (g\ f))\ (\lambda u.x)\ (\lambda u.u)\end{aligned}}}
最终展开式:
divide
=
λ
n
.
(
(
λ
f
.
(
λ
x
.
x
x
)
(
λ
x
.
f
(
x
x
)
)
)
(
λ
c
.
λ
n
.
λ
m
.
λ
f
.
λ
x
.
(
λ
d
.
(
λ
n
.
n
(
λ
x
.
(
λ
a
.
λ
b
.
b
)
)
(
λ
a
.
λ
b
.
a
)
)
d
(
(
λ
f
.
λ
x
.
x
)
f
x
)
(
f
(
c
d
m
f
x
)
)
)
(
(
λ
m
.
λ
n
.
n
(
λ
n
.
λ
f
.
λ
x
.
n
(
λ
g
.
λ
h
.
h
(
g
f
)
)
(
λ
u
.
x
)
(
λ
u
.
u
)
)
m
)
n
m
)
)
)
(
(
λ
n
.
λ
f
.
λ
x
.
f
(
n
f
x
)
)
n
)
{\displaystyle \scriptstyle \operatorname {divide} =\lambda n.((\lambda f.(\lambda x.x\ x)\ (\lambda x.f\ (x\ x)))\ (\lambda c.\lambda n.\lambda m.\lambda f.\lambda x.(\lambda d.(\lambda n.n\ (\lambda x.(\lambda a.\lambda b.b))\ (\lambda a.\lambda b.a))\ d\ ((\lambda f.\lambda x.x)\ f\ x)\ (f\ (c\ d\ m\ f\ x)))\ ((\lambda m.\lambda n.n(\lambda n.\lambda f.\lambda x.n\ (\lambda g.\lambda h.h\ (g\ f))\ (\lambda u.x)\ (\lambda u.u))m)\ n\ m)))\ ((\lambda n.\lambda f.\lambda x.f\ (n\ f\ x))\ n)}
以文本格式表示(用\代替λ):
divide = (\n.((\f.(\x.x x) (\x.f (x x))) (\c.\n.\m.\f.\x.(\d.(\n.n (\x.(\a.\b.b)) (\a.\b.a)) d ((\f.\x.x) f x) (f (c d m f x))) ((\m.\n.n (\n.\f.\x.n (\g.\h.h (g f)) (\u.x) (\u.u)) m) n m))) ((\n.\f.\x. f (n f x)) n))
例如,9/3可表示为:
divide (\f.\x.f (f (f (f (f (f (f (f (f x))))))))) (\f.\x.f (f (f x)))
使用lambda演算计算器,按正规顺序归约后结果为3:
\f.\x.f (f (f (x)))
通过使用包含正负值的邱奇序对,可将邱奇数扩展至有符号数 [ 5] 。整数值即两个邱奇数的差值。
自然数转有符号数的定义为:
convert
s
=
λ
x
.
pair
x
0
{\displaystyle \operatorname {convert} _{s}=\lambda x.\operatorname {pair} \ x\ 0}
取反操作通过交换序对元素实现:
neg
s
=
λ
x
.
pair
(
second
x
)
(
first
x
)
{\displaystyle \operatorname {neg} _{s}=\lambda x.\operatorname {pair} \ (\operatorname {second} \ x)\ (\operatorname {first} \ x)}
当序对中某一元素为零时,整数表示更自然。OneZero 函数确保该条件:
OneZero
=
λ
x
.
IsZero
(
first
x
)
x
(
IsZero
(
second
x
)
x
(
OneZero
(
pair
(
pred
(
first
x
)
)
(
pred
(
second
x
)
)
)
)
)
{\displaystyle \operatorname {OneZero} =\lambda x.\operatorname {IsZero} \ (\operatorname {first} \ x)\ x\ (\operatorname {IsZero} \ (\operatorname {second} \ x)\ x\ (\operatorname {OneZero} \ (\operatorname {pair} \ (\operatorname {pred} \ (\operatorname {first} \ x))\ (\operatorname {pred} \ (\operatorname {second} \ x)))))}
使用Y组合子实现递归:
OneZ
=
λ
c
.
λ
x
.
IsZero
(
first
x
)
x
(
IsZero
(
second
x
)
x
(
c
(
pair
(
pred
(
first
x
)
)
(
pred
(
second
x
)
)
)
)
)
{\displaystyle \operatorname {OneZ} =\lambda c.\lambda x.\operatorname {IsZero} \ (\operatorname {first} \ x)\ x\ (\operatorname {IsZero} \ (\operatorname {second} \ x)\ x\ (c\ (\operatorname {pair} \ (\operatorname {pred} \ (\operatorname {first} \ x))\ (\operatorname {pred} \ (\operatorname {second} \ x)))))}
OneZero
=
Y
OneZ
{\displaystyle \operatorname {OneZero} =Y\operatorname {OneZ} }
加法数学定义为:
x
+
y
=
[
x
p
,
x
n
]
+
[
y
p
,
y
n
]
=
(
x
p
+
y
p
)
−
(
x
n
+
y
n
)
=
[
x
p
+
y
p
,
x
n
+
y
n
]
{\displaystyle x+y=[x_{p},x_{n}]+[y_{p},y_{n}]=(x_{p}+y_{p})-(x_{n}+y_{n})=[x_{p}+y_{p},x_{n}+y_{n}]}
对应lambda表达式:
plus
s
=
λ
x
.
λ
y
.
OneZero
(
pair
(
plus
(
first
x
)
(
first
y
)
)
(
plus
(
second
x
)
(
second
y
)
)
)
{\displaystyle \operatorname {plus} _{s}=\lambda x.\lambda y.\operatorname {OneZero} \ (\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {first} \ x)\ (\operatorname {first} \ y))\ (\operatorname {plus} \ (\operatorname {second} \ x)\ (\operatorname {second} \ y)))}
减法定义为:
x
−
y
=
[
x
p
,
x
n
]
−
[
y
p
,
y
n
]
=
(
x
p
+
y
n
)
−
(
x
n
+
y
p
)
=
[
x
p
+
y
n
,
x
n
+
y
p
]
{\displaystyle x-y=[x_{p},x_{n}]-[y_{p},y_{n}]=(x_{p}+y_{n})-(x_{n}+y_{p})=[x_{p}+y_{n},x_{n}+y_{p}]}
对应lambda表达式:
minus
s
=
λ
x
.
λ
y
.
OneZero
(
pair
(
plus
(
first
x
)
(
second
y
)
)
(
plus
(
second
x
)
(
first
y
)
)
)
{\displaystyle \operatorname {minus} _{s}=\lambda x.\lambda y.\operatorname {OneZero} \ (\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {first} \ x)\ (\operatorname {second} \ y))\ (\operatorname {plus} \ (\operatorname {second} \ x)\ (\operatorname {first} \ y)))}
乘法定义为:
x
∗
y
=
(
x
p
∗
y
p
+
x
n
∗
y
n
)
−
(
x
p
∗
y
n
+
x
n
∗
y
p
)
=
[
x
p
∗
y
p
+
x
n
∗
y
n
,
x
p
∗
y
n
+
x
n
∗
y
p
]
{\displaystyle x*y=(x_{p}*y_{p}+x_{n}*y_{n})-(x_{p}*y_{n}+x_{n}*y_{p})=[x_{p}*y_{p}+x_{n}*y_{n},x_{p}*y_{n}+x_{n}*y_{p}]}
对应lambda表达式:
mult
s
=
λ
x
.
λ
y
.
pair
(
plus
(
mult
(
first
x
)
(
first
y
)
)
(
mult
(
second
x
)
(
second
y
)
)
)
(
plus
(
mult
(
first
x
)
(
second
y
)
)
(
mult
(
second
x
)
(
first
y
)
)
)
{\displaystyle \operatorname {mult} _{s}=\lambda x.\lambda y.\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {mult} \ (\operatorname {first} \ x)\ (\operatorname {first} \ y))\ (\operatorname {mult} \ (\operatorname {second} \ x)\ (\operatorname {second} \ y)))\ (\operatorname {plus} \ (\operatorname {mult} \ (\operatorname {first} \ x)\ (\operatorname {second} \ y))\ (\operatorname {mult} \ (\operatorname {second} \ x)\ (\operatorname {first} \ y)))}
除法需确保序对元素含零(见上文的OneZero ),定义辅助函数:
divZ
=
λ
x
.
λ
y
.
IsZero
y
0
(
divide
x
y
)
{\displaystyle \operatorname {divZ} =\lambda x.\lambda y.\operatorname {IsZero} \ y\ 0\ (\operatorname {divide} \ x\ y)}
除法表达式:
divide
s
=
λ
x
.
λ
y
.
pair
(
plus
(
divZ
(
first
x
)
(
first
y
)
)
(
divZ
(
second
x
)
(
second
y
)
)
)
(
plus
(
divZ
(
first
x
)
(
second
y
)
)
(
divZ
(
second
x
)
(
first
y
)
)
)
{\displaystyle \operatorname {divide} _{s}=\lambda x.\lambda y.\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {divZ} \ (\operatorname {first} \ x)\ (\operatorname {first} \ y))\ (\operatorname {divZ} \ (\operatorname {second} \ x)\ (\operatorname {second} \ y)))\ (\operatorname {plus} \ (\operatorname {divZ} \ (\operatorname {first} \ x)\ (\operatorname {second} \ y))\ (\operatorname {divZ} \ (\operatorname {second} \ x)\ (\operatorname {first} \ y)))}
有理数可表示为有符号数序对,可计算实数 可通过极限过程编码[ 6] [ 7] 。复数可自然地表示为实数序对。上述数据类型验证了邱奇-图灵论题 :任何数据类型或计算均可编码于lambda演算中。
大部分真实世界的编程语言都提供原生于机器的整数,church 与 unchurch 函式会在整数及与之对应的邱奇数间转换。这里使用Haskell 撰写函式, \
等同于lambda演算的 λ。 用其它语言表达也会很类似。
type Church a = ( a -> a ) -> a -> a
church :: Integer -> Church Integer
church 0 = \ f -> \ x -> x
church n = \ f -> \ x -> f ( church ( n - 1 ) f x )
unchurch :: Church Integer -> Integer
unchurch cn = cn ( + 1 ) 0
邱奇布尔值 是布尔值真 和假 的邱奇编码形式。某些编程语言使用这个方式来实践布尔算术的模型,Smalltalk 和Pico 即为典型示例。
布尔逻辑本质上是选择机制。邱奇布尔值的编码形式为接收两个参数的函数:
真 (true)选择第一个参数
假 (false)选择第二个参数
其标准定义为:
true
≡
λ
a
.
λ
b
.
a
false
≡
λ
a
.
λ
b
.
b
{\displaystyle {\begin{aligned}\operatorname {true} &\equiv \lambda a.\lambda b.a\\\operatorname {false} &\equiv \lambda a.\lambda b.b\end{aligned}}}
这种编码允许谓词函数(返回逻辑值 的函数)直接作为条件语句使用。当布尔函数作用于两个参数时,将根据真值返回其中一个参数:
p
r
e
d
i
c
a
t
e
-
x
t
h
e
n
-
c
l
a
u
s
e
e
l
s
e
-
c
l
a
u
s
e
{\displaystyle \operatorname {predicate-} x\ \operatorname {then-clause} \ \operatorname {else-clause} }
若predicate-x 为真则返回then-clause ,否则返回else-clause 。
由于真值与假值的选择特性,它们可组合出各类逻辑运算符。需注意逻辑非not 存在多种实现方式:
and
=
λ
p
.
λ
q
.
p
q
p
or
=
λ
p
.
λ
q
.
p
p
q
not
1
=
λ
p
.
λ
a
.
λ
b
.
p
b
a
not
2
=
λ
p
.
p
(
λ
a
.
λ
b
.
b
)
(
λ
a
.
λ
b
.
a
)
=
λ
p
.
p
false
true
xor
=
λ
a
.
λ
b
.
a
(
not
b
)
b
if
=
λ
p
.
λ
a
.
λ
b
.
p
a
b
{\displaystyle {\begin{aligned}\operatorname {and} &=\lambda p.\lambda q.p\ q\ p\\\operatorname {or} &=\lambda p.\lambda q.p\ p\ q\\\operatorname {not} _{1}&=\lambda p.\lambda a.\lambda b.p\ b\ a\\\operatorname {not} _{2}&=\lambda p.p\ (\lambda a.\lambda b.b)\ (\lambda a.\lambda b.a)=\lambda p.p\operatorname {false} \operatorname {true} \\\operatorname {xor} &=\lambda a.\lambda b.a\ (\operatorname {not} \ b)\ b\\\operatorname {if} &=\lambda p.\lambda a.\lambda b.p\ a\ b\end{aligned}}}
注:
1 求值策略使用应用次序时,这个方法才正确。
2 求值策略使用正常次序时,这个方法才正确。
运算示例解析:
and
true
false
=
(
λ
p
.
λ
q
.
p
q
p
)
true
false
=
true
false
true
=
(
λ
a
.
λ
b
.
a
)
false
true
=
false
or
true
false
=
(
λ
p
.
λ
q
.
p
p
q
)
(
λ
a
.
λ
b
.
a
)
(
λ
a
.
λ
b
.
b
)
=
(
λ
a
.
λ
b
.
a
)
(
λ
a
.
λ
b
.
a
)
(
λ
a
.
λ
b
.
b
)
=
(
λ
a
.
λ
b
.
a
)
=
true
not
1
true
=
(
λ
p
.
λ
a
.
λ
b
.
p
b
a
)
(
λ
a
.
λ
b
.
a
)
=
λ
a
.
λ
b
.
(
λ
a
.
λ
b
.
a
)
b
a
=
λ
a
.
λ
b
.
(
λ
c
.
b
)
a
=
λ
a
.
λ
b
.
b
=
false
not
2
true
=
(
λ
p
.
p
(
λ
a
.
λ
b
.
b
)
(
λ
a
.
λ
b
.
a
)
)
(
λ
a
.
λ
b
.
a
)
=
(
λ
a
.
λ
b
.
a
)
(
λ
a
.
λ
b
.
b
)
(
λ
a
.
λ
b
.
a
)
=
(
λ
b
.
(
λ
a
.
λ
b
.
b
)
)
(
λ
a
.
λ
b
.
a
)
=
λ
a
.
λ
b
.
b
=
false
{\displaystyle {\begin{aligned}\operatorname {and} \operatorname {true} \operatorname {false} &=(\lambda p.\lambda q.p\ q\ p)\ \operatorname {true} \ \operatorname {false} =\operatorname {true} \operatorname {false} \operatorname {true} =(\lambda a.\lambda b.a)\operatorname {false} \operatorname {true} =\operatorname {false} \\\operatorname {or} \operatorname {true} \operatorname {false} &=(\lambda p.\lambda q.p\ p\ q)\ (\lambda a.\lambda b.a)\ (\lambda a.\lambda b.b)=(\lambda a.\lambda b.a)\ (\lambda a.\lambda b.a)\ (\lambda a.\lambda b.b)=(\lambda a.\lambda b.a)=\operatorname {true} \\\operatorname {not} _{1}\ \operatorname {true} &=(\lambda p.\lambda a.\lambda b.p\ b\ a)(\lambda a.\lambda b.a)=\lambda a.\lambda b.(\lambda a.\lambda b.a)\ b\ a=\lambda a.\lambda b.(\lambda c.b)\ a=\lambda a.\lambda b.b=\operatorname {false} \\\operatorname {not} _{2}\ \operatorname {true} &=(\lambda p.p\ (\lambda a.\lambda b.b)(\lambda a.\lambda b.a))(\lambda a.\lambda b.a)=(\lambda a.\lambda b.a)(\lambda a.\lambda b.b)(\lambda a.\lambda b.a)=(\lambda b.(\lambda a.\lambda b.b))\ (\lambda a.\lambda b.a)=\lambda a.\lambda b.b=\operatorname {false} \end{aligned}}}
谓词 是返回布尔值的函数。最基础的谓词是
IsZero
{\displaystyle \operatorname {IsZero} }
,当其参数为邱奇数
0
{\displaystyle 0}
时返回
true
{\displaystyle \operatorname {true} }
,否则返回
false
{\displaystyle \operatorname {false} }
:
IsZero
=
λ
n
.
n
(
λ
x
.
false
)
true
{\displaystyle \operatorname {IsZero} =\lambda n.n\ (\lambda x.\operatorname {false} )\ \operatorname {true} }
下列谓词检测第一个参数是否小于等于第二个参数:
LEQ
=
λ
m
.
λ
n
.
IsZero
(
minus
m
n
)
{\displaystyle \operatorname {LEQ} =\lambda m.\lambda n.\operatorname {IsZero} \ (\operatorname {minus} \ m\ n)}
基于恒等关系:
x
=
y
≡
(
x
≤
y
∧
y
≤
x
)
{\displaystyle x=y\equiv (x\leq y\land y\leq x)}
相等性检测可定义为:
EQ
=
λ
m
.
λ
n
.
and
(
LEQ
m
n
)
(
LEQ
n
m
)
{\displaystyle \operatorname {EQ} =\lambda m.\lambda n.\operatorname {and} \ (\operatorname {LEQ} \ m\ n)\ (\operatorname {LEQ} \ n\ m)}
邱奇序对是二元组 的邱奇编码实现。序对被表示为接收函数的函数,当传入参数时会将该参数作用于序对的两个分量。其lambda演算 定义为:
pair
≡
λ
x
.
λ
y
.
λ
z
.
z
x
y
first
≡
λ
p
.
p
(
λ
x
.
λ
y
.
x
)
second
≡
λ
p
.
p
(
λ
x
.
λ
y
.
y
)
{\displaystyle {\begin{aligned}\operatorname {pair} &\equiv \lambda x.\lambda y.\lambda z.z\ x\ y\\\operatorname {first} &\equiv \lambda p.p\ (\lambda x.\lambda y.x)\\\operatorname {second} &\equiv \lambda p.p\ (\lambda x.\lambda y.y)\end{aligned}}}
示例推导:
first
(
pair
a
b
)
=
(
λ
p
.
p
(
λ
x
.
λ
y
.
x
)
)
(
(
λ
x
.
λ
y
.
λ
z
.
z
x
y
)
a
b
)
=
(
λ
p
.
p
(
λ
x
.
λ
y
.
x
)
)
(
λ
z
.
z
a
b
)
=
(
λ
z
.
z
a
b
)
(
λ
x
.
λ
y
.
x
)
=
(
λ
x
.
λ
y
.
x
)
a
b
=
a
{\displaystyle {\begin{aligned}&\operatorname {first} \ (\operatorname {pair} \ a\ b)\\=&(\lambda p.p\ (\lambda x.\lambda y.x))\ ((\lambda x.\lambda y.\lambda z.z\ x\ y)\ a\ b)\\=&(\lambda p.p\ (\lambda x.\lambda y.x))\ (\lambda z.z\ a\ b)\\=&(\lambda z.z\ a\ b)\ (\lambda x.\lambda y.x)\\=&(\lambda x.\lambda y.x)\ a\ b=a\end{aligned}}}
不可变 的列表 由列表节点构成,其基本操作包括:
函数
描述
nil
构造空列表
isnil
检测列表是否为空
cons
在列表头部添加元素
head
获取列表首元素
tail
获取列表尾部
以下给出四种不同的列表表示法:
使用双序对构造列表节点(支持空列表)
使用单序对构造列表节点
基于右折叠函数 的列表表示
采用Scott编码的模式匹配参数化表示
非空列表可用邱奇序对表示:
为支持空列表,需额外包裹序对形成三层结构:
First - 空列表标识符
Second.First 存储首元素
Second.Second 存储尾部
基于此的核心操作定义如下:[ 8]
表达式
描述
nil
≡
pair
true
true
{\displaystyle \operatorname {nil} \equiv \operatorname {pair} \ \operatorname {true} \ \operatorname {true} }
序对首元素为true表示空列表
isnil
≡
first
{\displaystyle \operatorname {isnil} \equiv \operatorname {first} }
提取空列表标识符
cons
≡
λ
h
.
λ
t
.
pair
false
(
pair
h
t
)
{\displaystyle \operatorname {cons} \equiv \lambda h.\lambda t.\operatorname {pair} \operatorname {false} \ (\operatorname {pair} h\ t)}
构造非空列表节点
head
≡
λ
z
.
first
(
second
z
)
{\displaystyle \operatorname {head} \equiv \lambda z.\operatorname {first} \ (\operatorname {second} z)}
通过second.first获取首元素
tail
≡
λ
z
.
second
(
second
z
)
{\displaystyle \operatorname {tail} \equiv \lambda z.\operatorname {second} \ (\operatorname {second} z)}
通过second.second获取尾部
注意:当列表为空时,head和tail函数不应被调用。
另一种定义方式[ 9] :
cons
≡
pair
head
≡
first
tail
≡
second
nil
≡
false
isnil
≡
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
false
)
true
{\displaystyle {\begin{aligned}\operatorname {cons} &\equiv \operatorname {pair} \\\operatorname {head} &\equiv \operatorname {first} \\\operatorname {tail} &\equiv \operatorname {second} \\\operatorname {nil} &\equiv \operatorname {false} \\\operatorname {isnil} &\equiv \lambda l.l(\lambda h.\lambda t.\lambda d.\operatorname {false} )\operatorname {true} \\\end{aligned}}}
通用处理模板定义为:
p
r
o
c
e
s
s
-
l
i
s
t
≡
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
h
e
a
d
-
a
n
d
-
t
a
i
l
-
c
l
a
u
s
e
)
n
i
l
-
c
l
a
u
s
e
{\displaystyle {\begin{aligned}\operatorname {process-list} &\equiv \lambda l.l(\lambda h.\lambda t.\lambda d.\operatorname {head-and-tail-clause} )\operatorname {nil-clause} \\\end{aligned}}}
其他扩展操作:
t
a
i
l
-
o
r
-
n
i
l
≡
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
t
)
nil
fold
≡
λ
f
.
Y
(
λ
r
.
λ
a
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
r
(
f
a
h
)
t
)
a
)
rfold
≡
λ
f
.
λ
a
.
Y
(
λ
r
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
f
(
r
t
)
h
)
a
)
length
≡
fold
(
λ
a
.
λ
h
.
succ
a
)
zero
{\displaystyle {\begin{aligned}\operatorname {tail-or-nil} &\equiv \lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ t)\ \operatorname {nil} \\\operatorname {fold} &\equiv \lambda f.\ \operatorname {Y} \ (\lambda r.\lambda a.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ r\ (f\ a\ h)\ t)\ a)\\\operatorname {rfold} &\equiv \lambda f.\lambda a.\ \operatorname {Y} \ (\lambda r.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ f\ (r\ t)\ h)\ a)\\\operatorname {length} &\equiv \operatorname {fold} \ (\lambda a.\lambda h.\ \operatorname {succ} \ a)\ \operatorname {zero} \end{aligned}}}
map
≡
λ
f
.
λ
l
.
rfold
(
λ
a
.
λ
h
.
cons
(
f
h
)
a
)
nil
l
≡
λ
f
.
rfold
(
λ
a
.
λ
h
.
cons
(
f
h
)
a
)
nil
filter
≡
λ
f
.
λ
l
.
rfold
(
λ
a
.
λ
h
.
f
h
(
cons
h
a
)
a
)
nil
l
≡
λ
f
.
rfold
(
λ
a
.
λ
h
.
f
h
(
cons
h
a
)
a
)
nil
reverse
≡
λ
l
.
fold
(
λ
a
.
λ
h
.
cons
h
a
)
nil
l
≡
fold
(
λ
a
.
λ
h
.
cons
h
a
)
nil
concat
≡
λ
l
.
λ
g
.
rfold
(
λ
a
.
λ
h
.
cons
h
a
)
g
l
append
≡
λ
l
.
λ
v
.
concat
l
(
cons
v
nil
)
{\displaystyle {\begin{aligned}\operatorname {map} &\equiv \lambda f.\lambda l.\ \operatorname {rfold} \ (\lambda a.\lambda h.\ \operatorname {cons} \ (f\ h)\ a)\ \operatorname {nil} \ l\\&\equiv \lambda f.\ \operatorname {rfold} \ (\lambda a.\lambda h.\ \operatorname {cons} \ (f\ h)\ a)\ \operatorname {nil} \\\operatorname {filter} &\equiv \lambda f.\lambda l.\ \operatorname {rfold} \ (\lambda a.\lambda h.\ f\ h\ (\operatorname {cons} \ h\ a)\ a)\ \operatorname {nil} \ l\\&\equiv \lambda f.\ \operatorname {rfold} \ (\lambda a.\lambda h.\ f\ h\ (\operatorname {cons} \ h\ a)\ a)\ \operatorname {nil} \\\operatorname {reverse} &\equiv \lambda l.\ \operatorname {fold} \ (\lambda a.\lambda h.\ \operatorname {cons} \ h\ a)\ \operatorname {nil} \ l\\&\equiv \operatorname {fold} \ (\lambda a.\lambda h.\ \operatorname {cons} \ h\ a)\ \operatorname {nil} \\\operatorname {concat} &\equiv \lambda l.\lambda g.\ \operatorname {rfold} \ (\lambda a.\lambda h.\ \operatorname {cons} \ h\ a)\ g\ l\\\operatorname {append} &\equiv \lambda l.\lambda v.\ \operatorname {concat} \ l\ (\operatorname {cons} \ v\ \operatorname {nil} )\end{aligned}}}
skip
≡
λ
n
.
λ
l
.
n
t
a
i
l
-
o
r
-
n
i
l
l
≡
λ
n
.
n
t
a
i
l
-
o
r
-
n
i
l
≡
Y
(
λ
r
.
λ
n
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
IsZero
n
l
(
r
(
pred
n
)
t
)
)
nil
)
s
k
i
p
-
l
a
s
t
≡
λ
n
.
λ
l
.
IsZero
n
l
second
(
Y
(
λ
r
.
λ
l
r
.
l
r
(
λ
h
.
λ
t
.
λ
d
.
r
t
(
λ
n
a
.
λ
l
a
.
IsZero
n
a
(
pair
zero
(
cons
h
l
a
)
)
(
pair
(
pred
n
a
)
nil
)
)
)
(
pair
n
nil
)
)
l
)
s
k
i
p
-
w
h
i
l
e
≡
λ
f
.
Y
(
λ
r
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
f
h
(
r
t
)
l
)
nil
)
take
≡
Y
(
λ
r
.
λ
n
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
IsZero
n
nil
(
cons
h
(
r
(
pred
n
)
t
)
)
)
nil
)
t
a
k
e
-
l
a
s
t
≡
λ
n
.
λ
l
.
IsZero
n
l
second
(
Y
(
λ
r
.
λ
l
r
.
l
r
(
λ
h
.
λ
t
.
λ
d
.
r
t
(
λ
n
a
.
λ
l
a
.
IsZero
n
a
(
pair
zero
l
a
)
(
pair
(
pred
n
a
)
l
r
)
)
)
(
pair
n
nil
)
)
l
)
t
a
k
e
-
w
h
i
l
e
≡
λ
f
.
Y
(
λ
r
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
f
d
(
cons
h
(
r
t
)
)
nil
)
nil
)
{\displaystyle {\begin{aligned}\operatorname {skip} &\equiv \lambda n.\lambda l.\ n\ \operatorname {tail-or-nil} \ l\\&\equiv \lambda n.\ n\ \operatorname {tail-or-nil} \\&\equiv \operatorname {Y} \ (\lambda r.\lambda n.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ \operatorname {IsZero} \ n\ l\ (r\ (\operatorname {pred} \ n)\ t))\ \operatorname {nil} )\\\operatorname {skip-last} &\equiv \lambda n.\lambda l.\ \operatorname {IsZero} \ n\ l\ \operatorname {second} (\\&\ \ \ \ \operatorname {Y} \ (\lambda r.\lambda lr.\ lr\ (\lambda h.\lambda t.\lambda d.\\&\ \ \ \ \ \ \ \ r\ t\ (\lambda na.\lambda la.\ \operatorname {IsZero} \ na\\&\ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ \operatorname {zero} \ (\operatorname {cons} \ h\ la))\\&\ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ (\operatorname {pred} \ na)\ \operatorname {nil} )\\&\ \ \ \ \ \ \ \ ))\\&\ \ \ \ \ \ \ \ (\operatorname {pair} \ n\ \operatorname {nil} )\\&\ \ \ \ )\ l)\\\operatorname {skip-while} &\equiv \lambda f.\ \operatorname {Y} \ (\lambda r.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ f\ h\ (r\ t)\ l)\ \operatorname {nil} )\\\operatorname {take} &\equiv \operatorname {Y} \ (\lambda r.\lambda n.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ \operatorname {IsZero} \ n\ \operatorname {nil} \ (\operatorname {cons} \ h\ (r\ (\operatorname {pred} \ n)\ t)))\ \operatorname {nil} )\\\operatorname {take-last} &\equiv \lambda n.\lambda l.\ \operatorname {IsZero} \ n\ l\ \operatorname {second} (\\&\ \ \ \ \operatorname {Y} \ (\lambda r.\lambda lr.\ lr\ (\lambda h.\lambda t.\lambda d.\\&\ \ \ \ \ \ \ \ r\ t\ (\lambda na.\lambda la.\ \operatorname {IsZero} \ na\\&\ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ \operatorname {zero} \ la)\\&\ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ (\operatorname {pred} \ na)\ lr)\\&\ \ \ \ \ \ \ \ ))\\&\ \ \ \ \ \ \ \ (\operatorname {pair} \ n\ \operatorname {nil} )\\&\ \ \ \ )\ l)\\\operatorname {take-while} &\equiv \lambda f.\ \operatorname {Y} \ (\lambda r.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ f\ d\ (\operatorname {cons} \ h\ (r\ t))\ \operatorname {nil} )\ \operatorname {nil} )\end{aligned}}}
all
≡
Y
(
λ
r
.
λ
f
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
f
h
(
r
f
t
)
false
)
true
)
any
≡
Y
(
λ
r
.
λ
f
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
f
h
true
(
r
f
t
)
)
false
)
e
l
e
m
e
n
t
-
a
t
≡
λ
n
.
λ
l
.
head
(
skip
n
l
)
i
n
s
e
r
t
-
a
t
≡
λ
n
.
λ
v
.
λ
l
.
concat
(
take
n
l
)
(
cons
v
(
skip
n
l
)
)
r
e
m
o
v
e
-
a
t
≡
λ
n
.
λ
l
.
concat
(
take
n
l
)
(
skip
(
succ
n
)
l
)
r
e
p
l
a
c
e
-
a
t
≡
λ
n
.
λ
v
.
λ
l
.
concat
(
take
n
l
)
(
cons
v
(
skip
(
succ
n
)
l
)
)
i
n
d
e
x
-
o
f
≡
λ
f
.
Y
(
λ
r
.
λ
n
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
f
h
n
(
r
(
succ
n
)
t
)
)
zero
)
one
l
a
s
t
-
i
n
d
e
x
-
o
f
≡
λ
f
.
Y
(
λ
r
.
λ
n
.
λ
l
.
l
(
λ
h
.
λ
t
.
λ
d
.
(
λ
i
.
IsZero
i
(
f
h
n
zero
)
i
)
(
r
(
succ
n
)
t
)
)
zero
)
one
range
≡
λ
f
.
λ
z
.
Y
(
λ
r
.
λ
s
.
λ
n
.
IsZero
n
nil
(
cons
(
s
f
z
)
(
r
(
succ
s
)
(
pred
n
)
)
)
)
zero
repeat
≡
λ
v
.
Y
(
λ
r
.
λ
n
.
IsZero
n
nil
(
cons
v
(
r
(
pred
n
)
)
)
)
zip
≡
Y
(
λ
r
.
λ
l
1.
λ
l
2.
l
1
(
λ
h
1.
λ
t
1.
λ
d
1.
l
2
(
λ
h
2.
λ
t
2.
λ
d
2.
cons
(
pair
h
1
h
2
)
(
r
t
1
t
2
)
)
nil
)
nil
)
{\displaystyle {\begin{aligned}\operatorname {all} &\equiv \operatorname {Y} \ (\lambda r.\lambda f.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ f\ h\ (r\ f\ t)\ \operatorname {false} )\ \operatorname {true} )\\\operatorname {any} &\equiv \operatorname {Y} \ (\lambda r.\lambda f.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ f\ h\ \operatorname {true} \ (r\ f\ t))\ \operatorname {false} )\\\operatorname {element-at} &\equiv \lambda n.\lambda l.\ \operatorname {head} \ (\operatorname {skip} \ n\ l)\\\operatorname {insert-at} &\equiv \lambda n.\lambda v.\lambda l.\ \operatorname {concat} \ (\operatorname {take} \ n\ l)\ (\operatorname {cons} \ v\ (\operatorname {skip} \ n\ l))\\\operatorname {remove-at} &\equiv \lambda n.\lambda l.\ \operatorname {concat} \ (\operatorname {take} \ n\ l)\ (\operatorname {skip} \ (\operatorname {succ} \ n)\ l)\\\operatorname {replace-at} &\equiv \lambda n.\lambda v.\lambda l.\ \operatorname {concat} \ (\operatorname {take} \ n\ l)\ (\operatorname {cons} \ v\ (\operatorname {skip} \ (\operatorname {succ} \ n)\ l))\\\operatorname {index-of} &\equiv \lambda f.\ \operatorname {Y} \ (\lambda r.\lambda n.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ f\ h\ n\ (r\ (\operatorname {succ} \ n)\ t))\ \operatorname {zero} )\ \operatorname {one} \\\operatorname {last-index-of} &\equiv \lambda f.\ \operatorname {Y} \ (\lambda r.\lambda n.\lambda l.\ l\ (\lambda h.\lambda t.\lambda d.\ (\lambda i.\ \operatorname {IsZero} \ i\ (f\ h\ n\ \operatorname {zero} )\ i)\ (r\ (\operatorname {succ} \ n)\ t))\ \operatorname {zero} )\ \operatorname {one} \\\operatorname {range} &\equiv \lambda f.\lambda z.\ \operatorname {Y} \ (\lambda r.\lambda s.\lambda n.\ \operatorname {IsZero} \ n\ \operatorname {nil} \ (\operatorname {cons} \ (s\ f\ z)\ (r\ (\operatorname {succ} \ s)\ (\operatorname {pred} \ n))))\ \operatorname {zero} \\\operatorname {repeat} &\equiv \lambda v.\ \operatorname {Y} \ (\lambda r.\lambda n.\ \operatorname {IsZero} \ n\ \operatorname {nil} \ (\operatorname {cons} \ v\ (r\ (\operatorname {pred} \ n))))\\\operatorname {zip} &\equiv Y\ (\lambda r.\lambda l1.\lambda l2.\ l1\ (\lambda h1.\lambda t1.\lambda d1.\ l2\ (\lambda h2.\lambda t2.\lambda d2.\ \operatorname {cons} \ (\operatorname {pair} \ h1\ h2)\ (r\ t1\ t2))\ \operatorname {nil} )\ \operatorname {nil} )\\\end{aligned}}}
作为邱奇序对编码的替代方案,列表可通过其右折叠函数 进行编码。例如,包含三个元素x、y、z的列表可编码为高阶函数,当该函数应用组合子c和初始值n时,返回c x (c y (c z n))。这等价于部分应用函数组合链的调用:(c x ∘ c y ∘ c z) n。
nil
≡
λ
c
.
λ
n
.
n
singleton
≡
λ
h
.
λ
c
.
λ
n
.
c
h
n
cons
≡
λ
h
.
λ
t
.
λ
c
.
λ
n
.
c
h
(
t
c
n
)
append
≡
λ
l
.
λ
t
.
λ
c
.
λ
n
.
l
c
(
t
c
n
)
isnil
≡
λ
l
.
l
(
λ
h
.
λ
r
.
false
)
true
nonempty
≡
λ
l
.
l
(
λ
h
.
λ
r
.
true
)
false
head
≡
λ
l
.
l
(
λ
h
.
λ
r
.
h
)
false
map
≡
λ
f
.
λ
l
.
λ
c
.
λ
n
.
l
(
λ
h
.
λ
r
.
c
(
f
h
)
r
)
n
tail
≡
λ
l
.
λ
c
.
λ
n
.
l
(
λ
h
.
λ
r
.
λ
g
.
g
h
(
r
c
)
)
(
λ
c
.
n
)
(
λ
h
.
λ
t
.
t
)
{\displaystyle {\begin{aligned}\operatorname {nil} &\equiv \lambda c.\lambda n.n\\\operatorname {singleton} &\equiv \lambda h.\lambda c.\lambda n.c\ h\ n\\\operatorname {cons} &\equiv \lambda h.\lambda t.\lambda c.\lambda n.c\ h\ (t\ c\ n)\\\operatorname {append} &\equiv \lambda l.\lambda t.\lambda c.\lambda n.l\ c\ (t\ c\ n)\\\operatorname {isnil} &\equiv \lambda l.l\ (\lambda h.\lambda r.\operatorname {false} )\ \operatorname {true} \\\operatorname {nonempty} &\equiv \lambda l.l\ (\lambda h.\lambda r.\operatorname {true} )\ \operatorname {false} \\\operatorname {head} &\equiv \lambda l.l\ (\lambda h.\lambda r.h)\ \operatorname {false} \\\operatorname {map} &\equiv \lambda f.\lambda l.\lambda c.\lambda n.l\ (\lambda h.\lambda r.c\ (f\ h)\ r)\ n\\\operatorname {tail} &\equiv \lambda l.\lambda c.\lambda n.l\ (\lambda h.\lambda r.\lambda g.g\ h\ (r\ c))\ (\lambda c.n)\ (\lambda h.\lambda t.t)\end{aligned}}}
此列表表示可在系统F 类型系统中定义。
与邱奇数的对应关系并非巧合,邱奇数本质上是单元值列表(如[() () ()])的一进制编码,列表长度即表示自然数值。对此类列表进行右折叠时,组合函数忽略元素值,其本质与邱奇数中的函数组合链(即(c () ∘ c () ∘ c ()) n = (f ∘ f ∘ f) n)具有等价性。
另一种实现方式是采用Scott编码 ,这种方式能生成更简洁的代码[ 10] (参见摩根森-斯科特编码 )。
该编码的核心思想是利用模式匹配的特性。以Scala 语法为例,假设list
表示包含空列表Nil
和构造器Cons(h, t)
的列表类型,可通过模式匹配进行计算:
list match {
case Nil => nilCode
case Cons ( h , t ) => consCode ( h , t )
}
列表的行为由其模式匹配决定,因此可将列表定义为接收nilCode
和consCode
参数的函数:
list
nilCode
consCode
{\displaystyle \operatorname {list} \ \operatorname {nilCode} \ \operatorname {consCode} }
设n
对应空列表处理参数,c
对应非空列表处理参数,则:
空列表定义为:
nil
≡
λ
n
.
λ
c
.
n
{\displaystyle \operatorname {nil} \equiv \lambda n.\lambda c.\ n}
非空列表(含首元素h和尾部t)定义为:
cons
h
t
≡
λ
n
.
λ
c
.
c
h
t
{\displaystyle \operatorname {cons} \ h\ t\ \ \equiv \ \ \lambda n.\lambda c.\ c\ h\ t}
更一般地,包含
m
{\displaystyle m}
种构造器的代数数据类型 将被编码为具有
m
{\displaystyle m}
个参数的函数。当第
i
{\displaystyle i}
个构造器包含
n
i
{\displaystyle n_{i}}
个参数时,对应编码参数也接收
n
i
{\displaystyle n_{i}}
个参数。
该编码可在无类型λ演算中使用,但带类型版本需支持递归和类型多态的系统。以元素类型E、计算结果类型C的列表为例,其递归类型定义为("=>"表示函数类型):
type List =
C => // 空列表分支
( E => List => C ) => // 非空列表分支
C // 模式匹配结果
支持任意计算类型的列表需量化类型C
,而泛型列表还需将元素类型E
作为类型参数。
^ 1.0 1.1 1.2 Trancón y Widemann, Baltasar; Parnas, David Lorge. Olaf Chitil; Zoltán Horváth; Viktória Zsók , 编. Implementation and Application of Functional Languages . 19th International Workshop, IFL 2007, Freiburg, Germany, September 27–29, 2007 Revised Selected Papers. Lecture Notes in Computer Science 5083 : 228–229. 2008. ISBN 978-3-540-85372-5 . doi:10.1007/978-3-540-85373-2_13 .
^ Jansen, Jan Martin; Koopman, Pieter W. M.; Plasmeijer, Marinus J. Efficient interpretation by transforming data types and patterns to functions. Nilsson, Henrik (编). Trends in functional programming. Volume 7. Bristol: Intellect. 2006: 73–90. CiteSeerX 10.1.1.73.9841 . ISBN 978-1-84150-188-8 .
^ Predecessor and lists are not representable in simply typed lambda calculus . Lambda Calculus and Lambda Calculators. okmij.org.
^
Allison, Lloyd. Lambda Calculus Integers .
^
Bauer, Andrej. Andrej对问题的回答:"使用lambda演算表示负数和复数" .
^
精确实数计算 . Haskell. (原始内容 存档于2015-03-26).
^
Bauer, Andrej. 实数计算软件 . GitHub . 2022-09-26.
^ Pierce, Benjamin C. 类型与程序语言 . 麻省理工出版社 . 2002: 500. ISBN 978-0-262-16209-8 .
^ 特朗普, 约翰. 14. 二元λ演算与组合逻辑 . 卡鲁德, 克里斯蒂安·S (编). 从莱布尼茨到柴廷的随机性与复杂性. 世界科学出版公司. 2007: 237–262. ISBN 978-981-4474-39-9 . PDF版本:特朗普, 约翰. 二元λ演算与组合逻辑 (PDF) . 2014-05-14 [2017-11-24 ] .
^ Jansen, Jan Martin. λ演算编程:从Church到Scott的往返. Achten, Peter; Koopman, Pieter W. M. (编). 函数式代码之美——献给里努斯·普拉斯梅尔的61岁诞辰. 计算机科学讲义 8106 . 施普林格. 2013: 168–180. ISBN 978-3-642-40354-5 . doi:10.1007/978-3-642-40355-2_12 .