プログラミング Haskell 第13章 プログラムの論証 その2
最終章「プログラムの論証」続きです。まだ難しくはないです。
reverse (reverse xs) = xs を証明する xs = [] の時 reverse (reverse []) => reverse [] => [] xs=ns の時 reverse (reverse ns) = ns が成り立つと仮定して。 reverse (reverse (n:ns)) => reverse (reverse ns ++ [n]) => reverse [n] ++ reverse (reverse ns) -- 分配則 => [n] ++ reverse (reverse ns) -- 前回証明した reverse [x] = [x] => [n] ++ ns => (n:ns) 故に任意のリスト xs について reverse (reverse xs) = xs
reverse の分配則は別に証明します。
reverse (xs ++ ys) = reverse ys ++ reverse xs を証明する xs = [] の時 reverse ([] ++ ys) => reverse ys また reverse ys ++ reverse [] => reverse ys ++ [] => reverse ys xs = ns の時に以下が成り立つと仮定して reverse (ns ++ ys) = reverse ys ++ reverse ns xs=(n:ns) の時 reverse ((n:ns) ++ ys) => reverse (n:(ns ++ ys)) => reverse (ns ++ ys) ++ [n] -- reverse を1回適用(簡約)する => (reverse ys ++ reverse ns) ++ [n] => reverse ys ++ (reverse ns ++ [n]) => reverse ys ++ (reverse (n:ns)) -- reverse を逆向きに適用
最後の関数の逆向きの適用は本書とはちょっと違うやりかたですが、「関数とその定義は相互に置き換え可能」と 13.2 に書いてあったのでやりかたとして間違ってはいないはずです。
まだ「あたりまえ」の範疇ですが、この調子でもっと自明でない複雑な命題も証明できそうだなという感覚は見えてきたところで今日はここまで。