Vedi questa risposta StackOverflow riguardante l'inferenza del tipo di Go. Non ho familiarità con Go me, ma sulla base di questa risposta sembra una "deduzione di tipo" a senso unico (per prendere in prestito qualche teminologia C ++). Significa che se hai:
x := y + z
quindi il tipo di x
viene dedotto calcolando il tipo di y + z
, che è una cosa relativamente banale da fare per il compilatore. Per fare ciò, i tipi di y
e z
devono essere conosciuti a priori : questo può essere fatto tramite annotazioni di tipo o desunte dai letterali a loro assegnati.
Al contrario, la maggior parte dei linguaggi funzionali ha un'inferenza di tipo che usa tutte le informazioni possibili all'interno di un modulo (o funzione, se l'algoritmo di inferenza è locale) per derivare il tipo di variabili. Gli algoritmi di inferenza complicati (come Hindley-Milner) spesso implicano una qualche forma di tipo unificazione (un po 'come risolvere equazioni) dietro le quinte. Ad esempio, in Haskell, se scrivi:
let x = y + z
allora Haskell può dedurre il tipo non solo x
ma anche y
e z
semplicemente basandosi sul fatto che stai eseguendo l'aggiunta su di essi. In questo caso:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(La minuscola a
qui indica un tipo polimorfico , spesso chiamato "generici" in altri linguaggi come il C ++. La parte Num a =>
è un vincolo per indicare che il supporto di tipo a
abbia qualche nozione di addizione.)
Ecco un esempio più interessante: il combinatore a virgola fissa che consente di definire qualsiasi funzione ricorsiva:
let fix f = f (fix f)
Notate che da nessuna parte abbiamo specificato il tipo di f
, né abbiamo specificato il tipo di fix
, tuttavia il compilatore Haskell può automaticamente capire che:
f :: t -> t
fix :: (t -> t) -> t
Questo dice che:
- Il parametro
f
deve essere una funzione da un tipo arbitrario t
allo stesso tipo t
.
-
fix
è una funzione che riceve un parametro di tipo t -> t
e restituisce un risultato di tipo t
.