2 歸納定義與證明

2.3 自然數上之歸納證明

上一節中我們定出了函數 exp。如果定義正確,exp b n 算的應是 $b^n$. 例如,我們知道 $b^{m+n} = b^m \times b^n$. 我們定出的函數 exp 是否真有此性質呢?

定理 2.1

對任何 b, m, n :: Nat, exp b (m + n) = exp b m * exp b n.

我們試著證明定理2.1 。數學歸納法是我們目前唯一的工具, 而要使用它,第一個問題是:該用 b, m, 或 n 的哪一個來做歸納呢(意即把哪一個拆解)?

觀察定理2.1 中待證明式的等號兩邊,並參照 exp, (+), 與 (*)的定義。 等號左手邊的 exp b (m + n) 之中,化簡 exp b 前得知道 m + n 究竟是 Zero 還是 Suc k。 而根據 (+) 的定義,化簡 m + n 前需知道 m 究竟是 Zero 還是 Suc k. 再看右手邊,根據 (*) 的定義,要化簡 exp b m * exp b n 得先化簡 exp b m, 而後者也得知道 m 是什麼。對兩邊的分析都指向:我們應針對 m 做歸納!

策略擬定後,我們便試試看吧!

證明

欲證明 exp b (m + n) = exp b m * exp b n, 我們在 m 之上做歸納。 m 要不就是 Zero, 要不就是 Suc k.

情況 m := Zero. 此時需證明 exp b (Zero + n) = exp b Zero * exp b n. 推論如下:

   exp b (Zero + n)
 ===    {- (+) 之定義 -}
   exp b n
 ===    {- 因 1 * k = k -}
   1 *: exp b n
 ===    {- exp 之定義 -}
   exp b Zero *: exp b n 

情況 m := Suc m. 此時需證明 exp b ((Suc m) + n) = exp b (Suc m) * exp b n, 但可假設 exp b (m + n) = exp b m * exp b n 已成立。推論如下:

   exp b ((Suc m) + n)
 ===    {- (+) 之定義 -}
   exp b (Suc (m + n))
 ===    {- exp 之定義 -}
   b *: exp b (m + n)
 ===    {- 歸納假設 -}
   b *: (exp b m *: exp b n)
 ===    {- (*) 之結合律 -}
   (b *: exp b m) *: exp b n
 ===    {- exp 之定義 -}
   exp b (Suc m) *: exp b n 

對這個證明,讀者是否有所懷疑?最大的疑問可能在「假設 exp b (m + n) = exp b m * exp b n 成立」這句上。這不就是我們要證明的性質嗎?在證明中假設它成立,似乎是用該性質自己在證明自己。這是可以的嗎?

為清楚說明,我們回顧一下第2.1 節中的數學歸納法(並把區域識別字改為 k 以避免混淆):

  (∀ k . P k)  <==   P Zero ⋀ (∀ k . P (Suc k) <== P k) 

證明2.1 欲證的是 exp b (m + n) = exp b m * exp b n,並在 m 上做歸納。 更精確地說,就是選用了下述的 P: 在程式推導圈子中,(<=>) 常用來代表「只用在真假值上、且滿足結合律的等號」。本書中使用 (<=>) 以和 (=) 做區分。

P m <=> (exp b (m + n) = exp b m * exp b n) 

在證明中改變的是 m,而 b 與 n 是固定的。數學歸納法可證明 (∀ m . P m), 展開後正是 (∀ m . exp b (m + n) = exp b m * exp b n). 而根據數學歸納法,我們需提供 P Zero 與 (∀ m . P (Suc m) <== P m) 的證明。

證明2.1 中「{\bf 情況} m := Zero」的部分,就是 P Zero 的證明。 而「{\bf 情況} m := Suc m」則是 (∀ m . P (Suc m) <== P m) 的證明。 「假設 exp b (m + n) = exp b m * exp b n 成立」指的是假設 P m 成立,我們在此前提之下試圖證明 P (Suc m). 因此,證明 2.1 並沒有「用該性質自己證明自己」。 我們是以一個比較小的結果(P m)證明稍大一點的結果(P (Suc m))。 就如同我們寫歸納程式時,假設 f n 已經算出,試著用它定出 f (Suc n).

在證明之中,如 P m 這種在歸納步驟假設成立的性質被稱作歸納假設(induction hypothesis)。

程式與證明   證明2.1 還有一些能啟發我們之處。方才,我們看到 exp b (m + n) = exp b m * exp b n, 決定以數學歸納法證明,但接下來怎麼著手?怎麼選定在哪個變數上做歸納?

答案是:分析該式中程式的行為。程式怎麼拆其參數,我們在證明中就怎麼拆。 我們試圖證明某些程式的性質,但程式本身便提供了證明可怎麼進行的提示。 「使證明的結構符合程式的結構」是許多證明的秘訣。 並非所有證明都可以如此完成,但本原則在許多情況下適用。

再看看 exp, (+), (*) 等函數的定義。 為何他們都分出了兩個情況:Zero 與 Suc n, 並且 Suc n 的情況使用到該函數對於 n 的值? 因為自然數的資料型別是這麼定的! 自然數只可能是Zero 或 Suc n,而後者是由 n 做出來的。 因此程式也如此寫。程式的結構依循與其處理的資料型別之結構。

資料、程式、與證明原來有著這樣的關係:證明的結構依循著程式的結構,而程式的結構又依循著資料型別的結構。歸納定義出了一個型別後,自然知道怎麼在上面寫歸納程式;歸納程式有了,自然知道如何做關於這些程式的歸納證明。一切由定義資料結構開始。掌握這個原則,大部分的證明就不是難事。

讓符號為你工作   再考慮證明2.1 中的狀況m := Suc m. 假想由你做這個證明,由第一行 exp b ((Suc m) + n) 開始。接下來該怎麼進行?

既然我們已經打定主意用數學歸納法,在證明的某處必定會使用exp b (m + n) = exp b m * exp b n這個歸納假設。 因此,證明前幾行的目的便是想辦法將 exp b ((Suc m) + n) 中的 Suc 往外提,將 exp b 往內側推,使得式子中出現 exp b (m + n)。一旦成功,就可運用歸納假設,將其改寫成 exp b m * exp b n! 接下的就是機械化地收尾、將式子整理成 exp b (Suc m) * exp b n 了。

這呼應到第0.2 節所說的「讓符號為你工作」。 光從語意上想,我們不易理解為何 exp b ((Suc m) + n) 能夠等於 exp b (Suc m) * exp b n. 但符號給我們線索。 我們可觀察式子的結構,暫時不去想語意; 我們的目標是操作、移動這些符號,將它們轉換成可使用歸納假設的形式。 因此,接下來的演算推導便有所依據而非盲目進行:已知目標是把某符號往外提或往內推, 我們就可尋找、使用可達到此目的的規則。 這些規則包括已知函數的定義、或諸如分配律、遞移律、結合律等等數學性質。 若很明顯地缺了一個想要的性質,也許可以把它當作引理另外證證看。 符號幫助我們,使我們的思考清晰而有方向。

練習 2.1

證明 1 * k = k. 這個證明並不需要歸納。

練習 2.2

證明 (+) 之結合律: m + (n + k) = (m + n) + k. 此證明中你使用的述語是什麼?

練習 2.3

證明 k + 1 = k. 你需要使用歸納法嗎?用什麼述語?

最後,說到自然數上的歸納定義,似乎不得不提階層(factorial)。用非正式的寫法,fact n = n * (n-1) * (n-2) * ... * 1. 形式化的定義如下:

fact :: Nat -> Nat
fact Zero     = 1
fact (Suc n)  = (Suc n) *: fact n 

我們在定理 2.5 中將會談到階層與排列的關係。