Consulte esta resposta StackOverflow sobre a inferência de tipo do Go. Eu não estou familiarizado com Go, mas com base nessa resposta, parece uma "dedução de tipo" unidirecional (para emprestar alguma teminologia em C ++). Isso significa que se você tiver:
x := y + z
então o tipo de x
é deduzido por descobrir o tipo de y + z
, o que é uma coisa relativamente trivial a ser feita pelo compilador. Para fazer isso, os tipos y
e z
precisam ser conhecidos a priori : isso pode ser feito através de anotações de tipo ou deduzido dos literais atribuídos a eles.
Por outro lado, a maioria das linguagens funcionais possui inferência de tipo que utiliza todas as informações possíveis dentro de um módulo (ou função, se o algoritmo de inferência for local) para derivar o tipo das variáveis. Algoritmos de inferência complicados (como Hindley-Milner) geralmente envolvem alguma forma de unificação de tipo (um pouco como resolver equações) nos bastidores. Por exemplo, em Haskell, se você escrever:
let x = y + z
Haskell pode inferir o tipo não apenas, x
mas também y
e z
simplesmente, com base no fato de que você está realizando adição neles. Nesse caso:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(As letras minúsculas a
aqui denotam um tipo polimórfico , geralmente chamado de "genéricos" em outros idiomas como C ++. A Num a =>
parte é uma restrição para indicar que o a
suporte ao tipo tem alguma noção de adição.)
Aqui está um exemplo mais interessante: o combinador de ponto fixo que permite definir qualquer função recursiva:
let fix f = f (fix f)
Observe que em nenhum lugar especificamos o tipo de f
, nem o tipo de fix
, mas o compilador Haskell pode descobrir automaticamente que:
f :: t -> t
fix :: (t -> t) -> t
Isto diz que:
- O parâmetro
f
deve ser uma função de algum tipo arbitrário t
para o mesmo tipo t
.
fix
é uma função que recebe um parâmetro do tipo t -> t
e retorna um resultado do tipo t
.
x
,y
,z
são o mesmoNum
tipo de eric, mas eles ainda podem serInteger
s,Double
s,Ratio Integer
s ... Haskell está disposto a fazer uma escolha arbitrária entre tipos numéricos, mas não para outros typeclasses.