Arend - HoTT-basierte abhängige Typensprache (Teil 2)

Im ersten Teil des Artikels über die Arend-Sprache haben wir die einfachsten induktiven Typen, rekursiven Funktionen, Klassen und Mengen untersucht.

2. Sortieren von Listen in Arend


2.1 Bestellte Listen in Arend


Wir definieren den Typ der geordneten Listen als ein Paar, das aus einer Liste und einem Nachweis ihrer Reihenfolge besteht. Wie bereits erwähnt, werden in Arend abhängige Paare mit dem Schlüsselwort \Sigma definiert. Wir geben die Definition des Sorted Typs durch Vergleich mit der Stichprobe an, inspiriert von der Definition aus dem bereits erwähnten Artikel über geordnete Listen.

 \func SortedList (O : LinearOrder.Dec) => \Sigma (l : List O) (Sorted l) \data Sorted {A : LinearOrder.Dec} (xs : List A) \elim xs | nil => nilSorted | :-: x nil => singletonSorted | :-: x1 (:-: x2 xs) => consSorted ((x1 = x2) || (x1 < x2)) (Sorted (x2 :-: xs)) 

Hinweis: Arend konnte automatisch schließen, dass der Sorted Typ im \Prop Universum enthalten ist. Dies geschah, weil sich alle drei Muster in der Sorted Definition gegenseitig ausschließen und der consSorted Konstruktor zwei Parameter hat, die beide zu \Prop .
Lassen Sie uns eine offensichtliche Eigenschaft des Sorted Prädikats beweisen, sagen wir, dass das Ende einer geordneten Liste selbst eine geordnete Liste ist (diese Eigenschaft wird uns in Zukunft nützlich sein).

 \func tail-sorted {O : LinearOrder.Dec} (x : O) (xs : List O) (A : Sorted (x :-: xs)) : Sorted xs \elim xs, A | nil, _ => nilSorted | :-: _ _, consSorted _ xs-sorted => xs-sorted 

In der nach tail-sorted wir gleichzeitig den Mustervergleich für die xs Liste und das Sorted Prädikat verwendet. Außerdem haben wir das Überspringzeichen "_" verwendet , das nicht verwendete Variablen ersetzen kann.

Man kann sich fragen, ob es in Arend möglich ist, die Eigenschaft geordneter Listen zu beweisen, die in Abschnitt 1.3 als Beispiel für eine Tatsache erwähnt werden, die in Agda ohne Anmerkungen zur Immaterialität nicht bewiesen werden kann. Denken Sie daran, dass diese Eigenschaft behauptet, dass es ausreicht, die Gleichheit der ersten Komponenten der Paare zu überprüfen, um die Gleichheit der durch abhängige Paare definierten geordneten Listen zu beweisen.

Es wird argumentiert, dass in Arend diese Eigenschaft als Folge der inProp erwähnten inProp Konstruktion und der Extensionalitätseigenschaft für abhängige SigmaExt Paare leicht erhalten werden kann.

 \func sorted-equality {A : LinearOrder.Dec} (l1 l2 : SortedList A) (P : l1.1 = l2.1) : l1 = l2 => SigmaPropExt Sorted l1 l2 P 

Die SigmaPropExt Eigenschaft SigmaPropExt im Paths- Modul der Standardbibliothek bewiesen. Dort werden auch viele andere Fakten aus dem zweiten Kapitel des HoTT-Buches , einschließlich der Eigenschaft der funktionalen Erweiterbarkeit , bewiesen.

Der Operator .n in Arend verwendet, um auf den Sigma-Projektor mit der Nummer n zuzugreifen (in unserem Fall ist der Sigma-Typ SortedList A , und der Ausdruck l1.1 bedeutet, dass die erste Komponente dieses Typs ein Ausdruck vom Typ List A ).

2.2 Implementierung der Eigenschaft "be permutation"


Versuchen wir nun, die Listensortierfunktion in Arend zu implementieren. Natürlich wollen wir keine einfache Implementierung des Sortieralgorithmus, sondern eine Implementierung zusammen mit einem Nachweis einiger Eigenschaften.

Dieser Algorithmus muss mindestens zwei Eigenschaften haben:
1. Das Ergebnis des Algorithmus sollte eine geordnete Liste sein.
2. Die resultierende Liste sollte eine Permutation der ursprünglichen Liste sein.

Versuchen wir zunächst, die Eigenschaft "be permutation" von Listen in Arend zu implementieren. Dazu passen wir die Definition von hier für Arend an.

 \truncated \data InsertSpec {A : \Set} (xs : List A) (a : A) (ys : List A) : \Prop \elim xs, ys | xs, :-: y ys => insertedHere (a = y) (xs = ys) | :-: x xs, :-: y ys => insertedThere (x = y) (InsertSpec xs a ys) \truncated \data Perm {A : \Set} (xs ys : List A) : \Prop | permInsert (xs' ys' : List A) (a : A) (Perm xs' ys') (InsertSpec xs' a xs) (InsertSpec ys' a ys) | permTrivial (xs = ys) 

Das von uns eingeführte InsertSpec Prädikat hat die folgende intuitive Bedeutung: InsertSpec xs a ys bedeutet genau, dass die Liste ys das Ergebnis des Einfügens des Elements a in die Liste xs (an einer beliebigen Position) ist. Somit kann InsertSpec als Spezifikation der InsertSpec verwendet werden.

Es ist klar, dass der Datentyp Perm tatsächlich die Beziehung "be permutation" definiert: Der Konstruktor permInsert genau an, dass xs und ys für beide Seiten durchlässig sind, wenn xs und ys erhalten werden, indem dasselbe Element a in einige Listen xs' und ys' kürzere Längen, die bereits Permutationen voneinander sind.

Für unsere Definition der Eigenschaft "be permutation" ist es einfach, die Symmetrieeigenschaft zu überprüfen.

 \func Perm-symmetric {A : \Set} {xs ys : List A} (P : Perm xs ys) : Perm ys xs \elim P | permTrivial xs=ys => permTrivial (inv xs=ys) | permInsert perm-xs'-ys' xs-spec ys-spec => permInsert (Perm-symmetric perm-xs'-ys') ys-spec xs-spec 

Die Transitivitätseigenschaft ist auch für Perm erfüllt, aber ihre Überprüfung ist viel komplizierter. Da diese Eigenschaft bei der Implementierung unseres Sortieralgorithmus keine Rolle spielt, überlassen wir sie dem Leser als Übung.

 \func Perm-transitive {A : \Set} (xs ys zs : List A) (P1 : Perm xs ys) (P2 : Perm ys zs) : Perm xs zs => {?} 

2.3 Änderung der Homotopie im Vergleich zur Probe


Versuchen wir nun, eine Funktion zu implementieren, die ein Element in eine geordnete Liste einfügt, damit die resultierende Liste geordnet bleibt. Beginnen wir mit der folgenden naiven Implementierung.

 \func insert {O : LinearOrder.Dec} (xs : List O) (y : O) : List O \elim xs | nil => y :-: nil | :-: x xs' => \case LinearOrder.trichotomy xy \with {  | byLeft x=y => x :-: insert xs' y  | byRight (byLeft x<y) => x :-: insert xs' y  | byRight (byRight y<x) => y :-: x :-: xs' } 

Das \case Konstrukt ermöglicht den Abgleich mit einer Stichprobe eines beliebigen Ausdrucks ( \elim kann nur auf der höchsten Ebene einer Funktionsdefinition und nur für deren Parameter verwendet werden). Wenn Sie Arend bitten, den Einfügetyp zu überprüfen, wird die folgende Fehlermeldung angezeigt.

 [ERROR] Data type '||' is truncated to the universe \Prop  which does not fit in the universe of the eliminator type: List OE In: | byLeft x-leq-y => x :-: insert xs' y While processing: insert 

Das Problem ist, dass in der LinearOrder.Dec Klasse LinearOrder.Dec Definition der trichotomy mit dem Operator || wird , die wiederum unter Verwendung von Satzkürzungen bestimmt wird. Wie bereits erwähnt, ist für Typen, die zum \Prop Universum gehören, die Übereinstimmung mit einem Muster in Arend nur zulässig, wenn der Typ des resultierenden Ausdrucks selbst eine Behauptung ist (für die obige Funktion ist das Ergebnis vom Typ List OE , und dieser Typ ist eine Menge).

Gibt es einen Weg um dieses Problem herum? Der einfachste Weg, dies zu lösen, besteht darin, die Definition der Eigenschaft der Trichotomie zu ändern. Betrachten Sie die folgende Definition der Trichotomie unter Verwendung des nicht abgeschnittenen Typs Or anstelle des abgeschnittenen || ::

 \func set-trichotomy {A : StrictPoset} (xy : A) => ((x = y) `Or` (x < y)) `Or` (y < x) 

trichotomy diese Definition in irgendetwas von der ursprünglichen trichotomy Definition durch || ? Warum haben wir überhaupt einen propositionell abgeschnittenen Typ verwendet, wenn dies unser Leben nur kompliziert und uns daran hindert, Mustervergleiche zu verwenden?

Versuchen wir zunächst, die erste Frage zu beantworten: Bei strengen StrictPoset Ordnungen StrictPoset Unterschied zwischen trichotomy und set-trichotomy eigentlich gar nicht. Beachten Sie, dass der set-trichotomy Typ eine Aussage ist. Diese Tatsache folgt aus der Tatsache, dass sich alle drei Alternativen in der Definition der Trichotomie aufgrund von Ordnungsaxiomen gegenseitig ausschließen und jeder der drei Typen x = y, x < y, y < x selbst eine Aussage ist ( x = y ist also eine Aussage Wie in der Definition der BaseSet Klasse BaseSet wir gefordert, dass das Medium E eine Menge ist!).

 \func set-trichotomy-isProp {A : StrictPoset} (xy : A) (l1 l2 : set-trichotomy xy): l1 = l2 \elim l1, l2 | inl (inl l1), inl (inl l2) => pmap (\lam z => inl (inl z)) (Path.inProp l1 l2) | inl (inr l1), inl (inr l2) => pmap (\lam z => inl (inr z)) (Path.inProp l1 l2) | inr l1, inr l2 => pmap inr (Path.inProp l1 l2) | inl (inl l1), inl (inr l2) => absurd (lt-eq-false l1 l2) | inl (inr l1), inl (inl l2) => absurd (lt-eq-false l2 l1) | inl (inl l1), inr l2 => absurd (lt-eq-false (inv l1) l2) | inr l1, inl (inl l2) => absurd (lt-eq-false (inv l2) l1) | inl (inr l1), inr l2 => absurd (lt-lt-false l1 l2) | inr l1, inl (inr l2) => absurd (lt-lt-false l2 l1) \where {  \func lt-eq-false {A : StrictPoset} {xy : A} (l1 : x = y) (l2 : x < y) : Empty =>    A.<-irreflexive x (transport (x <) (inv l1) l2)  \func lt-lt-false {A : StrictPoset} {xy : A} (l1 : x < y) (l2 : y < x) : Empty =>   A.<-irreflexive x (A.<-transitive _ _ _ l1 l2) } 

absurd ist in der obigen Auflistung die Bezeichnung für das Ex-Falso-Quodlibet-Prinzip, das im Logikmodul definiert ist. Da der Empty Typ keine Konstruktoren in der Definition enthält (siehe Abschnitt 1.2), ist es nicht erforderlich, Fälle in der Definition von absurd :

 \func absurd {A : \Type} (x : Empty) : A 

Da wir jetzt wissen, dass die set-trichotomy eine Aussage ist, können wir die set-trichotomy Eigenschaft aus der üblichen trichotomy Eigenschaft entscheidbarer Ordnungen ableiten. Dazu können wir die Konstruktion \return \level verwenden, die dem Arend-Timer mitteilt, dass zu diesem Zeitpunkt der Mustervergleich eine zulässige Operation ist (in diesem Fall müssen wir beweisen, dass das Ergebnis der Funktion set-trichotomy-property eine Anweisung ist).

 \func set-trichotomy-property {A : LinearOrder.Dec} (xy : A) : set-trichotomy xy => \case A.trichotomy xy \return \level (set-trichotomy xy) (set-trichotomy-isProp xy) \with {  | byLeft x=y => inl (inl x=y)  | byRight (byLeft x<y) => inl (inr x<y)  | byRight (byRight y<x) => inr (y<x) } 

Versuchen wir nun, die zweite Frage zu beantworten, nämlich warum es bei der Formulierung der Eigenschaften mathematischer Objekte vorzuziehen ist, nicht gewöhnliche, sondern propositionell verkürzte Konstruktionen zu verwenden. Betrachten Sie dazu ein Fragment der Definition nichtlinearer linearer Ordnungen (vollständige Definitionen von Lattice und TotalOrder finden Sie im LinearOrder- Modul):

 \class TotalOrder \extends Lattice { | totality (xy : E) : x <= y || y <= x } 

Versuchen wir uns jetzt vorzustellen, wie sich die Bedeutung der TotalOrder Klasse ändern würde, wenn wir die Definition des Totalitätsfelds durch die nicht abgeschnittene Or Konstruktion TotalOrder würden.

 \class BadTotalOrder \extends Lattice { | badTotality (xy : E) : (x <= y) `Or` (y <= x) } 

In diesem Fall ist der Typ (x <= y) `Or` (y <= x) keine Aussage mehr, weil Bei gleichen Werten von x und y beide Alternativen bei der Definition von badTotality implementiert werden, und die Wahl des linken oder rechten Zweigs beim Nachweis von badTotality absolut willkürlich und liegt im Ermessen des Benutzers - es gibt keinen Grund, einen Or Konstruktor einem anderen vorzuziehen.

Jetzt ist klar, was der Unterschied zwischen TotalOrder und BadTotalOrder . Zwei geordnete Mengen O1 O2 : TotalOrder sind immer gleich, wenn es möglich ist, die Gleichheit der Mengen O1.E, O2.E und der Ordnungen O1.<, O2.< Zu beweisen (dies ist die gewünschte Eigenschaft). Andererseits ist es für O1 O2 : BadTotalOrder nur BadTotalOrder , die Gleichheit von O1 und O2 zu beweisen, wenn zusätzlich zu allen Elementen x aus E Gleichheit O1.badTotality xx und O2.badTotality xx .

Es stellt sich also heraus, dass die Klasse BadTotalOrder intuitiv nicht als "linear geordnete Menge" betrachtet werden muss, sondern als "linear geordnete Menge zusammen mit der Auswahl für jedes Element x Feldes E linken oder rechten Zweigs Or bei der Implementierung von badTotality xx ".

2.4 Sortieralgorithmus


Wir fahren nun mit der Implementierung des Sortieralgorithmus fort. Versuchen wir, die naive Implementierung der insert Funktion aus dem vorherigen Abschnitt mithilfe der bewährten set-trichotomy-property (in diesem Fall haben wir aufgrund der erfolgreicheren Anordnung von Klammern bei der Definition der set-trichotomy die Anzahl der berücksichtigten Fälle reduziert).

 \func insert {O : LinearOrder.Dec} (xs : List O) (y : O) : List O \elim xs | nil => y :-: nil | :-: x xs' => \case set-trichotomy-property xy \with {  | inr y<x => y :-: x :-: xs'  | inl x<=y => x :-: insert xs' y } 

Versuchen wir nun, ein Analogon dieser Definition für geordnete Listen zu implementieren. Wir werden das spezielle Konstrukt \let … \in verwenden, mit dem wir dem Kontext neue lokale Variablen hinzufügen können.

 \func insert {O : LinearOrder.Dec} (xs : SortedList O) (y : O) : SortedList O \elim xs | (nil, _) => (y :-: nil, singletonSorted) | (:-: x xs', xs-sorted) => \case set-trichotomy-property xy \with {  | inr y<x => (y :-: x :-: xs', consSorted (byRight y<x) xs-sorted)  | inl x<=y => \let (result, result-sorted) => insert (xs', tail-sorted x xs' xs-sorted) y         \in (x :-: result, {?}) 

Wir haben im Beweis ein unvollständiges Fragment hinterlassen (angezeigt durch den Ausdruck {?} ). An der Stelle, an der Sie zeigen möchten, dass das x :-: result der Liste x :-: result geordnet ist. Obwohl es im Kontext Hinweise auf die Reihenfolge der result , müssen wir überprüfen, ob x den Wert des ersten Elements der result nicht überschreitet, was von den Prämissen im Kontext nicht so einfach zu verfolgen ist (um alle Prämissen im aktuellen Ziel zu sehen - das nennen wir Derzeitiger Berechnungszweig - Sie müssen die Typprüfung bei der insert anfordern.

Es stellt sich heraus, dass das insert viel einfacher zu implementieren ist, wenn wir die Reihenfolge der resultierenden Liste parallel zum Nachweis der insert . Ändern Sie die Unterschrift der insert und schreiben Sie in den einfachsten Fällen den Nachweis dieser Spezifikation:

 \func insert {O : LinearOrder.Dec} (xs : SortedList O) (y : O) : \Sigma (ys : SortedList O) (InsertSpec xs.1 y ys.1) \elim xs | (nil, _) => ((y :-: nil, singletonSorted), insertedHere idp idp) | (:-: x xs', xs-sorted) => \case set-trichotomy-property xy \with {  | inr y<x => ((y :-: x :-: xs', consSorted (byRight y<x) xs-sorted), insertedHere idp idp)  | inl x<=y =>   \let ((result, result-sorted), result-spec) => insert (xs', tail-sorted x xs' xs-sorted) y   \in ((x :-: result, {?}), insertedThere idp result-spec) 

Für ein einzelnes Fragment ohne Beweis gibt Arend den folgenden Kontextwert aus:

 Expected type: Sorted (x :-: (insert (\this, tail-sorted x \this \this) \this).1.1) Context:  result-sorted : Sorted (insert (\this, tail-sorted \this \this \this) \this).1.1  xs-sorted : Sorted (x :-: xs')  x : O  x<=y : Or (x = y) (O.< xy)  O : Dec  result : List O  y : O  xs' : List O  result-spec : InsertSpec xs' y (insert (xs', tail-sorted \this xs' \this) y).1.1 

Um den Beweis zu vervollständigen, müssen wir die volle Leistung des Operators \case : Wir werden den Mustervergleich mit 5 verschiedenen Variablen verwenden, und da die Typen einiger Variablen von den Werten anderer Variablen abhängen können, werden wir den abhängigen Mustervergleich verwenden.

Die Doppelpunktkonstruktion gibt explizit an, wie der Typ einiger verglichener Variablen von den Werten anderer Variablen abhängt (also in der Art der Variablen xs-sorted, result-spec und result-sorted in jedem von \case anstelle von xs' und result stimmt mit den entsprechenden Stichproben überein).

Das Konstrukt \return ordnet die Variablen, die zum Abgleichen des Musters verwendet werden, dem Typ des erwarteten Ergebnisses zu. Mit anderen Worten, im aktuellen Ziel wird in jeder der \case Klauseln die entsprechende Stichprobe durch die entsprechende Stichprobe ersetzt. Ohne diese Konstruktion würde eine solche Ersetzung nicht durchgeführt, und das Ziel aller \case Klauseln würde mit dem Ziel anstelle des \case Ausdrucks selbst übereinstimmen.

 \func insert {O : LinearOrder.Dec} (xs : SortedList O) (y : O) : \Sigma (ys : SortedList O) (InsertSpec xs.1 y ys.1) \elim xs  | (nil, _) => ((y :-: nil, singletonSorted), insertedHere idp idp)  | (:-: x xs', xs-sorted) => \case set-trichotomy-property xy \with {   | inr y<x => ((y :-: x :-: xs', consSorted (byRight y<x) xs-sorted), insertedHere idp idp)   | inl x<=y =>     \let ((result, result-sorted), result-spec) => insert (xs', tail-sorted x xs' xs-sorted) y     \in ((x :-: result,       \case result \as result, xs' \as xs', xs-sorted : Sorted (x :-: xs'), result-spec : InsertSpec xs' y result, result-sorted : Sorted result       \return Sorted (x :-: result) \with {        | nil, _, _, _, _ => singletonSorted        | :-: r rs, _, _, insertedHere y=r _, result-sorted => consSorted (transport (\lam z => (x = z) || (x < z)) y=r (Or-to-|| x<=y)) result-sorted        | :-: r rs, :-: x' _, consSorted x<=x' _, insertedThere x2=r _, result-sorted => consSorted (transport (\lam z => (x = z) || (x < z)) x2=r x<=x') result-sorted }), insertedThere idp result-spec) 

Im obigen Codeblock verdienen die komplexen ersten Argumente des consSorted Konstruktors in den letzten beiden Absätzen des Mustervergleichs einen zusätzlichen Kommentar. Um zu verstehen, was diese beiden Ausdrücke bedeuten, ersetzen wir sie durch den Ausdruck {?} Und bitten den Arend-Timer, Ziele an beiden Positionen zu bestimmen.

Sie können sehen, dass sowohl dort als auch dort das aktuelle Ziel der Typ (x = r) || O.< xr (x = r) || O.< xr . Darüber hinaus gibt es im Rahmen des ersten Ziels Prämissen

 x<=y : Or (x = y) (O.< xy) y=r : y = r 

und im Kontext der zweiten Prämisse

 x<=x' : (x = x') || O.< xx' x2=r : x' = r. 

Intuitiv klar: Um das erste Ziel zu beweisen, reicht es aus, die Variable r durch die richtige Aussage Or (x = y) (O.< xy) zu ersetzen und dann zum propositionell abgeschnittenen Typ || wechseln Verwenden der in Abschnitt 1.3 definierten Or-to-|| -Funktion . Um das zweite Ziel zu beweisen, setzen Sie einfach (x = x') || O.< x x' (x = x') || O.< x x' anstelle der Variablen x' Variable r .

Zur Formalisierung der beschriebenen Ausdruckssubstitutionsoperation existiert in der Standard-Arend-Bibliothek eine spezielle transport . Betrachten Sie ihre Unterschrift:

 \func transport {A : \Type} (B : A -> \Type) {aa' : A} (p : a = a') (b : B a) : B a' 

In unserem Fall müssen wir anstelle der Variablen A den Typ OE ersetzen (er kann explizit weggelassen werden, wenn die anderen transport angegeben werden) und anstelle von B den Ausdruck \lam (z : O) => (x = z) || (x < z) \lam (z : O) => (x = z) || (x < z) .

Die Implementierung des Einfügungssortierungsalgorithmus zusammen mit der Spezifikation verursacht keine besonderen Schwierigkeiten mehr: Um die Liste x :-: xs' zu sortieren, sortieren wir zuerst den Schwanz der Liste xs' mit einem rekursiven Aufruf von insertSort und fügen dann das Element x in diese Liste ein, wobei die Reihenfolge für insertSort wird Hilfe beim Zugriff auf die bereits implementierte insert .

 \func insertSort {O : LinearOrder.Dec} (xs : List O) : \Sigma (result : SortedList O) (Perm xs result.1) \elim xs | nil => ((nil, nilSorted), permTrivial idp) | :-: x xs' => \let | (ys, perm-xs'-ys) => insertSort xs'                      | (zs, zs-spec) => insert ys x                  \in (zs, permInsert perm-xs'-ys (insertedHere idp idp) zs-spec) 

Wir haben das ursprüngliche Ziel erreicht und die Sortierung der Listen auf Arend implementiert. Der gesamte in diesem Absatz angegebene Arend-Code kann von hier aus in einer Datei heruntergeladen werden .

Man könnte sich fragen, wie man die Implementierung der LinearOrder.Dec ändern müsste, wenn wir anstelle der strengen LinearOrder.Dec Befehle die nicht strengen TotalOrder Befehle verwenden würden. Wie wir uns erinnern, wird bei der Definition der Totalitätsfunktion die Verwendung der abgeschnittenen Operation || war ziemlich bedeutsam, das heißt, diese Definition entspricht nicht einer Definition, in der anstelle von || verwendet von Or .

Die Antwort auf diese Frage lautet wie folgt: Es ist immer noch möglich, ein insert Analogon für TotalOrder zu TotalOrder . Dazu müssten wir jedoch beweisen, dass der Typ der insert Funktion eine Anweisung ist (dies würde es uns bei der Definition von insert , mit der Stichprobe gemäß der totality xy Anweisung totality xy ).

Mit anderen Worten, wir müssten beweisen, dass es nur eine geordnete Liste bis zur Gleichheit gibt, was das Ergebnis des Einfügens des Elements y in die geordnete Liste xs . Es ist leicht zu erkennen, dass dies eine wahre Tatsache ist, aber der formale Beweis ist nicht mehr so ​​trivial. Wir überlassen die Überprüfung dieser Tatsache dem interessierten Leser als Übung.

3. Schlussbemerkungen


In dieser Einführung haben wir die Hauptkonstrukte der Arend-Sprache kennengelernt und auch gelernt, wie man den Klassenmechanismus verwendet. Es ist uns gelungen, den einfachsten Algorithmus zusammen mit dem Nachweis seiner Spezifikation zu implementieren. So haben wir gezeigt, dass Arend gut zur Lösung "alltäglicher" Probleme geeignet ist, wie zum Beispiel zur Programmüberprüfung.

Wir haben weit entfernt von allen Funktionen und Merkmalen von Arend erwähnt. Zum Beispiel haben wir fast nichts über Typen mit Bedingungen gesagt, die es Ihnen ermöglichen, verschiedene Typkonstruktoren mit einigen speziellen Parameterwerten für diese Konstruktoren zu „kleben“. Beispielsweise wird eine Implementierung des Integer-Typs in Arend unter Verwendung von Typen mit folgenden Bedingungen angegeben:

 \data Int | pos Nat | neg Nat \with { zero => pos zero } 

Diese Definition besagt, dass ganze Zahlen aus zwei Kopien des Typs natürlicher Zahlen bestehen, in denen "positive" und "negative" Nullen identifiziert werden. Eine solche Definition ist viel praktischer als die Definition aus der Standard-Coq-Bibliothek, bei der die „negative Kopie“ natürlicher Zahlen „um eins verschoben“ werden muss, damit sich diese Kopien nicht überschneiden (es ist viel bequemer, wenn die Notation neg 1 die Zahl -1, nicht -2 bedeutet). .

Wir haben nichts über den Algorithmus zum Ableiten von Prädikativ- und Homotopieebenen in Klassen und deren Instanzen gesagt. Wir haben auch die Art des Intervalls I kaum erwähnt, obwohl es eine Schlüsselrolle in der Theorie der Typen mit Intervallen spielt, die die logische Grundlage von Arend sind. Um zu verstehen, wie wichtig dieser Typ ist, muss erwähnt werden, dass in Arend die Typgleichheit durch das Konzept eines Intervalls definiert wird. , , , (.. ).

: , HoTT JetBrains Research.

Source: https://habr.com/ru/post/de470632/


All Articles