F#

2009-03-08 12 views
7

のオプションの仕組みはなんですか?私はApressのエキスパートF#の本を読んでいます。おもちゃのF#ライブラリを構築する際に参考にしていますが、把握できなかった点が1つあります。これは「オプション」タイプです。F#

どのように動作し、実際の使用状況はどうですか?

答えて

19

オプションタイプは、C#で少なくともNullable<T>類似した参照タイプです。 Option<T>の値は、カプセル化された値がないことを意味するNone、またはTの特定の値を持つSomeのいずれかです。及び方法は、C#でString値がいずれか null参照である、又はは、文字列オブジェクトを参照 - これは単にC#でNullable<int>いずれかヌル値であり、又はが関連intを有している方法のようです。

オプション値を使用する場合、あなたは一般的に二つの経路指定 - 関連する値、および存在しないものがある場合のための1つを。言い換えれば、このコード:私は一般的なアイデアがあなたは(まあ、ほとんど)「いいえ関連する値/オブジェクトを処理するためにを強制ことであると信じ

int StringLength(string str) 
{ 
    if (str != null) 
    { 
     return str.Length; 
    } 
    else 
    { 
     return -1; 
    } 
} 

let stringLength (str:Option<string>) = 
    match str with 
    | Some(v) -> v.Length 
    | None -> -1 

はに似ています"大文字小文字は、コードをより堅牢にします

2

値がオプションの場合に使用します。 1つの用途は、一種の「ヌルリファレンス」を有することである。

val x : int option ref = None 

その後、後でxを「Some v」に変更することができます。

match !x with (* dereference x *) 
    None -> (* No value, do something *) 
| Some v -> (* Value v, do something else *) 
4

関数またはメソッドが値を「多分」または「任意に」返す必要がある場合に使用されます。 C#ではおそらくnullを返すか、Null Objectを返すか、値の型にNullableを返す可能性があります。

戻り値の欠点(最も一般的なケース)は、型が安全でないということです。nullはすべての型のインスタンスなので、後ほどすべての種類の毛状ヌル参照状況になります。

オプションタイプは、2つのコンストラクタを持つ、いわゆる識別されたユニオンタイプです。いずれも値がないことを明示的に示していません。基本的には、それは一般化されたヌルオブジェクトパターンです。

1

その他の回答に追加するには、Optionタイプは何も特別なものではありません。これは別の差別化されたユニオンです。あなたは1行でそれを自分で定義することができます。

type 'a Option = None | Some of 'a 

ユーティリティ、他の人が指摘したように、そのパターンマッチングは、安全にこれを解体できるようになるされ、代わりにnullをチェックするかどうかを示すために、いくつかのハック-回避策を使用します値は実際に値ではありません。

0

オプションタイプ使用して、機能パターン:あなたは、このようなツリーやリストなどの再帰的なデータ構造の一部を変更する必要がある場合

は、 既存のデータ構造としての限りを再利用したいと思うでしょう可能。オプションタイプ はこれを手伝うことができます。 これらの2つの関数は、数字5のすべての出現を7,に置き換えますが、最初のものはツリー全体をコピーします。 2番目のものはありません。

type Tree = Leaf of int 
     | Node of Tree * Tree 

let rec replace_no_sharing tree = 
    match tree with 
    | Leaf 5  -> Leaf 7 
    | Leaf x  -> Leaf x 
    | Node (a, b) -> Node (replace_no_sharing a, replace_no_sharing b) 

let replace_with_sharing tree = 
    let rec replace_option tree = 
     match tree with 
     | Leaf 5  -> Leaf 7 |> Some 
     | Leaf x  -> None 
     | Node (a, b) -> match replace_option a, replace_option b with 
         | None, None  -> None 
         | Some a, Some b -> Node (a, b) |> Some 
         | Some a, None -> Node (a, b) |> Some 
         | None, Some b -> Node (a, b) |> Some 
    match replace_option tree with 
    | None  -> tree 
    | Some tree -> tree 

すべてのケースで必ずしも必要なわけではありませんが、わかりやすいテクニックです。