Nun, etwas, das als Parametrizität bekannt ist, sagt uns, dass es, wenn wir die reine Teilmenge von ML betrachten (dh keine unendliche Rekursion ref
und all das seltsame Zeug), keine andere Möglichkeit gibt, eine Funktion mit diesem Typ zu definieren, als die, die das Leere zurückgibt Liste.
Alles begann mit Wadlers Artikel „ Theorems for free! ”. Dieses Papier sagt uns im Grunde zwei Dinge:
- Wenn wir Programmiersprachen betrachten, die bestimmte Bedingungen erfüllen, können wir einige coole Theoreme ableiten, indem wir nur die Typensignatur einer polymorphen Funktion betrachten (dies wird als Parametrizitätssatz bezeichnet).
- ML (ohne unendliche Rekursion
ref
und all das seltsame Zeug) erfüllt diese Bedingungen.
Aus dem Parametrizität Theorem wissen wir , dass , wenn wir eine Funktion haben f : 'a list -> 'b list
, dann für alle 'a
, 'b
, 'c
, 'd
und für alle Funktionen g : 'a -> 'c
, die h : 'b -> 'd
wir haben:
map h ∘ f = f ∘ map g
(Beachten Sie, f
links hat Typ 'a list -> 'b list
und f
rechts ist 'c list -> 'd list
.)
Wir können frei wählen, was g
wir wollen, also lassen Sie 'a = 'c
und g = id
. Jetzt haben wir map id = id
(leicht durch Induktion der Definition von zu beweisen map
):
map h ∘ f = f
Jetzt lass 'b = 'd = bool
und h = not
. Nehmen wir für einige an zs : bool list
, dass es passiert f zs ≠ [] : bool list
. Es ist klar, dass map not ∘ f = f
das nicht gilt, weil
(map not ∘ f) zs ≠ f zs
Wenn das erste Element der Liste rechts ist true
, dann ist links das erste Element false
und umgekehrt!
Dies bedeutet, dass unsere Annahme falsch ist und f zs = []
. Sind wir fertig? Nein.
Wir gingen davon aus, dass 'b
ist bool
. Wir haben gezeigt , dass , wenn f
mit Typ aufgerufen wird f : 'a list -> bool list
für jede 'a
, f
muss immer die leere Liste zurück. Kann es sein, dass wenn wir anrufen f
, f : 'a list -> unit list
es etwas anderes zurückgibt? Unsere Intuition sagt uns, dass dies Unsinn ist: Wir können einfach keine reine ML-Funktion schreiben, die immer die leere Liste zurückgibt, wenn wir möchten, dass sie uns eine Liste von Booleschen Werten gibt, und ansonsten möglicherweise eine nicht leere Liste zurückgibt! Dies ist jedoch kein Beweis.
Was wir sagen wollen, ist, dass f
es einheitlich ist : Wenn es immer die leere Liste für zurückgibt bool list
, muss es die leere Liste für unit list
und im Allgemeinen für jede zurückgeben 'a list
. Genau darum geht es beim zweiten Punkt in der Aufzählungsliste am Anfang meiner Antwort.
Das Papier sagt uns , dass in ML f
nehmen muß damit verbundene Werte zu verwandt denjenigen. Ich werde nicht in die Details über die Beziehungen, ist es genug , um zu sagen , dass Listen werden im Zusammenhang , wenn und nur wenn sie die gleiche Länge haben und ihre Elemente sind paarweise im Zusammenhang (das heißt, [x_1, x_2, ..., x_m]
und [y_1, y_2, ..., y_n]
beziehen sich, wenn und nur wenn m = n
und x_1
bezieht sich auf y_1
und x_2
ist verwandt mit y_2
und so weiter). Und der Spaß daran ist, in unserem Fall, da f
polymorph ist, wir können definieren , jede Beziehung auf die Elemente von Listen!
Lassen Sie uns holen jeder 'a
, 'b
und schauen Sie sich f : 'a list -> 'b list
. Nun sieh dir an f : 'a list -> bool list
; Wir haben bereits gezeigt, dass in diesem Fall f
immer die leere Liste zurückgegeben wird. Wir postulieren nun, dass alle Elemente von 'a
sich auf sich selbst beziehen (denken Sie daran, wir können jede gewünschte Beziehung wählen), dies impliziert, dass sich jede zs : 'a list
auf sich selbst bezieht. Wie wir wissen, werden f
verwandte Werte mit verwandten Werten in Verbindung gebracht. Dies bedeutet, dass sie f zs : 'b list
verwandt sind f zs : bool list
, aber die zweite Liste hat eine Länge von Null, und da die erste Liste damit verwandt ist, ist sie auch leer.
Der Vollständigkeit halber möchte ich erwähnen, dass es in der Originalarbeit des Wadlers einen Abschnitt über die Auswirkungen der allgemeinen Rekursion (mögliche Nichtbeendigung) gibt, und es gibt auch eine Arbeit , die freie Theoreme in Gegenwart von untersucht seq
.