共用方式為


彈性類型

彈性類型批注表示參數、變數或值具有與指定類型相容的類型,其中相容性取決於類別或介面物件階層中的位置。 彈性類型特別有用,特別是當類型階層中的類型自動轉換至較高類型時,您仍想要讓功能能夠使用階層中的任何類型,或實作介面的任何類型。

語法

#type

備註

在上一個語法中, type 代表基底類型或介面。

彈性型別相當於泛型型別,其條件約束會將允許的類型限制為與基底或介面類型相容的類型。 也就是說,下列兩行程式代碼是相等的。

#SomeType

'T when 'T :> SomeType

彈性類型在數種情況下很有用。 例如,當您有較高順序的函式(採用函式做為自變數的函式),讓函式傳回彈性類型通常很有用。 在下列範例中,在中使用 iterate2 彈性型別搭配時序自變數,可讓較高順序函式使用產生序列、陣列、清單和任何其他可列舉型別的函式。

請考慮下列兩個函式,其中一個會傳回序列,另一個函式會傳回彈性類型。

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])

另一個範例是,請考慮 Seq.concat 連結庫函式:

val concat: sequences:seq<#seq<'T>> -> seq<'T>

您可以將下列任一可列舉序列傳遞至此函式:

  • 清單清單
  • 陣列清單
  • 清單陣列
  • 序列陣列
  • 可列舉序列的任何其他組合

下列程式代碼使用 Seq.concat 來示範您可以使用彈性類型來支援的案例。

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

輸出如下。

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; ...]

在 F# 中,如同其他面向物件語言,有一個內容是實作介面的衍生型別或型別會自動轉換成基底類型或介面類型。 這些自動轉換會在直接自變數中發生,但不是當類型位於次級位置時,例如函式型別的傳回型別,或做為類型自變數的一部分。 因此,當您套用彈性類型表示法的類型是較複雜類型的一部分時,彈性型別表示法主要很有用。

另請參閱