Inferencia de tipos (F#)
En este tema se describe cómo el compilador de F# realiza la inferencia de los tipos de valor, variables, parámetros y valores devueltos.
Inferencia de tipos en general
La inferencia de tipos se ha diseñado para que no sea necesario especificar los tipos de las construcciones de F# excepto cuando el compilador no sea capaz de deducirlos de forma concluyente.La omisión de la información de tipos explícita no significa que F# sea un lenguaje de tipos dinámicos ni que los valores de F# estén débilmente tipados.F# es un lenguaje de tipos estáticos, lo que significa que el compilador deduce un tipo exacto para cada construcción durante la compilación.Si no hay información suficiente para que el compilador deduzca los tipos de cada construcción, se debe proporcionar información de tipos adicional, lo que suele hacerse agregando anotaciones de tipo explícitas en alguna parte del código.
Inferencia de tipos de parámetros y valores devueltos
En una lista de parámetros, no es preciso especificar el tipo de cada parámetro.No obstante, al ser F# un lenguaje de tipos estáticos, cada valor y expresión tiene un tipo definido en tiempo de compilación.Para aquellos tipos que no se especifican explícitamente, el compilador realiza la inferencia de tipos basándose en el contexto.Si el tipo no se especifica de otro modo, la inferencia de tipos da como resultado que es genérico.Si el código utiliza un valor de manera incoherente, de tal forma que ninguno de los tipos resultantes de la inferencia de tipos satisfaga todos los usos de un valor, el compilador notifica un error.
El tipo de la última expresión de una función determina el tipo de valor devuelto de la función.
Por ejemplo, en el código siguiente, la inferencia de tipos considera que los tipos de parámetro a y b, así como el tipo de valor devuelto, son int porque el literal 100 es del tipo int.
let f a b = a + b + 100
Se puede influir en la inferencia de tipos cambiando los literales.Si convierte el 100 en un valor del tipo uint32 anexándole el sufijo u, la inferencia de los tipos de a, de b y del valor devuelto dará como resultado que son del tipo uint32.
También se puede influir en la inferencia de tipos utilizando otras construcciones que impliquen restricciones del tipo, como las funciones y los métodos que solo funcionan con un tipo determinado.
Asimismo, se pueden aplicar anotaciones de tipo explícitas a los parámetros de las funciones o los métodos, o a las variables en las expresiones, como se muestra en los ejemplos siguientes.Se producen errores si hay algún conflicto 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 se puede especificar explícitamente el valor devuelto de una función proporcionando una anotación de tipo después de todos los parámetros.
let addu1 x y : uint32 =
x + y
Una anotación de tipo suele resultar útil cuando el parámetro es un tipo de objeto y se desea utilizar un miembro.
let replace(str: string) =
str.Replace("A", "a")
Generalización automática
Si el código de la 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 resultar muy 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)
Según la inferencia de tipos, 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#.