オプション (F#)
F# のオプション型は、名前付きの値または変数に、実際の値が存在しない場合があるときに使用します。 オプションには基になる型があり、その型の値を保持する場合と値がない場合があります。
解説
次のコードは、オプション型の使用例を示しています。
let keepIfPositive (a : int) = if a > 0 then Some(a) else None
値 None は、オプションに実際の値がない場合に使用されます。 それ以外の場合は、Some( ... ) 式でオプションに値を指定します。 値 Some と None は、次の exists 関数に示すように、パターン一致で役立ちます。この関数は、オプションに値がある場合は true を返し、値がない場合は false を返します。
let exists (x : int option) =
match x with
| Some(x) -> true
| None -> false
オプションの使用
オプションは、次のコードに示すように、検索で一致する結果が返されない場合によく使用されます。
let rec tryFindMatch pred list =
match list with
| head :: tail -> if pred(head)
then Some(head)
else tryFindMatch pred tail
| [] -> None
// result1 is Some 100 and its type is int option.
let result1 = tryFindMatch (fun elem -> elem = 100) [ 200; 100; 50; 25 ]
// result2 is None and its type is int option.
let result2 = tryFindMatch (fun elem -> elem = 26) [ 200; 100; 50; 25 ]
このコードでは、リストが再帰的に検索されます。 tryFindMatch 関数は、ブール値を返す述語関数 pred と検索するリストを受け取ります。 述語を満たす要素が見つかった場合は再帰が終了し、関数は Some(head) 式のオプションとして値を返します。 空のリストが一致すると、再帰は終了します。 その時点では値 head は見つかっていないので、None が返されます。
存在しない可能性もある値をコレクションで検索する多数の F# ライブラリ関数では、option 型が返されます。 慣例に基づき、これらの関数の先頭には、Seq.tryFindIndex のように、try プレフィックスが付けられます。
オプションは、値が存在しない可能性がある場合にも役立ちます。たとえば、値を作成しようとしたときに例外がスローされる可能性がある場合です。 これを次のコード例に示します。
open System.IO
let openFile filename =
try
let file = File.Open (filename, FileMode.Create)
Some(file)
with
| ex -> eprintf "An exception occurred with message %s" ex.Message
None
この例の openFile 関数は、ファイルが正常に開いた場合に File オブジェクトを返し、例外が発生した場合に None を返すため、この関数の型は string -> File option です。 状況によっては、例外を反映する代わりに例外をキャッチすることが、デザイン上の選択肢として適切でない場合があります。
オプションのプロパティとメソッド
オプション型では、次のプロパティとメソッドがサポートされます。
プロパティまたはメソッド |
型 |
説明 |
---|---|---|
'T option |
None 値を持つオプション値を作成できる静的プロパティです。 |
|
bool |
オプションの値が None の場合、true を返します。 |
|
bool |
オプションの値が None 以外の場合、true を返します。 |
|
'T option |
None 以外の値を持つオプションを作成する静的メンバーです。 |
|
'T |
基になる値を返すか、または、値が None の場合は NullReferenceException をスローします。 |
オプション モジュール
オプションに対して操作を実行するための有用な関数が含まれる、オプションというモジュールがあります。 一部の関数はプロパティの機能の繰り返しですが、関数が必要な状況では役立ちます。 Option.isSome および Option.isNone は両方とも、オプションが値を保持しているかどうかをテストするモジュール関数です。 Option.get は、値がある場合に、値を取得します。 値がない場合は、ArgumentException をスローします。
Option.bind 関数は、値がある場合に、値に対して関数を実行します。 関数は厳密に 1 つの引数を受け取り、パラメーター型はオプション型である必要があります。 この関数の戻り値は、別のオプション型です。
オプション モジュールには、リスト、配列、シーケンス、および他のコレクション型で使用できる関数に対応する関数も含まれています。 これらの関数には、Option.map、Option.iter、Option.forall、Option.exists、Option.foldBack、Option.fold、Option.count などがあります。 これらの関数を使用すると、0 個または 1 個の要素を持つコレクションのようにオプションを使用できます。 詳細および例については、「リスト」のコレクション関数の説明を参照してください。
他の型への変換
オプションは、リストまたは配列に変換できます。 これらのデータ構造のどちらにオプションを変換しても、結果のデータ構造には 0 個または 1 個の要素が含まれます。 オプションを配列に変換するには、Option.toArray を使用します。 オプションをリストに変換するには、Option.toList を使用します。