Könnte Hindley-Milner-Inferenz für die Sprache Go funktionieren?

22

Ich habe gelesen, dass Hindley-Milner nicht mit Typsystemen arbeitet, die Unterklassen haben, und es gibt andere Typsystemfunktionen, die ebenfalls nicht gut damit funktionieren. Go hat derzeit nur sehr eingeschränkte Typrückschlüsse im :=Operator. Go hat jedoch keine Unterklassen im herkömmlichen Sinne, sondern nur Schnittstellen, die Haskells Typklassen sehr ähnlich sehen und mit Hindley-Milner-Inferenz gut funktionieren.

Könnte die Hindley-Milner-Folgerung für Go im Prinzip genauso funktionieren wie für Haskell? Oder hat Go andere Funktionen, die es kaputt machen? (Andererseits hat Haskell auch einige Funktionen, die mit Hindly-Milner nicht funktionieren. Wenn Sie diese verwenden, müssen Sie diese Teile Ihres Programms manuell eingeben.)

JanKanis
quelle

Antworten:

35

Die Inferenz vom Hindley-Milner-Typ wird für Systeme vom Hindley-Milner-Typ verwendet, eine Einschränkung von Systemen vom System-F-Typ. Das interessante Merkmal von HM-Typ-Systemen ist, dass sie einen parametrischen Polymorphismus (auch bekannt als Generika) haben. Dies ist das größte Systemmerkmal, das Golang ablehnt.

Mit dieser frustrierenden Einschränkung ist eine Inferenz im HM-Stil unmöglich. Schauen wir uns den untypisierten Code an:

func f(a) {
  return a.method()
}

Was ist die Art von f? Wir können feststellen , dass amuss eine Methode haben, so konnten wir eine anonyme Schnittstelle benutzen func f(a interface { method() ??? }) ???. Wir haben jedoch keine Ahnung, was der Rückgabetyp ist. Mit Typvariablen können wir den Typ als deklarieren

func f[T](a interface{ method() T }) T

Da Go jedoch keine Typvariablen hat, funktioniert dies nicht. Während implizite Interfaces einige Aspekte der Typinferenz vereinfachen, können wir den Rückgabetyp eines Funktionsaufrufs jetzt nicht herausfinden. Das HM-System erfordert, dass alle Funktionen deklariert und nicht impliziert werden, und jeder Name kann nur einen einzigen Typ haben (wohingegen Go-Methoden unterschiedliche Typen in unterschiedlichen Schnittstellen haben können).

Stattdessen erfordert Go, dass Funktionen immer vollständig deklariert sind, Variablen jedoch die Verwendung von Typinferenz ermöglichen. Dies ist möglich, weil die rechte Seite einer Zuweisung variable := expressionzu diesem Zeitpunkt des Programms bereits einen bekannten Typ hat. Diese Art der Typinferenz ist einfach, korrekt und linear.

  • Der Typ einer Variablen ist zum Zeitpunkt der Deklaration sofort bekannt, wohingegen HM-Inferenz möglicherweise zuerst das gesamte Programm typüberprüfen muss. Dies wirkt sich auch spürbar auf die Qualität der Fehlermeldungen aus.
  • Der Typinferenzansatz von Go wählt immer den spezifischsten Typ für eine Variable aus, im Gegensatz zu HM, das den allgemeinsten Typ auswählt. Dies funktioniert auch bei impliziten Go-Schnittstellen problemlos mit Subtyping.
amon
quelle
24
@bishop Es ist "begründet" für unendlich kleine Werte von "Grund".
Hobbs
18
@bishop Nachdem ich Compiler-Arbeiten in generischen Sprachen durchgeführt habe, kann ich dem zustimmen: Es ist schwierig zu implementieren, ohne die Implementierung wesentlich zu komplizieren. Ich würde sogar "schwierig" durch "unmöglich" ersetzen. Das ist jedoch nicht der Punkt; der Punkt ist, ist es die zusätzliche Komplikation wert? Und die Antwort an alle, die mit und ohne Generika gearbeitet haben, lautet offensichtlich "Ja, definitiv!" Ich muss voll und ganz der Behauptung zustimmen, dass es idiotisch ist, Generika nicht einzuführen, weil "oh nein, Komplexität".
Mason Wheeler
18
Dies ist auch der Grund, warum Go-Entwickler so tun, als sei FP aller Art schlecht. Go verfügt über erstklassige Funktionen mit lexikalischem Verschluss, und damit die Fähigkeit , Funktionen höheren Ordnung zu schaffen, aber es ist unmöglich , sie zu jedem guten Gebrauch zu setzen , weil die Typen solcher Grundfunktionen wie map, filterund reducealle sind unaussprechlich innerhalb Gos sehr begrenzt Typ System.
Hobbs
9
@hobbs And Go könnte eine wirklich nette Sprache sein, wenn das behoben wäre, aber stattdessen müssen die Leute Bibliotheken der allgemeinen Generation wie gengenundgonerics
cat
14
@cat Es ist eine Schande. Auf den ersten Blick scheint Go eine großartige Sprache voller großartiger Ideen zu sein, aber dann merkt man, dass es keine Vererbung und keinen Polymorphismus gibt, so dass man OOP nicht gut machen kann, und es gibt keine Generika, so dass man FP nicht gut machen kann, und Sie starrt ausdruckslos auf den Bildschirm und fragt: "Wie genau soll diese Sprache dann verwendet werden?!?"
Mason Wheeler