共用方式為


彈性類型

「彈性型別註解」表示參數、變數或值的類型與所指定類型相容,而相容性是由類別或介面其物件導向階層中的位置所決定。 彈性類型在下列情況特別有用:如果不會自動轉換成類型階層中較高的類型,但您仍想要讓功能能夠使用階層中的任何類型或實作介面的任何類型。

語法

#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# 內容中,如同其他物件導向語言內容,衍生類型或實作介面的類型會自動轉換成基底類型或介面類型。 這些自動轉換會在直接引數中進行,但當類型位於下層位置、作為較複雜類型的一部分 (例如函式類型的傳回型別) 或作為型別引數時則否。 因此,彈性類型標記法主要適用於所要套用類型是較複雜類型之一部分的情況。

另請參閱