接着昨天的写:
继续谈论SKI前,得澄清一件重要的事。我说用S K K可以创建等价于
lambda x .
x的东西,并不等于我们可以把S K K归约到lambda x. x。在我们讨论的lambda算子里,我们说”x = y”当且仅当x和y要么完全一样,要么可以通过alpha变换变得一样(所以
lambda x y . x + y
等于
lambda a b . a + b,
但却不等于
lambda x y . y + x
)。这叫做intentional equivalence(内涵等价?)。不过另外一种等价关系极其有用。我们称之为extensional equivalence(外延等价?)或extentional equality。在extensional equality里,表达式X和表达式Y相等当且仅当X和Y如前所述等价,或者对任意值a, X a = Y a。从现在开始,我们用“=”或等价指代extensional equality。呵呵,其实编程的时候,equals()也是一个很难实现正确的函数。不然C++不会在STL里加入等价的概念;Java里
((Long)0L).equals(0) 居然返回false;Ruby里有equal?, eql?,和==;Common Lisp里有eq, eql, equal, 和equalp;而Joshua Bloch在Effective Java里用了整整一节讨论equal。更不用说我们学习逻辑的时候,要仔细定义什么叫做等价。
其实,我们可以把
任何lambda表达式转换为等价的组合子项。我们可以如下定义转换方程C, 把lambda表达式转换为SKI组合子表达式:
(1)
C{x} = x
(2)
C{E1 E2} = C{E1} C{E2}