S-演算(S-Calculus)中的组合子完备性证明
S-演算是组合子逻辑(Combinatory Logic)中的一个核心系统,由 Moses Schönfinkel 提出,后由 Haskell Curry 发展。它提供了一种无需变量绑定(如λ抽象)的函数表示和计算模型。今天,我将为你循序渐进地讲解如何证明S-演算中一组基本组合子(如S和K)是“完备的”,即足以表达所有的可计算函数(在λ演算的意义上)。
第一步:S-演算的基础与基本组合子
首先,我们需要明确S-演算的“语言”。它是一个应用性系统:
- 项(Terms) 由原子常元和函数应用构成。我们从一个极小的常元集合开始,最经典的就是 S 和 K。
- 应用(Application):如果
M和N是项,那么(M N)也是一个项,表示将M应用于N。应用是左结合的,即M N P表示((M N) P)。
核心是两个组合子 S 和 K 所满足的归约(或等价)公理:
- K组合子:
K x y → x(K是一个“常数函数生成器”,它接受两个参数,丢弃第二个,返回第一个)。 - S组合子:
S x y z → (x z)(y z)(S是一个“共享”或“分发”组合子,它将第一个参数x应用于z,第二个参数y应用于z,然后将前两个结果再应用)。
这里的 x, y, z 是元变量,代表任意项。一个仅由 S, K 和应用构成的项,称为一个组合子。S 和 K 本身是最基本的组合子。
第二步:组合子完备性的目标定义
当我们说“S和K是完备的”,其精确含义是:对于任意一个无类型的λ项 M(其中可能包含λ抽象和自由变量),我们都能找到一个仅由 S, K 和(可能需要的)特定变量(对应M中的自由变量)构成的组合子项 M*,使得 M* 在可转换性(convertibility)上与 M 等价。
更形式化地说,存在一个从λ项到组合子项的翻译函数 [[]],满足:如果 M =β N 在λ演算中成立,那么对应的组合子项 [[M]] 和 [[N]] 在S-演算中也是可互推的(通过S和K的公理)。
第三步:从λ项到组合子项的翻译算法
完备性证明是构造性的。我们定义一个翻译算法 CL,将λ项(可能含自由变量)映射为组合子项。
翻译规则如下,其中 x 是变量,M, N 是λ项:
CL(x) = x(变量自身是原子组合子项)CL(M N) = (CL(M) CL(N))(应用直接对应)- 关键的λ抽象翻译:
CL(λx. M)需要被定义为一个不包含λ符号、只由S,K和自由变量(可能包括x)构成的组合子。我们采用Curry的抽象算法:CL(λx. x) = I,但注意I可以用S和K定义:I ≡ S K K(因为S K K x → (K x)(K x) → x)。- 更一般地,我们递归定义:
a)CL(λx. M) = K CL(M),如果x不是M中的自由变量。
(理由:(K P) x → P,这正是常数函数的行为,与λx. M(x不在M中出现)的行为一致。)
b)CL(λx. x) = I ≡ S K K。
c)CL(λx. M N) = S CL(λx. M) CL(λx. N),如果上述特殊情况不适用。
(理由:检查(S P Q) x的归约:→ (P x)(Q x)。这正是我们希望(λx. (M N))表现的行为,因为它等于(λx. M) (λx. N)然后应用于x。但注意,我们的翻译是直接的,不先做此转换。) - 实际上,标准算法是以下三条:
[x] = x[M N] = ([M] [N])[λx. M]根据M的结构:- 如果
M = x,则[λx. x] = I(I可用S K K定义)。 - 否则,如果
M不包含自由变量x,则[λx. M] = K [M]。 - 否则,如果
M是形式P Q,则[λx. P Q] = S [λx. P] [λx. Q]。
- 如果
第四步:证明翻译的正确性(核心论证)
翻译算法构造完成后,我们必须证明它是正确的。正确性定理是:
对于任何λ项 M 和所有项 N,有 ([λx. M] [N]) 在S-演算中可归约到 [M[x := N]]。
这里 M[x := N] 表示在M中将自由变量x替换为N。这个定理保证了组合子翻译模拟了λ演算中最核心的β-归约。
证明:通过对 M 的结构进行归纳。
- 基础情况:
- 若
M = x,则[λx. x] = I,那么(I [N]) ≡ (S K K [N]) → (K [N])(K [N]) → [N],而[x[x := N]] = [N]。成立。 - 若
M = y(y是与x不同的变量),则[λx. y] = K y,那么(K y [N]) → y,而[y[x := N]] = y。成立。
- 若
- 归纳步骤:
- 若
M = P Q,则[λx. P Q] = S [λx. P] [λx. Q]。
计算左边:(S [λx. P] [λx. Q] [N]) → (([λx. P] [N]) ([λx. Q] [N]))。
根据归纳假设,([λx. P] [N])可归约到[P[x := N]],且([λx. Q] [N])可归约到[Q[x := N]]。
因此,整个项可归约到([P[x := N]] [Q[x := N]])。
而右边[(P Q)[x := N]] = [P[x := N] Q[x := N]] = ([P[x := N]] [Q[x := N]])。
两者一致,成立。
- 若
这个归纳证明表明,我们的翻译算法成功地将λ-演算的β-归约步骤,编码成了S-演算中仅使用 S 和 K 公理的归约序列。因此,任何λ-演算中的计算(归约)都可以在S-演算中模拟。
第五步:完备性的最终陈述与意义
结合翻译算法和正确性定理,我们得到:
S-K组合子完备性定理:对于任意一个(无类型)λ项 M,都存在一个由变量、S 和 K 通过应用构成的组合子项 M*(即 CL(M)),使得对于任意λ项 N1, ..., Nn,将 M* 应用于对应 N 的组合子翻译 N1*, ..., Nn* 时,其在S-演算中的可计算行为与 M 应用于 N1, ..., Nn 在λ演算中的行为相对应(即结果可互推)。
这意味着 {S, K} 构成了一个组合子完备集。它们是图灵完备的,因为λ演算是图灵完备的。实际上,我们甚至可以用更小的集合,比如只用一个组合子(如X组合子),但S和K是最经典和常用的最小完备集。
总结:你已经学习了从S和K组合子的定义开始,到明确完备性目标,再到构造具体的λ项翻译算法,最后通过结构归纳法证明该算法确实能模拟β-归约,从而严谨地证明了S和K组合子在表达所有可计算函数(在λ演算的意义上)的完备性。这是组合子逻辑和计算理论中的一个基础而优美的结果。