Ja, es ist möglich, einen genauen Typ für eine Sortierroutine auszudrücken, sodass jede Funktion mit diesem Typ tatsächlich die Eingabeliste sortieren muss.
Während es eine fortgeschrittenere und elegantere Lösung geben könnte, werde ich nur eine elementare skizzieren.
f: nat -> nat
0..n−1
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) .
Ein einfaches Lemma kann leicht bewiesen werden.
Lemma lem1: forall n f, permutation n f -> m < n -> f m < n.
... (* from the def *)
mnh
m<n
Definition nth {A} {n} (l: list A n) m (h : m < n): A :=
... (* recursion over n *)
Bei einer Bestellung am A
können wir ausdrücken, dass eine Liste sortiert ist:
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 :=
...
Schließlich ist hier der Typ für einen Sortieralgorithmus:
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
n0..n−1l
s
f(m)<nnth
Beachten Sie jedoch, dass der Benutzer, dh der Programmierer, den korrekten Sortieralgorithmus nachweisen muss. Der Compiler überprüft nicht einfach, ob die Sortierung korrekt ist. Er überprüft lediglich einen bereitgestellten Beweis. In der Tat kann der Compiler nicht viel mehr als das: Semantische Eigenschaften wie "Dieses Programm ist ein Sortieralgorithmus" sind (nach dem Rice-Theorem) unentscheidbar , so dass wir nicht hoffen können, den Testschritt vollautomatisch zu machen.
In ferner, ferner Zukunft können wir immer noch hoffen, dass automatische Theoremprüfer so intelligent werden, dass "die meisten" praktisch verwendeten Algorithmen automatisch als korrekt erwiesen werden können. Der Reissatz besagt nur, dass dies nicht in allen Fällen möglich ist. Wir können nur auf ein korrektes, allgemein anwendbares, aber von Natur aus unvollständiges System hoffen.
Abschließend wird manchmal vergessen, dass selbst einfache Typsysteme unvollständig sind ! ZB auch in Java
int f(int x) {
if (x+2 != 2+x)
return "Houston, we have a problem!";
return 42;
}
ist semantisch typsicher (es wird immer eine Ganzzahl zurückgegeben), aber die Typprüfung beschwert sich über die nicht erreichbare Rückgabe.