目前的排版不论从效果还是从实现来看都相当丑陋, 但也只能将就一下了. 或许只有等到博客进行大型实质性重构时, 我才会考虑这些问题.
和其他小人书一样, 本书也包含大量文字游戏, 这有点难以传达? 若有必要, 我会添加一些译注.
欢迎回来! | 1 | 很高兴回到这里! |
让我们为一门叫做Pie的新语言擦拭并更新一些我们的旧玩具. 以下东西是一个 Atom , 这显然吗?
| 2 | 一点也不, Atom 是什么意思? |
要成为一个Atom , 就是要成为一个原子(atom).注记. 在Lisp中, 原子可以是符号, 数字, 以及其他许多东西. 但在这里, 原子只是符号. | 3 | 那么, 'atom 是一个Atom 是因为'atom 是一个原子. |
以下东西是一个Atom , 这显然吗?
译注. ratatouille指的是普罗旺斯杂烩. | 4 | 是的, 因为'ratatouille 也是一个原子.但是, 精确地说, 什么是一个原子呢? |
原子是由一个单引号 (tick mark) 后跟着一个或更多的字母或者连字符而来的. 注记. 在Pie中, 只有原子使用单引号. | 5 | 因此, 那么 显然是一个Atom 吗? |
当然了, 因为原子可以包含连字符. 那么 和 和 如何, 它们是原子吗? | 6 | 是一个原子, 因为连字符可以出现在一个原子里的任何位置; 不是一个原子, 因为它缺少了单引号; 不是一个原子, 因为它的后面既没有跟着一个字母, 也没有跟着一个连字符. |
'Atom 是一个Atom 吗? | 7 | 是的, 即便'Atom 也是一个Atom , 因为它是一个单引号后面跟着一个或更多的字母或者连字符. |
'at0m 是一个Atom 吗? | 8 | 不是, 因为根据第1章第5框, 原子只能包含字母或者连字符, 而字符0 并不是一个字母, 它是数位零. |
'cœurs-d-artichauts 是一个Atom 吗?译注. cœurs d'artichauts是一种食物, 即洋蓟心. | 9 | 是的, 因为œ 是一个字母. |
'ἄτομον 是一个Atom 吗?译注. ἄτομον是一个古希腊语词, 意思是不可分割的东西, 即原子. | 10 | That's Greek to me! 译注. 这算是一语双关. 但是希腊字母也是字母, 所以它必然是一个Atom . |
|
诸如
注记. 感谢Per Martin-Löf (1942–). | 11 | 判断的要义在于什么? |
一个判断是一个人对于一个表达所采取的一个态度. 当我们得以获知什么东西时, 我们就在作出一个判断. 关于 Atom 和'courgette , 可以判断什么? | 12 | 'courgette 是一个Atom .译注. courgette指的是西葫芦. |
一个判断形式(form of judgment)是一个带有空白的观察, 例如 ____是一个____. | 13 | 还有其他的判断形式吗? |
判断 (judgment)的另一种形式是 判断 (judgement). | 14 | 十分有趣. |
和 是相同的 吗? | 15 | 是的. 它们之所以是相同的 |
和 是相同的 吗? | 16 | 不是. 单引号之后, 它们有着不同的字母. |
|
第二种判断形式为 ____和____是相同的____. | 17 | 因而
译注. citron指的是香橼. |
这的确是一个判断, 而且我们有理由去相信.
| 18 | 诚然它是判断, 但是我们没有理由去相信它. 毕竟, 我们不该比较苹果 (apple) 和橙子. 译注. pomme是法语的苹果. |
是一个 这显然吗?注记. 当准备好的时候, 读[page 62]看 定型 (typing)指令. | 19 | 不, 完全不是. 成为一个 是什么意思呢?译注. baguette指的是法棍面包. |
成为一个 就是要成为一个序对, 其car 是一个Atom , 例如'ratatouille , 其cdr 也是一个Atom , 例如'baguette . | 20 | cons , car , cdr 看上去很眼熟. 不谈以前, 这里它们是什么意思呢? 它们和序对 (pair) 又有什么关系呢? |
一个序对以cons 起手, 而以另外两个部分作结, 我们称其为它的car 和cdr .注记. 在Lisp中, cons 可以使得列表更长. 但在这里, cons 只是用来构造序对. | 21 | 好吧, 这意味着之所以 是一个 是因为(cons 'ratatouille 'baguette) 是一个序对, 其car 是一个Atom , 其cdr 也是一个Atom .那么, |
甚至cons 和Pair 在单独情况下都不是表达式, 它们都需要两个参数. 和 是相同的 吗?注记. 在Lisp中, cons 是一个过程, 有着其自身的含义, 但是诸如cond 或lambda 这样的形式如果单独出现则是没有意义的. | 22 | 两个表达式为相同的 是什么意思呢? |
这意味着它们的car 都是相同的Atom , 它们的cdr 也都是相同的Atom . | 23 | 那么的确 和 是相同的
|
和 是相同的 吗? | 24 | 的car 是'ratatouille 而 的car 是'baguette .因此, 我们没有理由去相信它们是相同的 |
可以怎样描述呢? | 25 | 它是一个
|
描述其他表达式的表达式, 例如Atom , 被称为类型(type).
注记. 当一个名字 (例如 Pair 或者Atom ) 牵涉类型时, 首字母会大写. | 26 | 是的, 因为它描述了car 和cdr 均为Atom 的序对. |
第三种判断形式为 ____是一个类型. | 27 | 这意味着
|
|
| 28 | 它的确是一个判断, 但是我们没有任何理由去相信它, 因为'courgette 并不描述其他表达式. |
Atom 和Atom 是相同的类型吗? | 29 | 想必如此, 它们看上去就应该是相同的类型. |
第四种判断形式, 也是最后一种, 如下 ____和____是相同的类型. | 30 | 那么, 所以说
|
|
以下是一个判断吗?
| 31 | 它是一个判断, 但是没有理由去相信它. |
和 是相同的类型吗? | 32 | 看起来相当可信啊. |
判断是获知的行为, 而相信是获知的一部分. | 33 | 判断难道不是句子吗? |
句子从理解它们的人那里获得意义. 句子捕获了我们所拥有的思想, 而思想比我们用来表达思想的词语要重要得多. | 34 | 啊, 所以说得以获知 和 是相同的类型这一行为是一个判断. |
的确如此.
译注. pêche指的是桃子. | 35 | 好问题.
|
不, 当然不是, 因为
某些形式的判断只有在早前的判断的基础之上才具备意义. 注记. 这种早前的判断有时被称为前置假定(presupposition). | 36 | 有哪些呢? |
为了提问一个表达式是否由一个类型描述, 我们必须已经判断过给定的类型的确是一个类型. 为了提问两个表达式是否在一个类型下是相同的, 我们必须首先判断出这两个表达式都由该类型所描述. 注记. 当然, 为了描述那两个表达式, 那个给定的类型也得是类型. 在提问两个表达式是否是相同的类型之前, 有什么判断是必要的吗? | 37 | 为了提问两个表达式是否是相同的类型, 我们必须先要判断这两个表达式的确都是类型. |
和 是相同的 吗? | 38 | 看起来十分熟悉啊. 想必是这样, 因为car 可以找到一个序对的car , 所以它们是相同的. |
和 是相同的 吗? | 39 | 诚然如此, 因为这个序对的cdr 是'baguette . |
于是 是一个...译注. aubergine指的是茄子. | 40 | ... (Pair Atom Atom) , 因为 是一个序对, 其car 是Atom 'aubergine , 其cdr 是Atom 'courgette . |
和 是相同的 吗? | 41 | 是的, 的确如此. |
正如从第1章第39框到第1章第41框所展现的那样, 写法不同的表达式或许可能是相同的. 其中一种写法要比其他写法都更加直接. | 42 | 'baguette 的确看上去比 更加直接. |
一个表达式的规范形式(normal form)是书写该表达式最直接的方式. 任何两个相同的表达式都有着等同的规范形式, 并且任何两个有着等同规范形式的表达式都是相同的. | 43 | 'olive-oil 是 的规范形式吗? |
这个问题是不完整的. 相同总是相对于某个类型而言的, 因此规范形式也由类型决定. | 44 | 'olive-oil 是Atom 的规范形式吗? |
是的, 的确如此. 是一个规范的 吗?注记. 规范的(normal)是具有规范形式(in normal form)的简略说法. | 45 | 是的, (cons 'ratatouille 'baguette) 的确是规范的.每个表达式都具有一个规范形式吗? |
如果不刻画一个表达式的类型, 那么提问其是否具有规范形式也是没有意义的. 然而, 给定一个类型, 每个由该类型描述的表达式的确都有一个由该类型确定的规范形式. | 46 | 如果了两个表达式根据它们的类型是相同的, 那么它们就具有等同的规范形式. 因此, 这必然意味着我们可以通过比较两个表达式的规范形式来判断 (check) 它们是否相同. |
|
的规范形式是什么? | 47 | 类型是什么呢? 如果类型是 那么规范形式为
|
干得好! 之前我们对于什么是一个 的描述其实是不完整的, 而完整的描述应该是... | 48 | ...成为一个序对, 其car 是一个Atom , 其cdr 也是一个Atom , 或者是与这样一个序对相同的一个表达式. |
|
和 是相同的 吗? | 49 | 是的, 之所以这两个表达式是相同的(Pair Atom Atom) , 是因为 的规范形式是
|
为什么 和 是相同的(Pair Atom Atom) 呢? | 50 | 这看起来非常显然? |
是的, 但是不是每个看上去显然的东西实际上都是显然的. 第1章第23框描述了何谓一个表达式和另一个表达式是相同的
注记. 在Lisp中, 相同的原子使用两次 cons 产生的序对并不eq . 但在这里, 它们无法以任何方式进行区分. | 51 | 和 的顶层都是cons , 'aubergine 和'aubergine 是相同的Atom , 'courgette 和'courgette 是相同的Atom .这两个表达式具有相同的
|
|
很好. 的规范形式是什么呢? | 52 | 我猜是(Pair 'olive 'oil) , 是这样吗? |
实际上, 表达式 既不由某个类型刻画, 本身也不是一个类型, 因此提问其规范形式是毫无意义的.注记. 不被类型刻画且自身不是类型的表达式也被称为是病态类型(ill-typed)的. | 53 | 为什么呢? |
因为Pair 在其参数为实际原子时并非类型.只有在其参数均为类型 (例如 | 54 | 这是不是意味着Pair 不能和car 与cdr 一起使用呢? |
不, 完全不是. 的规范形式是什么? | 55 | 它的类型是什么呢? 规范形式总是相对于某个类型而言的. |
类型本身也有规范形式. 如果两个类型有着等同的规范形式, 那么它们就是相同的类型. 如果两个类型是相同的类型, 那么它们就具有等同的规范形式. | 56 | 类型 的规范形式必然是(Pair Atom Atom) , 因为 的规范形式为Atom , 并且 的规范形式也是Atom . |
|
就是这样. 现在我们知道 也是一个 因为... | 57 | ... 的规范形式为 而 是一个
|
另一种说法是 和 是相同的类型. | 58 | 如果一个表达式是一个 那么它也是一个 因为这两个类型是相同的类型. |
类似地, 如果一个表达式是一个 那么它也是一个 因为这两个类型是相同的类型. | 59 | 对于 也是类似的, 因为它和前面两个也是相同的类型. |
'6 是一个Atom 吗? | 60 | 不是, 我们没有理由去相信
6 既非字母也非连字符, 不是吗? |
的确如此. 是一个 吗? | 61 | 不, 因为(cons '17 'pepper) 的car 是'17 , 它并非一个Atom .尽管如此, 拥有数字应该也是很自然的事情才对. |
数字当然是很方便的. 除了Atom 和Pair , 我们还可以判断某个东西是否是一个Nat . | 62 | 让我们来试一下. |
1 是一个Nat 吗?注记. Nat 是自然数(natural number)的缩写. | 63 | 的确, 1 是一个Nat . |
1729 是一个Nat 吗? | 64 | 是的, 1729 是一个Nat . 它不仅是一个Nat , 还很著名!注记. 谢谢Srinivasa Ramanujan (1887–1920) 和Godfrey Harold Hardy (1877–1947). |
-1 是一个Nat 吗? | 65 | 嗯, 你确定? |
不, 当然不是. -23 呢? | 66 | 不是很清楚啊. |
正数是Nat . | 67 | 啊, 那么-23 不是一个Nat ? |
我们更喜欢采取积极 (positive) 的态度. 译注. 这大概是一语双关吧. 最小的Nat 是什么? | 68 | 0 不是一个自然数吗? |
啊, 所以我们也不能总是很积极. 我们该如何获得剩下来的Nat 呢?注记. 然而, 数字 1 总是正的. | 69 | 我们可以使用我们的老朋友add1 . 如果是一个Nat , 那么(add1 ) 也是一个Nat , 并且这个新的Nat 永远是正数, 即便是0 .有多少个 |
很多很多! | 70 | 存在最大的Nat 吗? |
并不, 因为我们总是可以... | 71 | ...使用add1 来加上一? |
的确是这样!
注记. 谢谢Giuseppe Peano (1838-1932). | 72 | 显然不是. |
(+ 0 26) 和26 是相同的吗?注记. 即便我们还没有解释 + , 暂时请用你自己对于加法的理解. | 73 | 这个问题没有意义. 但是, 我们可以问它们是否是相同的Nat 吗? |
当然可以.
| 74 | 是的, 这是因为(+ 0 26) 的规范形式为26 , 而26 和26 当然是相同的. |
zero 的意思是什么呢? | 75 | zero 和0 是相同的吗? |
在Pie里, zero 和0 不过是书写同一个Nat 的不同方式而已.
| 76 | 嗯, 如果zero 和0 是相同的Nat 的话, 那么这似乎很合理. |
实际上, one 没有意义. 但是, (add1 zero) 是书写数字1 的另一种方式.通过定义使得
| 77 | 为什么这个定义周围用虚线框住了呢? |
虚线框意味着这个定义有点问题, 以至于它不能在之后使用. | 78 | 这个定义有什么问题呢? 看上去很正常啊. |
当定义一个名字时, 有必要先claim 这个名字具有一个类型, 而one 是一个Nat .
| 79 | 因此, two 可以被定义成
|
|
如果1 是书写(add1 zero) 的另一种方式, 那么书写4 的另一种方式是什么呢? | 80 | 难道不应该是 吗? 我们不能定义four 来指代这个表达式吗? |
当然可以了. 那么, 再问一下书写8 有另外的方式吗? | 81 | 那必然是
|
8 是规范的吗? | 82 | 似乎如此, 但是为什么8 是规范的呢? |
之所以8 是规范的, 是因为其顶add1 是一个构造子(constructor), 并且塞在顶add1 下面的参数, 即7 , 也是规范的.注记. 第1章第81框中的顶 add1 只此一次用下划线标注出来以示强调. | 83 | 为什么7 , 亦写作 是规范的呢? |
7 是规范的完全是同理可得. | 84 | 这意味着zero 必然是规范的, 不然的话(add1 zero) 就不是规范的了. |
zero 的顶是什么呢? | 85 | 必须是zero . |
之所以zero 是规范的, 是因为顶zero 是一个构造子, 并且其没有参数. 是规范的吗? | 86 | 不是, 因为+ 不是构造子. |
一个以构造子为顶的表达式被称为一个值(value). 即便 不是规范的, 它的确是一个值.注记. 值也被称为典则(canonical)表达式. | 87 | 这个表达式不是规范的, 是因为 并非书写3 的最直接方式. |
|
现在我们给出另一个并非规范的表达式. 这是书写3 的最直接方式吗? | 88 | 肯定不是. 准确来说, 构造子究竟是什么呢? |
某些表达式是类型, 例如Nat 和(Pair Nat Atom) .对于新类型的解释的一部分是要说明其构造子为何. 构造子表达式是构造具有该类型的表达式的直接方式. | 89 | 构造子的例子有哪些呢? |
Nat 的构造子是zero 和add1 , 而Pair 的构造子是cons . | 90 | 值和规范形式之间有何关系? |
在一个值里, 顶层的构造子的参数不必是规范的. 但如果这些参数的确是规范的, 那么整个构造子表达式就具有规范形式. 所有的值都是规范的吗? | 91 | 显然不是. 和 都是值, 但是它们都不是规范的. |
|
以下空白方框里填什么会使得整个表达式不是一个Nat 值呢?
| 92 | 'aubergine 怎么样? |
诚然如此. 并非一个Nat 值, 因为'aubergine 是一个Atom 而不是一个Nat .当填充这样的方框时, 我们的期望是作为结果的表达式由某个类型刻画. | 93 | 然而, 若置于该方框里的是任何一个Nat 表达式, 那么整个表达式就是一个值. 这一整个表达式以add1 为顶, 而add1 是一个Nat 构造子. |
找出一个与某起始表达式相同的值被称为求值(evaluation). | 94 | 类型呢? 毕竟, 相同需要类型. |
有时当我们提及相同时, 我们并不显式提及类型. 然而, 总是存在一个意图的类型, 并且这个类型可以通过仔细阅读找到. | 95 | 难道求值指的不是找到一个表达式的意义(meaning)吗? 这不只是某个更简单的表达式. |
我们这里的含义不一样. 表达式并不指向某种外部的意义概念——在Pie中, 除了表达式和我们对于表达式的判断之外, 别无其他. 注记. 在Lisp中, 值和表达式是不同的, 而求值的结果是一个值. | 96 | 这是一种看待求值的新方式. 为什么规范形式和值之间要做区分呢? |
|
规范表达式没有可供求值的剩余机会了. 通常而言, 规范的表达式更容易理解. 然而, 往往找到一个值就足够了, 因为顶层的构造子可以用来判断接下来必然发生的事情. | 97 | 如果找到一个值经常就足够了的话, 难道说这意味着我们可以自由地去寻找值, 并且然后可以想停就停呢? |
是这样的, 只要关于构造子的参数的信息从没有用到即可. 和four 是相同的Nat 吗? | 98 | 这里给出一个可能的回答. 它们不是相同的 是一个值, 而且它当然长得不像变量four . 找到four 的值也无济于事, 因为four 的值看起来非常不同. |
算是好的尝试. 但是, 实际上它们是相同的 | 99 | 怎么能这样呢? |
两个不是值的Nat 表达式相同, 如果它们的值相同. 恰存在两种Nat 值可以相同的方式: 每种构造子一个.如果两个都是 | 100 | 那么两个值都以add1 为顶的情况呢? |
|
如果每个add1 的参数是相同的Nat , 那么两个add1 表达式是相同的Nat 值.为什么 和 是相同的
| 101 | 这两个表达式都是值. 这两个值都以add1 为顶, 因此它们的参数应该是相同的Nat .这两个参数都是 |
|
为什么 和 是相同的
| 102 | 这两个Nat 都以add1 为顶, 于是它们都是值.它们之所以相同, 是因为 和 是相同的
|
为什么(+ 0 1) 和(+ 1 0) 是相同的Nat ? | 103 | 这些Nat 并非值, 因而为了判断它们是否相同, 第一步应该是找出它们的值.这两个表达式都以 和 是相同的
|
很对. | 104 | 是否这意味着four 本可以按照以下方式定义?
|
为什么有虚线框呢? | 105 | four 已经被定义了, 因而不能被再次定义. |
|
不过当然了, 一开始four 的确可以像那样定义.实际上, 其他表达式都不能分辨出 | 106 | cons 是一个构造子吗? |
是的, cons 构造Pair . | 107 | 为了对于car 表达式求值, 是否有必要对于car 的参数求值? |
的确. 为了找出一个car 表达式的值, 我们从找出其参数的值开始.关于这参数的值, 我们能说什么呢? | 108 | 这参数的值以cons 为顶. |
在找出参数的值之后, 接下来应该做什么呢? | 109 | 整个表达式的值是cons 的第一个参数. |
的值是什么? | 110 | cons 的第一个参数是 这并非一个值. |
为了找出一个car 表达式的值, 首先找出其参数的值, 这应该是(cons ) , 而 的值然后就是的值.如何找出一个 注记. 这里的代表 car 而代表cdr . | 111 | 就和car 一样, 我们从对于cdr 的参数求值开始, 直至其变为(cons ) , 然后 的值就是的值.所有的构造子都有参数吗? |
当然不是, 回忆一下, 第1章第86框里的zero 是一个构造子.两个表达式为相同的 | 112 | 这必然意味着每个表达式的值都以cons 为顶, 并且它们的car 是相同的Atom 而cdr 是相同的Nat . |
非常好. | 113 | 原子是构造子吗? |
原子'bay 是一个构造子, 因而原子'leaf 也是一个构造子. | 114 | 所有原子都是构造子吗? |
是的, 每个原子都构造其自身. 这是不是意味着每个原子都是值? | 115 | 的确, 因为解释为什么
Atom 值. |
嗯. 在表达式 | 116 | 那必然是zero , 因为zero 是没有参数的构造子. |
对于表达式'garlic 而言, 什么是顶层的构造子? | 117 | 原子'garlic 是仅有的构造子, 所以它必然就是顶层的构造子.那么, |
不是, Nat 并非一个构造子. zero 和add1 是创造数据的构造子, 而Nat 描述了特定的数据, 其要么就是zero , 要么以add1 为顶, 且以另一个Nat 为其参数.
| 118 | 不是, 因为Pair 表达式是在描述以cons 为顶的表达式. 构造子创建数据, 而不是类型.那么, |
Pair 是一个类型构造子(type constructor), 因其构造了一个类型. 类似地, Nat 和Atom 也是类型构造子. 是一个 吗? | 119 | 不是. 难道它不应该是一个 吗? |
的确如此! 但是 是一个 请问 的类型是什么?注记. 谢谢Julia Child (1912-2004). | 120 | 基于我们的所见所闻, 它必然是一个
译注. basil, thyme, oregano分别是罗勒, 百里香, 牛至, 这是三种典型的香料. 另外, Julia Child是一位厨师和电视名人. |
诚然如此. | 121 | 好吧, 暂时就那么多了, 我的脑袋要炸了! |
或许你应该再一次阅读这一章. 判断, 表达式, 类型是本书最重要的概念. | 122 | 在完全读完这一章之后, 或许应该来点新鲜蔬菜. |
ratatouille如何? | 1 | 很好(très bien), 谢谢提问. |
第1章里有构造子和类型构造子, 分别构造值和类型. 然而, | 2 | 那么, car 是什么呢? |
car 是一个消去子(eliminator). 消去子将构造子构造的值拆开来.另一个消去子是什么呢? | 3 | 如果car 是一个消去子, 那么显然cdr 也是一个消去子. |
|
另一种看待(消去子和构造子的)不同的方式在于值包含信息, 而消去子允许我们去利用这样的信息. | 4 | 存在兼作构造子和消去子的东西吗? |
不, 并不存在. 可以定义一个函数(function), 其表达力相当于 | 5 | 怎么做呢? |
这需要请出我们的老朋友λ . | 6 | 这是什么? 我有点陌生. |
Oops! 它也被称为lambda .注记. λ 可以选择写成lambda . | 7 | 好吧, λ 可以构造函数.这是不是意味着 |
是的, 的确如此, 因为每个长得像(λ ( ) ) 的表达式都是一个值.这种值的消去子是什么呢? 注记. 记号的意思是零个或更多的, 因此的意思是一个或更多的. | 8 | 我们唯一能对函数做的事情就是将其应用于参数上. 这样的话函数怎么拥有消去子呢? |
应用函数于参数是函数的消去子. | 9 | 好吧. |
|
的值是什么?译注. lentils指的是小扁豆. | 10 | 它自λ 起, 因而它已经是一个值了. |
是的. 的值是什么呢? | 11 | 那必然是(cons 'garlic 'lentils) , 如果λ 和lambda 的行为一致且cons 是一个构造子的话.但是这难道不意味着即便 |
不, 并非如此, 但是这是个非常好的问题. 替换这个λ 表达式的flavor 行为之发生是因为该λ 表达式被应用于了一个参数, 而不是因为cons .注记. 一致地替换一个变量以一个表达式有时被称为替换(substitution). 这个λ 表达式的体的每个flavor 都会被替换为'garlic , 不论环绕flavor 的表达式是什么. | 12 | 因此, 也就是说 的值应该是 对吗? |
为什么前一个框里的 不需要计算呢? | 13 | 整个表达式以cons 为顶, 故其已是值. |
第2章第12框里有点夸大其词. 如果以下λ 表达式的体中的root 出现在另一个同名的λ 之下的话, 那么它就不会被替换了. 的值是什么?译注. 这里的例子有两个同名但不同的变量, 以示对比. | 14 | 那必然是 因为内层的root 出现在一个同名的λ 表达式之下. |
λ 的确和lambda 行为一致, 因而这的确是正确的答案.成为一个 就是要成为一个λ 表达式, 当其应用于一个Atom 作为参数时, 则求值至一个
注记. (→ Atom (Pair Atom Atom)) 读作箭头 原子 暂停 序对 原子 原子, 并且 → 可以写成是两个字符的版本: -> . | 15 | 那以这样的λ 表达式为值的表达式呢? |
是的, 那些表达式也是 因为当给出一个Atom 作为其参数时, 它们也会变成
| 16 | 它们也是 吗? |
的确如此, 因为 是Atom 而 也是Atom . | 17 | 提问何谓两个表达式为相同的Nat , Atom , (Pair Nat Atom) 都是有意义的.提问何谓两个表达式为相同的 或者相同的 也是有意义的吗? |
是的, 的确如此. 两个表达式为相同的 当它们的值是相同的
| 18 | 它们的值是λ 表达式. 两个λ 为相同的 是什么意思呢? |
两个接受 (expect) 相同数目的参数的λ 是相同的, 如果它们的体是相同的. 例如, 两个λ 表达式是相同的 如果它们的体是相同的
| 19 | 这意味着 和 不是相同的 吗? |
这两个表达式有什么不同之处呢? | 20 | 参数的名字是不同的. 尽管如此, 这通常无关紧要. 现在紧不紧要呢? |
两个λ 表达式也是相同的, 如果可以通过一致地对于参数换名使得它们的体变得相同.注记. 一致地对于变量换名常被称为变换(alpha-conversion). 感谢Alonzo Church (1903-1995). 一致地对于变量换名不会改变任何东西的意义. | 21 | 和 是相同的 吗? |
|
|
|
不, 并非如此, 因为对于第二个λ 表达式中的变量进行一致换名以匹配第一个λ 表达式的参数将会产生 而(cons d a) 和(cons a d) 并非相同的(Pair Atom Atom) . | 22 | 呢? 它和 是相同的 吗? |
|
首先, 一致地将换名为. 现在, 问题就变为 和x 是否是相同的Nat . | 23 | 恰有两种方式可以使得两个表达式成为相同的Nat . 一种是它们的值都是zero . 另一种是它们的值都以add1 为顶, 而这两个add1 的参数是相同的Nat .这些表达式并非 |
x 的值尚不可知, 因为这个λ 表达式还没有被应用于一个参数. 但是, 当这个λ 表达式已被应用于一个参数时, x 的值仍然是一个Nat , 因为... | 24 | ...因为这个λ 表达式是一个 故参数x 不可能是任何其他什么东西. |
并非值且因为变量的缘故还不能被求值的表达式被称为中立(neutral)的. | 25 | 这意味着 是中立的咯?译注. rutabaga是芜菁甘蓝的意思. |
不, 它并非中立, 因为 是一个值.如果 是一个值吗? | 26 | 不是, 因为cdr 是一个消去子, 而消去子把值拆散.在不知道 |
中立表达式使得我们有必要扩展对于何谓相同的看法. 每个变量与其自身都是相同的, 不管其类型如何. 这是因为变量只能被一致地替换, 所以说一个变量的两次出现不可能被代之以不同的值. | 27 | 因此, 如果我们假定y 是一个Nat , 那么 和y 是相同的Nat , 这是因为该car 表达式的规范形式是y , 而y 和y 是相同的Nat . |
的确如此, 并且类似地, 我们有 和 是相同的
| 28 | 是的, 因为中立表达式x 和x 是相同的Nat . |
和 是相同的 吗? | 29 | 我们应该会这样认为, 但是理由是什么呢? |
第一步应该是一致地将y 换名为x . 和 是相同的 吗? | 30 | 是的, 如果假定 和 是相同的Nat .但是 |
如果两个表达式以等同的消去子为顶, 并且两个消去子的参数是相同的, 那么这两个表达式也是相同的. 字面上等同的中立表达式是相同的, 不管它们的类型如何. | 31 | 因而 和 是相同的Nat , 若假定x 是一个(Pair Nat Nat) . |
|
是一个 吗? | 32 | → 后面跟着更多的表达式意味着什么呢? |
→ 后面跟着的表达式, 除了最后一个, 都是参数的类型. 最后一个则是值的类型.注记. 最后一个类型读的时候前面会有停顿. | 33 | 好吧, 那么 的确是一个 这些表达式不可避免地正在逐渐变长. |
一种缩短它们的方式是小心地使用define , 如第1章第77框那样, 其总是允许我们用简短的名字来代替冗长的表达式. | 34 | 好想法. |
设构造子cons 被应用于'celery 和'carrot , 我们可以称这个值为vegetables . 从现在开始, 每当名字vegetables 被使用, 它就和 是相同的 因为这就是vegetables 如何被define 的.译注. celery指的是西芹. | 35 | 为什么claim 后面有写着 呢? |
|
(Pair Atom Atom) 描述了我们可以怎样使用vegetables . 例如, 我们知道(car vegetables) 是一个Atom , 而(cons 'onion vegetables) 是一个
注记. 这对于小扁豆汤 (lentil soup) 来说也是一个好的开始. | 36 | 啊, 懂了. |
和 是相同的 吗? | 37 | 的确如此, 因为每个表达式的值都是一个序对, 并且其car 是'celery 而cdr 是'carrot . |
实际上, 每当是一个(Pair Atom Atom) 时, 那么和 是相同的 找出(car ) 和(cdr ) 的值是没有必要的. | 38 | 这看起来很合理. |
|
以下定义可以允许吗?
| 39 | 什么鬼? |
尽管可能是个愚蠢的想法, 但它是可以被允许的. 的规范形式是什么? | 40 | 那必然是10 , 因为五 (five) 加等于十. |
再想想. 请记得five 的奇怪定义... | 41 | ...哦, 好吧, 那应该是14 , 因为five 被定义成了9 . |
的确如此. | 42 | 这个定义可以允许吗? 似乎它看上去不那么蠢.
|
虽然和将five 定义为9 相比没那么愚蠢, 但是这个定义也是不被允许的.已经被使用了的名字, 不论是用于构造子, 消去子, 还是之前的定义, 都不适合再与 | 43 | 好. |
|
Nat 有一个消去子可以区分值为zero 的Nat 和值以add1 为顶的Nat . 这个消去子被称为which-Nat . | 44 | which-Nat 到底是如何辨别应该是哪一种Nat 的呢? |
一个which-Nat 表达式具有三个参数: , , :
which-Nat 判断是否是zero , 如果是, 那么整个which-Nat 表达式的值即的值. 否则的话, 如果是(add1 ) , 那么整个which-Nat 表达式的值即( ) 的值. | 45 | 因此, which-Nat 既要判断一个数字是否是zero , 又要在数字并非zero 时去除其顶的add1 . |
的确如此. 的规范形式是什么呢? | 46 | 必然是'naught , 因为其target zero 是zero , 故整个which-Nat 表达式的值是, 即'naught .为什么 |
黯淡是用来指出n 在那个λ 表达式的体里没有被使用. 没有被使用的名字都将以黯淡的形式出现. | 47 | 为什么没有被使用呢? |
which-Nat 提供了使用更小的Nat 的可能性, 但是它并不要求一定使用. 当然, 为了提供这种可能性, which-Nat 的最后一个参数必须要接受一个Nat . | 48 | 好. |
|
的值是什么? | 49 | 必然是'more , 因为4 是另一种书写(add1 3) 的方式, 而其以add1 为顶. 的规范形式为
|
|
|
|
50 |
51 |
52 |
1 |
2 |
在[frame 2:70]里, 我们定义Pear 为
Pear 的消去子是由car 和cdr 定义的. | 1 | 并且... |
Pear 的一个消去子必须要做什么呢? | 2 | 这个消去子必须要暴露 (或者说解包) 一个Pear 中的信息. |
Pair 的消去子呢? 它必须要做什么? | 3 | Pair 的一个消去子必然要暴露一个Pair 中的信息. |
那很接近了. 正如[frame 1:22]所言, Pair 单独不是一个表达式, 然而 是一个表达式, 并且它有消去子. 也有消去子. | 4 | 再次尝试: 的一个消去子必然要暴露一个特定 中的信息, 一个 的消去子必然要暴露一个特定 中的信息. |