0

ここで、私が思いついた最終的な回答でアップキャストが必要な理由について、マイクロ質問があります(この下部にあります)。そして、「部屋の中の象」が欠けているだけなのかという大まかな質問:私がやりたいことを行うための本当に明白な簡潔な方法[私に尋ねないでください-なぜ-私は欲しいものを欲しがっています。私がこれが欲しいのは当然だと思ってください、そしてそれは...]

MongoDB.Bson CLR assmbly を介して F# から BsonDocument を初期化したいと考えています。私が使用すべきだと思う BsonDocument コンストラクターの特定のオーバーロードは

MongoDB.Bson.BsonDocument.BsonDocument(IDictionary<string,object>)

そして、これが私が使うべきものだと思う理由です(以下はタイプの庭を長い散歩です...)

MongoDB サイトMongoDB CSharp Driver Tutorialの C# サンプルでは、​​BsonDocument によって公開されたインターフェイスの .Add の 1 つ以上の呼び出しにマップされるコレクション初期化構文を使用しています。チュートリアルのサンプルは次のようになります。

var bdoc = new BsonDocument { { "a", "1" }, { "b", "2" }, };

.Add のどのオーバーロードが使用されているかはわかりませんが (Visual Studio で確認する方法もわかりません)、辞書ベースのオーバーロードはすべて <string, object> として型指定されています。この場合、各ペアの 2 番目の値、つまり文字列型の "1" と "2" は、(継承により) 自動的にオブジェクト型にもなるため、すべて問題ありません。また、.Add の他のオーバーロードでは、2 番目の項目が BsonValue 型である必要があります。これは、BsonString の抽象スーパータイプであり、どのオーバーロードが使用されても .NET 文字列から暗黙的に変換されます。そこでもすべて問題ありません。コンストラクターのどのオーバーロードが呼び出されるかは問題ではありません。

BsonDocument の .Add メソッドにたどり着くのが難しいため、これを F# に相当するものにするのは少し難しいです。と思いました

[("a", "1");("b", "2");] |> Seq.iter BsonDocument.Add

BsonDocument.Add は静的メソッドではないため、これは機能しません。BsonDocument をインスタンス化してから、BsonDocument の .Add メソッドを呼び出す楽しいラムダを作成できます。これにより、少なくとも可変性が楽しいものに分離されます。

[("a", "1");("b", "2");] |> Seq.fold ...

BsonDocument を参照する変数が (new BsonDocument()) の前に発生するため、BsonDocument の明示的な型表記が必要なため、これは非常に醜いことがわかります。したがって、左から右への型推論は行われません。 (まだ)十分な情報があり、楽しみは(少なくとも、明らかに)各ペアの2番目の値の文字列からBsonStringへの暗黙的な変換にアクセスする必要があることを知る方法がないため...

let bdoc = [("a","1");("b","2");] |> Seq.fold (fun (doc:BsonDocument) pair -> doc.Add(fst pair, new BsonString(snd pair))) (new BsonDocument())

...とにかく、コンストラクターのより大きなオーバーロードを使用すると思いました

BsonDocument(IDictionary<string, object>)

ただし、これは次のように強制されます。

let bdoc = (new BsonDocument(dict
  [("a", "1" :> Object); 
   ("b", "2" :> Object);
  ]))

アップキャストを取り出すと

:> Object

次に、F# は、BsonDocument のオーバーロードが見つからないと文句を言います。

(長い庭の散歩は終わりました...)

結局のところ、マイクロクエスチョンは、なぜ、F# では、入力ディクショナリの「1」と「2」がオブジェクトであり、適切なオーバーロードを見つけられないのかということです。

そして、全体像のマクロの問題は、F# でこれを行うための適切でベスト プラクティスであり、非常にクールで簡潔な方法を見逃したのではないかということです。

4

1 に答える 1

4

これは MongoDB の問題ではありません。問題はそれ("1", "2")が であるため、コンストラクターでstring * stringを作成していることです。F# は、指定された型を推測しました。この場合、その型推論はあなたが意図したことを決定しません。したがって、あなたはそれを伝えなければなりません。IDictionary<string,string>dictobj

> dict
  [("a", "1" :> obj); 
   ("b", "2" :> obj);
  ];;
val it : System.Collections.Generic.IDictionary<string,obj> =
  seq [[a, 1] {Key = "a";
               Value = "1";}; [b, 2] {Key = "b";
                                      Value = "2";}]
> dict
  [("a", "1"); 
   ("b", "2");
  ];;
val it : System.Collections.Generic.IDictionary<string,string> =
  seq [[a, 1] {Key = "a";
               Value = "1";}; [b, 2] {Key = "b";
                                      Value = "2";}]
于 2011-10-19T23:09:50.333 に答える