練習問題 3.3.4
関数
log
は,すべての
m
に対して,
log (2^m) = m
であるという条件によって指定できる.
log
のプログラムを構成し,それが仕様を満たすことを証明せよ.
log :: Nat -> Nat
log (Succ Zero) = Zero
log m = Succ (log (m / two))
two :: Nat
two = Succ (Succ Zero)
m
上の帰納法を使って証明する.
Zero の場合
log (two ^ Zero)
= { ^ の定義 }
log (Succ Zero)
= { log の定義 }
Zero
Succ m の場合
log (two ^ Succ m)
= { ^ の定義 }
log (two ^ m * two)
= { * の交換律 }
log (two * two ^ m)
= { log の定義 }
Succ (log (two * two ^ m / two))
= { / の仕様 }
Succ (log (two ^ m))
= { 帰納法の仮定 }
Succ m
*
の交換律:
m * n = n * m
は以下のように
n
上の帰納法により証明する.
Zero の場合
m * Zero
= { * の定義 }
Zero
= { Zero は * の左零元 }
Zero * m
Succ Zero の場合
m * Succ Zero
= { Succ Zero は単位元 }
Succ Zero * m
Succ n の場合
m * Succ n
= { * の定義 }
m * n + m
= { 帰納法の仮定 }
n * m + m
= { * は foldn のインスタンス,セクション }
(+m) (foldn (+n) Zero m)
= { 融合法則 }
foldn (+n) m m
= { foldn (+ Succ n) Zero m = foldn (+n) m m だから}
foldn (+Succ n) Zero m
= { * は foldn のインスタンス }
Succ n * m
foldn (+ Succ n) Zero m = foldn (+n) m m
の証明は
m
上の帰納法による.
Zero の場合
foldn (+ Succ n) Zero Zero
= { * は foldn のインスタンス }
Succ n * Zero
= { * の定義 }
Zero
= { * の定義 }
n * Zero
= { * は foldn のインスタンス }
foldn (+ n) Zero Zero
Succ m の場合
foldn (+ Succ n) Zero (Succ m)
= { foldn の定義 }
(+ Succ n) (foldn (+ Succ n) Zero m)
= { 帰納法の仮定 }
(+ Succ n) (foldn (+n) m m)
= { (+Succ n) = Succ . (+n) かつ m = (+m) Zero }
(Succ . (+n) . foldn (+n) ((+m) Zero)) m
= { 融合法則 }
(Succ . (+n) . (+m) . foldn (+n) Zero) m
= { Succ = (+1) }
((+1) . (+n) . (+m) . foldn (+n) Zero) m
= { 交換則,結合則 }
((+n) . (+1) . (+m) . fold (+n) Zero) m
= { Succ = (+1) }
((+n) . (+ Succ m) . fold (+n) Zero) m
= { 融合法則 }
((+n) . (fold (+n) ((+ Succ m) Zero))) m
= { (.)の定義,セクション,Zero は + の単位元 }
(+n) (foldn (+n) (Succ m) m)
= { foldn の定義 }
foldn (+n) (Succ m) (Succ m)