Compartir a través de


Inferencia de tipos

En este tema se describe cómo el compilador de F# deduce los tipos de valores, variables, parámetros y valores devueltos.

Inferencia de tipos en general

La idea de la inferencia de tipos es que no es necesario especificar los tipos de construcciones de F#, excepto cuando el compilador no puede deducir de forma concluyente el tipo. La omisión de 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 deduce los tipos de cada construcción, debe proporcionar información adicional sobre tipos, normalmente agregando anotaciones de tipo explícitas en algún lugar del código.

Inferencia de tipos de parámetro y valor devuelto

En una lista de parámetros, no es necesario especificar el tipo de cada parámetro. Y, sin embargo, F# es un lenguaje con tipo estático y, por lo tanto, cada valor y expresión tiene un tipo definido en tiempo de compilación. Para esos tipos que no especifique 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 incoherentemente, de tal manera 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 deducen todos los tipos a de parámetro y b el tipo de valor devuelto porque int el literal 100 es de tipo int.

let f a b = a + b + 100

Puede influir en la inferencia de tipos cambiando los literales. Si crea un 100uint32 objeto anexando el sufijo u, los tipos de a, by el valor devuelto se deducen como uint32.

También puede influir en la inferencia de tipos mediante 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 en expresiones, como se muestra en los ejemplos siguientes. Los errores se producen 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 proporcionando una anotación de tipo después de todos los parámetros.

let addu1 x y : uint32 =
   x + y

Un caso común en el que una anotación de tipo es útil en un parámetro es cuando el parámetro es un tipo de objeto y desea 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)

El tipo se deduce que debe ser

'a -> 'b -> 'a * 'b

Información adicional

La inferencia de tipos se describe con más detalle en la especificación del lenguaje F#.

Consulte también