Geben Sie Inferenz ein

Geben Sie Inferenz ein bezieht sich auf die automatische Erkennung der Typ eines Ausdrucks in a formelle Sprache. Diese beinhalten Programmiersprachen und mathematisch Typsysteme, aber auch natürliche Sprachen in einigen Zweigen von Informatik und Linguistik.

Nichttechnische Erklärung

Typen in einer allgemeinen Sicht können einer benannten Verwendung zugeordnet werden, mit der die Aktivitäten für ein Objekt dieses Typs vorgeschlagen und einschränken. Viele Substantive in der Sprache geben solche Verwendungen an. Zum Beispiel das Wort Leine zeigt eine andere Verwendung an als das Wort Linie. Etwas nennen a Tisch zeigt eine andere Bezeichnung an als es zu nennen Brennholz, obwohl es wesentlich dasselbe sein mag. Während ihre materiellen Eigenschaften die Dinge für einige Zwecke verwendbar machen, sind sie auch bestimmte Bezeichnungen unterliegen. Dies ist insbesondere in abstrakten Feldern der Fall, nämlich Mathematik und Informatik, in denen das Material schließlich nur Bits oder Formeln besteht.

Um unerwünschte, aber materiell mögliche Verwendungen auszuschließen, wird das Konzept der Typen in vielen Variationen definiert und angewendet. In Mathematik, Russells Paradox löste frühe Versionen der Typtheorie aus. In Programmiersprachen sind typische Beispiele "Typ Fehler", z. Bestellen Sie einen Computer, um Werte zu summieren, die keine Zahlen sind. Das Ergebnis wäre zwar wesentlich möglich, wäre zwar nicht mehr sinnvoll und möglicherweise katastrophal für den Gesamtprozess.

In einem TypisierungEin Ausdruck ist gegen einen Typ. Zum Beispiel, , , und sind alle getrennte Begriffe mit dem Typ für natürliche Zahlen. Traditionell folgt der Ausdruck von einem Dickdarm und seinem Typ, wie z. . Dies bedeutet, dass der Wert ist vom Typ . Dieses Formular wird auch verwendet, um neue Namen zu deklarieren, z. Ähnlich wie die Einführung eines neuen Charakters in eine Szene der Worte "Detective Decker".

Im Gegensatz zu einer Geschichte, in der sich die Bezeichnungen langsam entfalten, müssen sich die Objekte in formalen Sprachen oft mit ihrem Typ von Anfang an definiert werden. Wenn die Ausdrücke mehrdeutig sind, sind möglicherweise Typen erforderlich, um die beabsichtigte Verwendung explizit zu gestalten. Zum Beispiel der Ausdruck könnte einen Typ haben könnte aber auch als rationale oder reelle Zahl oder sogar als einfacher Text gelesen werden.

Infolgedessen können Programme oder Beweise mit Typen so belastet werden, dass es wünschenswert ist, sie aus dem Kontext abzuleiten. Dies kann möglich sein, indem die Verwendungen von Untyped Expression (einschließlich undefinierter Namen) gesammelt werden. Wenn zum Beispiel ein noch undefinierter Name n wird in einem Ausdruck verwendet , man könnte zu dem Schluss kommen, das n ist mindestens eine Zahl. Der Prozess des Abzugs des Typs aus einem Ausdruck und seines Kontextes ist Geben Sie Inferenz ein.

Im Allgemeinen haben nicht nur Objekte, sondern auch Aktivitäten Typen und können einfach durch ihre Verwendung eingeführt werden. Für eine Star Trek -Geschichte könnte eine so unbekannte Aktivität "strahlend" sein, die aus dem Fluss der Geschichte nur ausgeführt und nie offiziell eingeführt wird. Trotzdem kann man seinen Typ (Transport) nach dem, was passiert, ableiten. Darüber hinaus können sowohl Objekte als auch Aktivitäten aus ihren Teilen konstruiert werden. In einer solchen Umgebung kann die Typinferenz nicht nur komplexer, sondern auch hilfreicher werden, da eine vollständige Beschreibung von allem in einer komponierten Szene sammeln kann, während gleichzeitig widersprüchliche oder unbeabsichtigte Verwendungen erfasst werden können.

Typ-Überprüfung gegen Typ-Inferenz

Bei einer Typisierung ist ein Ausdruck E gegen einen Typ T, der formell als E: T geschrieben ist. Normalerweise ist ein Typing nur in einem Kontext sinnvoll, der hier weggelassen wird.

In dieser Umgebung sind die folgenden Fragen von besonderem Interesse:

  1. E: T? In diesem Fall werden sowohl ein Ausdruck E als auch ein Typ t angegeben. Ist E wirklich ein t? Dieses Szenario ist als bekannt als Typ Überprüfung.
  2. E: _? Hier ist nur der Ausdruck bekannt. Wenn es eine Möglichkeit gibt, einen Typ für E abzuleiten, dann haben wir erreicht Geben Sie Inferenz ein.
  3. _ : T? Andersherum. Gibt es einen Ausdruck dafür oder hat der Typ keine Werte? Gibt es ein Beispiel für ein t?

Für die Einfach tippte Lambda -Kalkülalle drei Fragen sind entschlossen. Die Situation ist nicht so bequem, wenn ausdruckswertere Typen zulässig sind.

Typen in Programmiersprachen

Typen sind eine Funktion, die in einigen vorhanden ist stark statisch typisiert Sprachen. Es ist oft charakteristisch von Funktionale Programmiersprachen Im Algemeinen. Einige Sprachen, die Typ -Inferenz enthalten C ++ 11,[1] C# (Beginnend mit Version 3.0), Kapelle, Sauber, Kristall, D, F#,[2] Freilasisch, gehen, Haskell, Java (Beginnend mit Version 10), Julia,[3] Kotlin,[4] Ml, Nim, Ocaml, Opa, Q#, Rpython, Rost,[5] Scala,[6] Schnell,[7] Typoskript,[8] Vala,[9] Pfeil,[10] und Visual Basic[11] (Beginnend mit Version 9.0). Die Mehrheit von ihnen verwendet eine einfache Form der Typinferenz; das Hindley-Milner-System kann eine umfassendere Entstehungsteilung liefern. Die Fähigkeit, Typen zu schließen, erleichtert automatisch viele Programmieraufgaben, sodass der Programmierer frei weggelassen wird Geben Sie Anmerkungen ein während dennoch die Typ -Überprüfung erlaubt.

In einigen Programmiersprachen haben alle Werte a Datentyp ausdrücklich deklariert bei Zeit kompilierenBegrenzung der Werte, die ein bestimmter Ausdruck annehmen kann Laufzeit. Zunehmend, Just-in-Time-Zusammenstellung verwischt die Unterscheidung zwischen Laufzeit und Kompilierzeit. Historisch gesehen sind diese Sprachen jedoch historisch, wenn der Wert eines Wertes nur zur Laufzeit bekannt ist dynamisch getippt. In anderen Sprachen ist die Art eines Ausdrucks nur bei bekannt Zeit kompilieren; Diese Sprachen sind statisch typisiert. In den meisten statisch typisierten Sprachen die Eingabe- und Ausgangstypen von Funktionen und Lokale Variablen Normalerweise muss explizit durch Typanmerkungen bereitgestellt werden. Zum Beispiel in C:

int füge eins hinzu(int x) {   int Ergebnis; / * Deklare Integer -Ergebnis */   Ergebnis = x + 1;   Rückkehr Ergebnis; } 

Das Unterschrift dieser Funktionsdefinition, int add_one (int x), erklärt das füge eins hinzu ist eine Funktion, die ein Argument nimmt, eine ganze Zahlund gibt eine Ganzzahl zurück. int Ergebnis; erklärt, dass die lokale Variable Ergebnis ist eine Ganzzahl. In einer hypothetischen Sprache, die den Typ -Inferenz unterstützt, kann der Code stattdessen so geschrieben werden:

füge eins hinzu(x) {  var Ergebnis;  / * Variable Ergebnis vom Typ abgeleitet */  var Ergebnis2; / * Variable Ergebnis vom Typ abgeleitetes Typ 2 */  Ergebnis = x + 1;  Ergebnis2 = x + 1.0;  / * Diese Zeile funktioniert nicht (in der vorgeschlagenen Sprache) */  Rückkehr Ergebnis; } 

Dies ist identisch mit der Art und Weise, wie Code in der Sprache geschrieben ist Pfeilaußer dass es einigen zusätzlichen Einschränkungen unterliegt, wie nachstehend beschrieben. Es wäre möglich zu sein schließen Die Arten aller Variablen zur Kompilierungszeit. Im obigen Beispiel würde der Compiler das schließen Ergebnis und x haben Typ Ganzzahl seit der Konstante 1 ist Typ Ganzzahl und deshalb das füge eins hinzu ist eine Funktion int -> int. Die Variable Ergebnis2 Wird nicht auf legale Weise verwendet, daher würde es keinen Typ haben.

In der imaginären Sprache, in der das letzte Beispiel geschrieben ist, würde der Compiler davon ausgehen, dass ohne Informationen im Gegenteil, + Nimmt zwei Ganzzahlen und gibt eine Ganzzahl zurück. (So ​​funktioniert es zum Beispiel in Ocaml.) Daraus kann der Typ -Inferenzer darauf schließen, dass die Art von x + 1 ist eine Ganzzahl, was bedeutet Ergebnis ist eine Ganzzahl und damit der Rückgabewert von füge eins hinzu ist eine Ganzzahl. In ähnlicher Weise seit + erfordert, dass beide Argumente vom gleichen Typ sein, x muss eine Ganzzahl sein, und damit, füge eins hinzu Akzeptiert eine ganze Zahl als Argument.

In der nachfolgenden Linie, jedoch, Ergebnis2 wird durch Hinzufügen einer Dezimalzahl berechnet 1.0 mit schwimmende Punktarithmetikeinen Konflikt in der Verwendung von x Sowohl für Ganzzahl- als auch für schwimmende Punkte. Der korrekte Algorithmus vom Typ-Inferenz für eine solche Situation war bekannt seit 1958 und es ist bekannt, dass es seit 1982 korrekt ist. Es geht die vorherigen Schlussfolgerungen erneut und verwendet von Anfang an den allgemeinsten Typ: In diesem Fall Gleitpunkt. Dies kann jedoch nachteilige Auswirkungen haben, beispielsweise kann es mit einem ganzzahligen Typ mit einem Schwimmpunkt von Anfang an Präzisionsprobleme einführen, beispielsweise mit einem Gleitpunkt von Anfang an Präzisionsprobleme aufzunehmen.

Häufig werden jedoch entartete Algorithmen vom Typ-Inferenz verwendet, die nicht zurückverfolgen und stattdessen eine Fehlermeldung in einer solchen Situation erzeugen. Dieses Verhalten kann vorzuziehen sein, da die Typinferenz möglicherweise nicht immer algorithmisch neutral ist, wie durch das vorherige Problem der schwimmenden Punkt-Präzision dargestellt.

Ein Algorithmus der Zwischen allgemeinheit erklärt implizit implizit Ergebnis2 als schwimmende Punktvariable, und der Zugabe konvertiert implizit x zu einem schwebenden Punkt. Dies kann korrekt sein, wenn die aufrufenden Kontexte niemals ein schwimmendes Punktargument liefern. Eine solche Situation zeigt den Unterschied zwischen Geben Sie Inferenz ein, was nicht beinhaltet Typumwandlung Typ, und implizite Typumwandlung, der Daten zu einem anderen Datentyp erzwingt, oft ohne Einschränkungen.

Schließlich ist ein signifikanter Nachteil des komplexen Algorithmus vom Typ In-Inferenz, dass die resultierende Auflösung der Typ-Inferenz für den Menschen nicht offensichtlich sein wird (insbesondere wegen der Rückverfolgung), was nachteilig sein kann, da der Code in erster Linie für den Menschen verständlich ist.

Die jüngste Entstehung von Just-in-Time-Zusammenstellung Ermöglicht hybride Ansätze, bei denen die Art der Argumente, die durch den verschiedenen aufrufenden Kontext geliefert werden, zur Kompilierungszeit bekannt ist und eine große Anzahl kompilierter Versionen derselben Funktion erzeugen kann. Jede kompilierte Version kann dann für eine andere Reihe von Typen optimiert werden. Zum Beispiel ermöglicht die JIT -Zusammenstellung mindestens zwei kompilierte Versionen von füge eins hinzu:

Eine Version, die eine Ganzzahleingabe akzeptiert und implizite Typkonvertierung verwendet.
Eine Version, die eine Gleitkomma-Nummer als Eingabe akzeptiert und überall schwimmende Punktanweisungen verwendet.

Technische Beschreibung

Typ -Inferenz ist die Fähigkeit, den Typ eines Ausdrucks zur Kompilierungszeit automatisch, entweder teilweise oder vollständig abzuleiten. Der Compiler kann oft auf die Art einer Variablen oder der Variablen schließen Geben Sie Signatur ein einer Funktion, ohne explizite Typanmerkungen zu verabschieden. In vielen Fällen ist es möglich, Typ Anmerkungen aus einem Programm vollständig wegzulassen, wenn das Typ -Inferenzsystem robust genug ist oder das Programm oder die Sprache einfach genug ist.

Um die Informationen zu erhalten, die erforderlich sind, um auf den Typ eines Ausdrucks zu schließen, sammelt der Compiler diese Informationen entweder als Aggregat und anschließende Verringerung der für seine Subenexpressionen angegebenen Typ -Anmerkungen oder durch ein implizites Verständnis der Art verschiedener Atomwerte (z. B. wahr: Bool; 42: Ganzzahl; 3.14159: real; etc.). Durch die Erkennung der eventuellen Reduktion von Ausdrücken auf implizit typisierte atomare Werte kann der Compiler für einen Typ, der Sprache schließt, ein Programm ohne Typ Anmerkungen vollständig kompilieren.

In komplexen Formen von higher-order programming und PolymorphismusEs ist nicht immer möglich, dass der Compiler so viel schließt, und gelegentlich sind Typ Anmerkungen zur Disambiguierung erforderlich. Zum Beispiel geben Sie Inferenz mit Polymorphe Rekursion Es ist bekannt, dass es unentscheidbar ist. Darüber hinaus können explizite Typanmerkungen verwendet werden, um den Code zu optimieren, indem der Compiler gezwungen wird, einen spezifischeren (schnelleren/kleineren) Typ zu verwenden, als er abgeleitet hatte.[12]

Einige Methoden zur Typinferenz basieren auf Einschränkung Zufriedenheit[13] oder Befriedigungsmodulo -Theorien.[14]

Beispiel

Als Beispiel die Haskell Funktion Karte wendet eine Funktion auf jedes Element einer Liste an und kann definiert werden als:

Karte f [] = [] Karte f (Erste:sich ausruhen) = f Erste : Karte f sich ausruhen 

Geben Sie Inferenz auf dem ein Karte Die Funktion verläuft wie folgt. Karte ist eine Funktion von zwei Argumenten, daher ist sein Typ beschränkt, von der Form zu sein a → b → c. In Haskell die Muster [] und (Erstens: Ruhe) Stimmen Sie immer Listen ab, daher muss das zweite Argument ein Listentyp sein: B = [D] für irgendeine Art d. Sein erstes Argument f ist angewandt zum Argument Erste, die einen Typ haben müssen d, entsprechend dem Typ im Listenargument, also f :: d → e (:: bedeutet "ist vom Typ") für einen Typ e. Der Rückgabewert von Karte fschließlich ist eine Liste von was auch immer f produziert, so [e].

Das Zusammenstellen der Teile führt zu Karte :: (d → e) → [d] → [e]. Nichts ist etwas Besonderes an den Typvariablen, daher kann es als neu gestaltet werden

Karte :: (a  b)  [a]  [b] 

Es stellt sich heraus, dass dies auch der allgemeinste Typ ist, da keine weiteren Einschränkungen gelten. Wie die abgeleitete Art von Karte ist parametrisch polymorphdie Art der Argumente und Ergebnisse von f werden nicht abgeleitet, sondern als Typvariablen gelassen, und so Karte Kann auf Funktionen und Listen verschiedener Typen angewendet werden, solange die tatsächlichen Typen in jedem Aufruf übereinstimmen.

Hindley -Milner -Inferenzalgorithmus vom Typ Hindley -Milner

Der Algorithmus, der zum ersten Mal zur Durchführung von Typinferenz verwendet wird, wird jetzt informell als Hindley -Milner -Algorithmus bezeichnet, obwohl der Algorithmus Damas und Milner ordnungsgemäß zugeordnet werden sollte.[15]

Der Ursprung dieses Algorithmus ist der Typ -Inferenzalgorithmus für die Einfach tippte Lambda -Kalkül das wurde von entwickelt von Haskell Curry und Robert Feys 1958. 1969 J. Roger Hindley erweiterte diese Arbeit und bewies, dass ihr Algorithmus immer den allgemeinsten Typ abmachte. 1978 Robin Milner,[16] unabhängig von Hindleys Arbeit lieferte einen gleichwertigen Algorithmus, Algorithmus w. 1982 Luis Damas[15] Schließlich bewiesen, dass Milners Algorithmus vollständig ist und erweitert ihn, um Systeme mit polymorphen Referenzen zu unterstützen.

Nebenwirkungen der allgemeinsten Art

Durch das Design führt die Inferenz vom Typ Typ, insbesondere korrekte (Backtracking), die Verwendung des am besten geeigneten Typs ein. Dies kann jedoch Auswirkungen haben, da allgemeinere Typen möglicherweise nicht immer algorithmisch neutral sind, wobei die typischen Fälle:

  • Schwimmpunkt wird als allgemeine Ganzzahltyp angesehen, während der Schwimmpunkt Präzisionsprobleme einführt
  • Variante/dynamische Typen werden als allgemeine Art von anderen Typen angesehen, die Gussregeln und -vergleiche einführen, die unterschiedlich sein könnten, beispielsweise verwenden solche Typen den '+' -Personal sowohl für numerische Ergänzungen als auch für String -Verkettungen, aber was die Operation ausgeführt wird, ist eher dynamisch als statisch bestimmt

Typeschluss für natürliche Sprachen

Typ -Inferenzalgorithmen wurden zur Analyse verwendet natürliche Sprachen sowie Programmiersprachen.[17][18][19] Typ -Inferenzalgorithmen werden auch in einigen verwendet Grammatikinduktion[20][21] und Einschränkungsbasierte Grammatik Systeme für natürliche Sprachen.[22]

Verweise

  1. ^ "Platzhaltertypspezifizierer (seit C ++ 11) - cppreference.com". en.cppreference.com. Abgerufen 2021-08-15.
  2. ^ Cartermp. "Inferenz eingeben - f#". docs.microsoft.com. Abgerufen 2020-11-21.
  3. ^ "Inferenz · Die Julia -Sprache". docs.julialang.org. Abgerufen 2020-11-21.
  4. ^ "Kotlin -Sprachspezifikation". kotlinlang.org. Abgerufen 2021-06-28.
  5. ^ "Aussagen - die Rostreferenz". doc.rustlang.org. Abgerufen 2021-06-28.
  6. ^ "Inferenz" Typ ". Scala -Dokumentation. Abgerufen 2020-11-21.
  7. ^ "Die Grundlagen - die Swift -Programmiersprache (Swift 5.5)". docs.swift.org. Abgerufen 2021-06-28.
  8. ^ "Dokumentation - Typinferenz". www.typescriptlang.org. Abgerufen 2020-11-21.
  9. ^ "Projekte/Vala/Tutorial - Gnome Wiki!". Wiki.gnome.org. Abgerufen 2021-06-28.
  10. ^ "Das Dart -Typ -System". Dart.dev. Abgerufen 2020-11-21.
  11. ^ Kathleendollard. "Lokale Typinferenz - Visual Basic". docs.microsoft.com. Abgerufen 2021-06-28.
  12. ^ Bryan O'Sullivan; Don Stewart; John Goerzen (2008). "Kapitel 25. Profiling und Optimierung". Real World Haskell. O'Reilly.
  13. ^ Talpin, Jean-Pierre und Pierre Jouvelot. "Polymorpher Typ, Region und Effektinferenz. "Journal of Functional Programing 2.3 (1992): 245-271.
  14. ^ Hassan, Mostafa; Urban, Caterina; Eilers, Marco; Müller, Peter (2018). "MaxSmt-basierter Typinferenz für Python 3". Computergestützte Überprüfung. Vorlesungsnotizen in Informatik. Vol. 10982. S. 12–19. doi:10.1007/978-3-319-96142-2_2. ISBN 978-3-319-96141-5.
  15. ^ a b Damas, Luis; Milner, Robin (1982), "Haupttypschemen für Funktionsprogramme", Popl '82: Verfahren des 9. ACM Sigplan-Sigact-Symposiums über Prinzipien der Programmiersprachen (PDF), ACM, S. 207–212
  16. ^ Milner, Robin (1978), "Eine Theorie des Typpolymorphismus in der Programmierung", Journal of Computer and System Sciences, 17 (3): 348–375, doi:10.1016/0022-0000 (78) 90014-4
  17. ^ Zentrum, Artificiał Intelligence. Parsing und Typinferenz für natürliche und Computersprachen. Diss. Stanford University, 1989.
  18. ^ Emele, Martin C. und Rémi Zajac. "Typisierte Vereinigungsgrammatiken.
  19. ^ Preschi, Remo. "Typengesteuerte natürliche Sprachanalyse. "(1988).
  20. ^ Fisher, Kathleen et al. "Fisher, Kathleen et al."Vom Schmutz bis zu Schaufeln: Vollautomatische Werkzeuggenerierung aus Ad -hoc -Daten. ACM Sigplan nennt. Vol. 43. Nr. 1. ACM, 2008.
  21. ^ Lappin, Shalom; Shieber, Stuart M. (2007). "Theorie und Praxis für maschinelles Lernen als Quelle der Einsicht in die universelle Grammatik" (PDF). Journal of Linguistics. 43 (2): 393–427. doi:10.1017/s0022226707004628.
  22. ^ Stuart M. Shieber (1992). Einschränkende Grammatikformalismen: Parsen und Typinferenz für natürliche und Computersprachen. MIT Press. ISBN 978-0-262-19324-5.

Externe Links