共用方式為


彈性型別 (F#)

「彈性型別附註」(Flexible Type Annotation) 表示參數、變數或值的型別與指定的型別相容,而相容性是由類別或介面之物件導向階層中的位置所決定。 當未發生自動轉換為型別階層中的更高型別,但您仍然要讓功能用於階層中的任何型別或實作介面的任何型別時,彈性型別特別有用。

#type

備註

在上述語法中,type 表示基底型別或介面。

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

#SomeType

'a when 'a :> 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# 的有些內容中,衍生型別或實作介面的型別會自動轉換為基底型別或介面型別。 這些自動轉換會發生於直接引數,但當型別位於附屬位置、做為較複雜型別的一部分 (例如函式型別的傳回型別) 或做為型別引數時,則不會發生。 因此,彈性型別標記法主要是在要套用的型別是較複雜型別的一部分時使用。

請參閱

參考

泛型 (F#)

其他資源

F# 語言參考