Inferencia de tipos
En este tema se describe la forma en que el compilador de F# realiza la inferencia de los tipos de valores, variables, parámetros y valores devueltos.
Inferencia de tipos en general
El concepto de inferencia de tipos consiste en que no es necesario especificar los tipos de construcciones de F#, excepto cuando el compilador no puede deducir el tipo de forma concluyente. El hecho de omitir información de tipo explícita no significa que F# sea un lenguaje con tipo dinámico o que los valores de F# estén débilmente tipados. F# es un lenguaje con tipo estático, lo que significa que el compilador deduce un tipo exacto para cada construcción durante la compilación. Si no hay suficiente información para que el compilador deduzca los tipos de cada construcción, debe proporcionar información de tipo adicional, normalmente mediante la adición de anotaciones de tipo explícitas en algún lugar del código.
Inferencia de tipos de parámetros y valores devueltos
En una lista de parámetros, no es necesario especificar el tipo de cada parámetro. Pero F# es un lenguaje con tipo estático y, por tanto, cada valor y expresión tiene un tipo definido en tiempo de compilación. Para los tipos que no se especifican explícitamente, el compilador deduce el tipo en función del contexto. Si no se especifica el tipo, se deduce que es genérico. Si el código usa un valor de forma incoherente, de modo que no haya ningún tipo inferido único que satisfaga todos los usos de un valor, el compilador notifica un error.
El tipo de valor devuelto de una función viene determinado por el tipo de la última expresión de la función.
Por ejemplo, en el código siguiente, se deduce que los tipos de parámetro a
y b
y el tipo de valor devuelto son int
porque el literal 100
es de tipo int
.
let f a b = a + b + 100
Puede influir en la inferencia de tipos si cambia los literales. Si hace que 100
sea uint32
mediante la anexión del sufijo u
, se deduce que los tipos de a
y b
y el valor devuelto son uint32
.
También puede influir en la inferencia de tipos si usa otras construcciones que implican restricciones en el tipo, como funciones y métodos que funcionan solo con un tipo determinado.
Además, puede aplicar anotaciones de tipo explícitas a parámetros de función o método o a variables de expresiones, como se muestra en los ejemplos siguientes. Se generan errores si se producen conflictos entre restricciones diferentes.
// Type annotations on a parameter.
let addu1 (x : uint32) y =
x + y
// Type annotations on an expression.
let addu2 x y =
(x : uint32) + y
También puede especificar explícitamente el valor devuelto de una función si proporciona una anotación de tipo después de todos los parámetros.
let addu1 x y : uint32 =
x + y
Un caso habitual en el que una anotación de tipo resulta útil en un parámetro es cuando el parámetro es un tipo de objeto y usted quiere usar un miembro.
let replace(str: string) =
str.Replace("A", "a")
Generalización automática
Si el código de función no depende del tipo de un parámetro, el compilador considera que el parámetro es genérico. Esto se denomina generalización automática y puede ser una ayuda eficaz para escribir código genérico sin aumentar la complejidad.
Por ejemplo, la función siguiente combina dos parámetros de cualquier tipo en una tupla.
let makeTuple a b = (a, b)
Se deduce que el tipo es:
'a -> 'b -> 'a * 'b
Información adicional
La inferencia de tipos se describe con más detalle en la especificación del lenguaje F#.