Inferência de tipos
Este tópico descreve como o compilador do F# infere os tipos de valores, variáveis, parâmetros e valores de retorno.
Inferência de tipos em geral
A ideia da inferência de tipo é que você não precisa especificar os tipos de construções do F#, exceto quando o compilador não puder deduzir o tipo de forma conclusiva. Omitir informações de tipo explícito não significa que F# é uma linguagem tipada dinamicamente ou que os valores em F# são fracamente tipados. F# é uma linguagem tipada estaticamente, o que significa que o compilador deduz um tipo exato para cada construção durante a compilação. Se não houver informações suficientes para o compilador deduzir os tipos de cada construção, você deverá fornecer informações de tipo adicionais, geralmente adicionando anotações de tipo explícitas em algum lugar no código.
Inferência de Tipos de Parâmetro e Retorno
Em uma lista de parâmetros, você não precisa especificar o tipo de cada parâmetro. E, no entanto, F# é uma linguagem de tipagem estática e, portanto, cada valor e expressão tem um tipo definido em tempo de compilação. Para os tipos que você não especifica explicitamente, o compilador infere o tipo com base no contexto. Se o tipo não for especificado de outra forma, é inferido como genérico. Se o código usar um valor de forma inconsistente, de forma que não haja um único tipo inferido que satisfaça todos os usos de um valor, o compilador relatará um erro.
O tipo de retorno de uma função é determinado pelo tipo da última expressão na função.
Por exemplo, no código a seguir, os tipos de parâmetro a
e b
o tipo de retorno são todos inferidosint
porque o literal 100
é do tipo int
.
let f a b = a + b + 100
Você pode influenciar a inferência de tipo alterando os literais. Se você fizer o 100
a uint32
anexando o sufixo u
, os tipos de a
, b
e o valor de retorno serão inferidos como uint32
.
Você também pode influenciar a inferência de tipo usando outras construções que implicam restrições no tipo, como funções e métodos que funcionam apenas com um tipo específico.
Além disso, você pode aplicar anotações de tipo explícitas a parâmetros de função ou método ou a variáveis em expressões, conforme mostrado nos exemplos a seguir. Ocorrem erros se ocorrerem conflitos entre diferentes restrições.
// Type annotations on a parameter.
let addu1 (x : uint32) y =
x + y
// Type annotations on an expression.
let addu2 x y =
(x : uint32) + y
Você também pode especificar explicitamente o valor de retorno de uma função fornecendo uma anotação de tipo após todos os parâmetros.
let addu1 x y : uint32 =
x + y
Um caso comum em que uma anotação de tipo é útil em um parâmetro é quando o parâmetro é um tipo de objeto e você deseja usar um membro.
let replace(str: string) =
str.Replace("A", "a")
Generalização automática
Se o código da função não depende do tipo de um parâmetro, o compilador considera o parâmetro genérico. Isso é chamado de generalização automática e pode ser uma ajuda poderosa para escrever código genérico sem aumentar a complexidade.
Por exemplo, a função a seguir combina dois parâmetros de qualquer tipo em uma tupla.
let makeTuple a b = (a, b)
O tipo é inferido para ser
'a -> 'b -> 'a * 'b
Informações adicionais
A inferência de tipo é descrita com mais detalhes na Especificação de linguagem do F#.