Siehe diese StackOverflow-Antwort bezüglich der Typinferenz von Go. Ich bin mit Go selbst nicht vertraut, aber basierend auf dieser Antwort scheint es ein einseitiger "Typabzug" zu sein (um etwas C ++ - Teminologie auszuleihen). Es bedeutet, dass wenn Sie haben:
x := y + z
Dann wird der Typ von x
abgeleitet, indem der Typ von herausgefunden wird y + z
, was für den Compiler relativ trivial ist. Um dies zu tun, werden die Typen y
und z
müssen bekannt sein , a priori : dies über Typenannotationen getan werden könnte , oder von den Literalen zugewiesen , um sie zu entnehmen.
Im Gegensatz dazu haben die meisten funktionalen Sprachen eine Typinferenz, die alle möglichen Informationen innerhalb eines Moduls (oder einer Funktion, wenn der Inferenzalgorithmus lokal ist) verwendet, um den Typ der Variablen abzuleiten. Komplizierte Inferenzalgorithmen (wie Hindley-Milner) beinhalten häufig eine Form der Typvereinigung (ein bisschen wie das Lösen von Gleichungen) hinter den Kulissen. Zum Beispiel in Haskell, wenn Sie schreiben:
let x = y + z
dann kann Haskell den Typ nicht nur, x
sondern auch y
und z
einfach basierend auf der Tatsache ableiten , dass Sie eine Addition an ihnen durchführen. In diesem Fall:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(Der Kleinbuchstabe a
bezeichnet hier einen polymorphen Typ , der in anderen Sprachen wie C ++ häufig als "Generika" bezeichnet wird. Der Num a =>
Teil ist eine Einschränkung , die angibt, dass die a
Typunterstützung einen Zusatzbegriff hat.)
Hier ist ein interessanteres Beispiel: Der Festkomma-Kombinator, mit dem jede rekursive Funktion definiert werden kann:
let fix f = f (fix f)
Beachten Sie, dass wir f
weder den Typ noch den Typ angegeben haben fix
, der Haskell-Compiler jedoch automatisch Folgendes herausfinden kann:
f :: t -> t
fix :: (t -> t) -> t
Dies sagt, dass:
- Der Parameter
f
muss eine Funktion von einem beliebigen Typ t
zum selben Typ sein t
.
fix
ist eine Funktion, die einen Parameter vom Typ Typ empfängt t -> t
und ein Ergebnis vom Typ zurückgibt t
.
x
,y
,z
ist der gleicheNum
eric Art, aber sie können immer noch seineInteger
s,Double
s,Ratio Integer
s ... Haskell ist bereit , eine willkürliche Wahl zwischen numerischen Typen zu machen, aber nicht für anderen typeclasses.Die Typinferenz in Go ist äußerst begrenzt und äußerst einfach. Es funktioniert nur in einem Sprachkonstrukt (Variablendeklaration) und nimmt einfach den Typ der rechten Seite und verwendet ihn als Typ für die Variable auf der linken Seite.
Die Typinferenz in Haskell kann überall verwendet werden. Sie kann verwendet werden, um die Typen für das gesamte Programm abzuleiten. Es basiert auf der Vereinheitlichung, was bedeutet, dass (konzeptionell) alle Typen "auf einmal" abgeleitet werden und sich gegenseitig beeinflussen können: In Go können Typinformationen nur von der rechten Seite einer Variablendeklaration nach links fließen. Seite, niemals in die andere Richtung und niemals außerhalb einer Variablendeklaration; In Haskell fließen Typinformationen frei in alle Richtungen durch das gesamte Programm.
Das Typensystem von Haskell ist jedoch so leistungsfähig, dass die Typinferenz tatsächlich nicht auf einen Typ schließen kann (oder genauer gesagt: Es müssen Einschränkungen eingeführt werden, damit ein Typ immer abgeleitet werden kann). Das Typensystem von Go ist so einfach (keine Subtypisierung, kein parametrischer Polymorphismus) und seine Folgerung so begrenzt, dass es immer erfolgreich ist.
quelle