Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Una anotación de tipo flexible indica que un parámetro, variable o valor tiene un tipo compatible con un tipo especificado, donde la compatibilidad viene determinada por posición en una jerarquía orientada a objetos de clases o interfaces. Los tipos flexibles son útiles específicamente cuando no se produce la conversión automática a tipos superiores en la jerarquía de tipos, pero aún desea permitir que la funcionalidad funcione con cualquier tipo de la jerarquía o cualquier tipo que implemente una interfaz.
Sintaxis
#type
Observaciones
En la sintaxis anterior, el tipo representa un tipo base o una interfaz.
Un tipo flexible es equivalente a un tipo genérico que tiene una restricción que limita los tipos permitidos a tipos que son compatibles con el tipo base o de interfaz. Es decir, las dos líneas de código siguientes son equivalentes.
#SomeType
'T when 'T :> SomeType
Los tipos flexibles son útiles en varios tipos de situaciones. Por ejemplo, cuando tiene una función de orden superior (una función que toma una función como argumento), a menudo resulta útil que la función devuelva un tipo flexible. En el ejemplo siguiente, el uso de un tipo flexible con un argumento de secuencia en iterate2 permite que la función de orden superior funcione con funciones que generan secuencias, matrices, listas y cualquier otro tipo enumerable.
Tenga en cuenta las dos funciones siguientes, una de las cuales devuelve una secuencia, la otra de las cuales devuelve un tipo flexible.
let iterate1 (f : unit -> seq<int>) =
for e in f() do printfn "%d" e
let iterate2 (f : unit -> #seq<int>) =
for e in f() do printfn "%d" e
// Passing a function that takes a list requires a cast.
iterate1 (fun () -> [1] :> seq<int>)
// Passing a function that takes a list to the version that specifies a
// flexible type as the return value is OK as is.
iterate2 (fun () -> [1])
Como otro ejemplo, considere la función de biblioteca Seq.concat :
val concat: sequences:seq<#seq<'T>> -> seq<'T>
Puede pasar cualquiera de las siguientes secuencias enumerables a esta función:
- Lista de listas
- Lista de matrices
- Matriz de listas
- Matriz de secuencias
- Cualquier otra combinación de secuencias enumerables
El código siguiente usa Seq.concat para mostrar los escenarios que se pueden admitir mediante tipos flexibles.
let list1 = [1;2;3]
let list2 = [4;5;6]
let list3 = [7;8;9]
let concat1 = Seq.concat [ list1; list2; list3]
printfn "%A" concat1
let array1 = [|1;2;3|]
let array2 = [|4;5;6|]
let array3 = [|7;8;9|]
let concat2 = Seq.concat [ array1; array2; array3 ]
printfn "%A" concat2
let concat3 = Seq.concat [| list1; list2; list3 |]
printfn "%A" concat3
let concat4 = Seq.concat [| array1; array2; array3 |]
printfn "%A" concat4
let seq1 = { 1 .. 3 }
let seq2 = { 4 .. 6 }
let seq3 = { 7 .. 9 }
let concat5 = Seq.concat [| seq1; seq2; seq3 |]
printfn "%A" concat5
La salida es la siguiente.
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
En F#, como en otros lenguajes orientados a objetos, hay contextos en los que los tipos o tipos derivados que implementan interfaces se convierten automáticamente en un tipo base o tipo de interfaz. Estas conversiones automáticas se producen en argumentos directos, pero no cuando el tipo está en una posición subordinada, como parte de un tipo más complejo, como un tipo de valor devuelto de un tipo de función o como argumento de tipo. Por lo tanto, la notación de tipo flexible es principalmente útil cuando el tipo al que se aplica forma parte de un tipo más complejo.