最近、少し Coq を勉強していて、False について納得するのに困難を感じていた。
悩んでいた話を忘れる前に書いておこう。
False -> A を Coq で証明すると次のプログラムが生成される
fun (A : Prop) (H : False) => match H return A with end : forall A : Prop, False -> A
これは False 型の引数 H を受け取って、A 型を返す関数である。この関数が存在することによって False -> A が証明されたことになる
順列組み合わせについてもけっこう悩んだ。ふたつのリストが順列組み合わせの関係にあるという Permutation という述語は以下のように定義される。
Inductive Permutation : list A -> list A -> Prop := | perm_nil: Permutation [] [] | perm_skip x l l' : Permutat|on l l' -> Permutation (x::l) (x::l') | perm_swap x y l : Permutation (y::x::l) (x::y::l) | perm_trans l l' l'' : Permutation l l' -> Permutation l' l'' -> Permutation l l''.
空リストと空リストは順列組み合わせ (perm_nil)、順列組み合わせとなっている l, l' があったときに先頭に同じ要素を前置したものは順列組み合わせ (perm_skip)、長さ2以上のリストで、先頭の2要素をひっくり返したものは順列組み合わせ (perm_swap)、推移律 (perm_trans)
これらで生成されるものが順列組み合わせであることは明らかなのだが、すべての順列組み合わせがこれらで生成できるというのは納得できなかった
納得するまでにけっこう時間がかかったのだが、こういうことだろう。
先頭要素が異なるリスト a::l と b::l' が順列組み合わせなら、l の中には b が入っているはずで、そうすると l と b::l'' が順列組み合わせになるように l'' を選べる。そうやって選んだ l'' を使うと、perm_skip により a::l と a::b::l'' は順列組合わせ。a::b::l'' と b::a::l'' は perm_swap により順列組み合わせ。a::l'' と l' は順列組み合わせのはずなので、perm_skip により b::a::l'' と b::l' も順列組み合わせ。だからひとつ短いリストの順列組み合わせの関係に帰着できる。
ここで、「はず」というのが 2回でてくる。l と b::l'' および a::l'' と l' の順列組み合わせの関係は、リストの長さがひとつ短いものに対する関係なので、帰納法みたいな感じで仮定してよい。というか、これはリストの長さに関する帰納法をやっているわけだよな。
[latest]