フレキシブル型

"フレキシブル型の注釈" は、パラメーター、変数、または値の型と、指定した型の間に互換性があることを示します。互換性は、クラスまたはインターフェイスのオブジェクト指向の階層における位置によって決まります。 フレキシブル型は、型階層の上位にある型への自動変換は行われないが、階層内の任意の型、またはインターフェイスを実装する任意の型で機能できるようにしたい場合に特に便利です。

構文

#type

解説

前の構文で、type は基本データ型またはインターフェイスを表します。

フレキシブル型は、許可される型を基本データ型またはインターフェイス型と互換性のある型に制限する制約を持つジェネリック型に相当します。 つまり、次の 2 つのコード行は同等です。

#SomeType

'T when 'T :> SomeType

フレキシブル型は、さまざまな状況で役立ちます。 たとえば、高階関数 (関数を引数として受け取る関数) がある場合、通常、関数でフレキシブル型を返すようにすると便利です。 次の例では、iterate2 のシーケンス引数でフレキシブル型を使用することにより、高階関数で、シーケンス、配列、リスト、およびその他の列挙可能な型を生成する関数を使用できます。

次の 2 つの関数について考えてみます。1 つはシーケンスを返し、もう 1 つはフレキシブル型を返します。

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

もう 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# の場合、他のオブジェクト指向言語と同様に、派生型またはインターフェイスを実装する型が基本データ型またはインターフェイス型に自動的に変換されるコンテキストがあります。 これらの自動変換は、直接引数では行われますが、関数型の戻り値の型などのより複雑な型の一部として、または型引数として、型が下位の位置にある場合は行われません。 したがって、フレキシブル型の表記は、それを適用している型がより複雑な型の一部である場合に、主に役立ちます。

関連項目