halt

A's arguments, like shuffie's and looking's, do not necessarily decrease for the recursion.

第九章从几个函数出发简单介绍了一下停机和死循环。

它将最终会停机的函数称为 total,否则称为 partial

以映射角度看函数,其居然有值无法到达陪域,因而称为 partial function

停机

这里给的证明是若函数 will-stop?total 的,则:

(will-stop? (lambda (x)
    (and (will-stop? last-try)
        (eternity x))))

会得到矛盾的值。

《计算理论导引》那书上的停机问题好像是归约到图灵机 不可判定上去

递归

(lambda (x) (x x))

这个例子相当引人入胜,用 构造出 length 来计算 list 的长度:

尝试

(((lambda (mk-length)
   (mk-length mk-length))
 (lambda (length)
   (lambda (l)
     (cond
       ((null? l) 0)
       (else (add1
              (length (cdr l)))))))) 
 '())

这个仅能计算一层,展开的话是:

->
(((lambda (length)
  (lambda (l)
    (cond
      ((null? l) 0)
      (else (add1
            (length (cdr l)))))))
  (lambda (length)
    (lambda (l)
      (cond
      ((null? l) 0)
       (else (add1
             (length (cdr l))))))))
  '())

->
((lambda (l)
    (cond
    ((null? l) 0)
    (else (add1
        ((lambda (length)
           (lambda (l)
            (cond
              ((null? l) 0)
              (else (add1
                (length (cdr l)))))))
           (cdr l))))))                 ; 本应传递一个 `length` 得到内部的 lambda,但传递了一个 `list`
  '())

->
0

可以看出来尚不足以进行长度大于 0 的递归,因为到后面 length 没有正确的参数传进去。

修复

; 一步步改进
(((lambda (mk-length)
   (mk-length mk-length))
 (lambda (mk-length)
   (lambda (l)
     (cond
       ((null? l) 0)
       (else (add1
              ((mk-length eternity)
               (cdr l))))))))
 '(1))

这里放了个 eternity 虚位以待,然而并不能改变它算不了非空 list 的事实:

->
(lambda (l)
  (cond
  ((null? l) 0)
  (else (add1
    ((lambda (mk-length)
      (lambda (l)
        (cond
          ((null? l) 0)
          (else (add1 
                  (mk-length (cdr l)))))))
      eternity                      ; 充其量
      (cdr l))))))

->
(lambda (l)
  (cond
    ((null? l) 0)
    (else (add1
      ((lambda (l')
          (cond
            ((null? l') 0)
            (else (add1 
                    (eternity (cdr l))))))
        (cdr l))))))

可以看出仅能递归两层。

接下来的任务是要用一个无穷递归来替换 eternity

无穷

为了让递归更明显,多写几层,无穷递归部分仍以 eternity 暂时代替

(lambda (l)
(cond
((null? l) 0)
(else (add1
  (
    (lambda (l)
    (cond
    ((null? l) 0)
    (else (add1
      (
        (lambda (l)
        (cond
        ((null? l) 0)
        (else (add1
          (
            (lambda (l)
            (cond
            ((null? l) 0)
            (else (add1
              (
                (lambda (l)
                (cond
                ((null? l) 0)
                (else (add1
                  (
                    (lambda (l)
                    (cond
                    ((null? l) 0)
                    (else (add1
                      (
                        (lambda (l)
                        (cond
                        ((null? l) 0)
                        (else (add1
                          (
                            (lambda (l)
                            (cond
                            ((null? l) 0)
                            (else (add1
                              (
                                (lambda (l)
                                (cond
                                ((null? l) 0)
                                (else (add1
                                  (
                                    (lambda (l)
                                    (cond
                                    ((null? l) 0)
                                    (else (add1
                                      (
                                        (lambda (l)
                                        (cond
                                        ((null? l) 0)
                                        (else (add1
                                          (
                                            (lambda (l)
                                            (cond
                                            ((null? l) 0)
                                            (else (add1
                                              (
                                                eternity
                                            (cdr l))))))
                                        (cdr l))))))
                                    (cdr l))))))
                                (cdr l))))))
                            (cdr l))))))
                        (cdr l))))))
                    (cdr l))))))
                (cdr l))))))
            (cdr l))))))
        (cdr l))))))
    (cdr l))))))
(cdr l))))))

回过头看用 eternity 作为占位符的定义:

((lambda (mk-length)
   (mk-length mk-length))
 (lambda (mk-length)
   (lambda (l)
     (cond
       ((null? l) 0)
       (else (add1
              ((mk-length eternity)
               (cdr l))))))))

最后真正想要得到的是这一部分:

(lambda (l)
  (cond
    ((null? l) 0)
    (else (add1
            ((mk-length eternity)
             (cdr l))))))

并且想要用这一个整体自身来替换 (mk-length eternity)

(lambda (l)
  (cond
    ((null? l) 0)
    (else (add1
            ((lambda (l)
              (cond
                ((null? l) 0)
                (else (add1
                        ((mk-length eternity)
                        (cdr l)))))))
             (cdr l))))))

换言之,我需要找到一个 eternity 满足


(mk-length eternity) 

=

(lambda (l)
  (cond
    ((null? l) 0)
    (else (add1
            ((mk-length eternity)
             (cdr l))))))

然而答案一开始就给出来了:

mk-length = 
(lambda (mk-length)
  (lambda (l)
    (cond
      ((null? l) 0)
      (else (add1
              ((mk-length eternity)
              (cdr l))))))))

(mk-length mk-length) = 
(lambda (l)
  (cond
    ((null? l) 0)
    (else (add1
            ((mk-length eternity)
            (cdr l))))))))

于是只需要取 eternity 在这里等于 mk-length 即可