回答:
はい、ソートルーチンの正確なタイプを表すことが可能です。そのタイプを持つ関数は、実際に入力リストをソートする必要があります。
より高度で洗練された解決策があるかもしれませんが、基本的なものだけをスケッチします。
f: nat -> nat
Definition permutation (n: nat) (f: nat -> nat): Prop :=
(* once restricted, its codomain is 0..n-1 *)
(forall m, m < n -> f m < n) /\
(* it is injective, hence surjective *)
(forall m1 m2, m1 < n -> m2 < n -> f m1 = f m2 -> m1 = m2) .
単純な補題は簡単に証明できます。
Lemma lem1: forall n f, permutation n f -> m < n -> f m < n.
... (* from the def *)
h
Definition nth {A} {n} (l: list A n) m (h : m < n): A :=
... (* recursion over n *)
の順序が与えられるA
と、リストがソートされることを表現できます。
Definition ordering (A: Type) :=
{ leq: A->A->bool |
(* axioms for ordering *)
(forall a, leq a a = true) /\
(forall a b c, leq a b = true -> leq b c = true -> leq a c = true) /\
(forall a b, leq a b = true -> leq b a = true -> a = b)
} .
Definition sorted {A} {n} (o: ordering A) (l: list A n): Prop :=
...
最後に、並べ替えアルゴリズムのタイプを次に示します。
Definition mysort (A: Type) (o: ordering A) (n: nat) (l: list A n):
{s: list A n | sorted o s /\
exists f (p: permutation n f),
forall (m: nat) (h: m < n),
nth l m h = nth s (f m) (lem1 n f p h) } :=
... (* the sorting algorithm, and a certificate for its output *)
s
l
s
nth
ただし、並べ替えアルゴリズムが正しいことを証明する必要があるのはユーザー、つまりプログラマーであることに注意してください。コンパイラーは、ソートが正しいことを単に検証するだけではなく、提供された証明をチェックするだけです。実際、コンパイラはそれ以上のことはできません。「このプログラムはソートアルゴリズムです」などのセマンティックプロパティは(ライスの定理により)決定できないため、証明ステップを完全に自動化することは望めません。
遠い将来においても、自動定理証明器が非常に賢くなり、実際に使用されている「ほとんど」のアルゴリズムが自動的に正しいことが証明されることを期待できます。ライスの定理は、これがすべての場合に実行できるわけではないと述べているだけです。私たちが期待できるのは、正確で広く適用されますが、本質的に不完全なシステムです。
最後に、単純な型システムであっても不完全であることを忘れてしまうことがあります。たとえばJavaでも
int f(int x) {
if (x+2 != 2+x)
return "Houston, we have a problem!";
return 42;
}
意味的にはタイプセーフです(常に整数を返します)が、型チェッカーは到達不能な戻りについて文句を言うでしょう。