Нужны были сюрпризы При инициализации документа MongoDB из F # dict? - PullRequest
0 голосов
/ 20 октября 2011

Здесь есть микро-вопрос о том, почему в последнем ответе, который я придумал, необходим повышающий отклик (внизу);и макро-вопрос о том, не скучаю ли я по «слону в комнате»: какой-то действительно очевидный лаконичный способ делать то, что я хочу [пожалуйста, не спрашивайте меня, почему я хочу то, чего хочу;просто примите это как данность, что я этого хочу, и это ...]

Я хочу инициализировать BsonDocument из F # через ассемблер MongoDB.Bson CLR.Конкретная перегрузка конструктора BsonDocument, которую я думаю, что я должен использовать, это

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

, и вот почему я думаю, что это тот, который я должен использовать (ниже приводится длинная прогулка по саду типов ...)

Пример C # с сайта MongoDB Учебное пособие по CSharp для MongoDB использует синтаксис инициализатора коллекции, который сопоставляется с одним или несколькими вызовами .Add на интерфейсе, предоставляемом BsonDocument.Пример учебника похож на следующий:

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

Я не уверен, какая перегрузка .Add используется (и не знаю, как проверить в Visual Studio), но все перегрузки на основе словарянапечатаны как,В этом случае вторые значения в каждой паре, а именно «1» и «2» типа string, автоматически (по наследству) также имеют тип объекта, так что все в порядке.И другие перегрузки .Add, которые требуют, чтобы второй элемент имел тип BsonValue, который является абстрактным супертипом BsonString, который имеет неявное преобразование из строки .NET независимо от используемой перегрузки;так что там тоже все нормально.Неважно, какая перегрузка конструктора вызывается.

Это немного сложно маневрировать в F # -эквиваленте, потому что трудно получить метод .Add BsonDocument.Я думал о

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

, но это не работает, потому что BsonDocument.Add не является статическим методом;Я мог бы создать экземпляр BsonDocument, а затем написать забавную лямбду, которая вызывает метод BsonDocument .Add, который, по крайней мере, изолировал бы изменчивость от удовольствия:

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

, но это оказалось очень уродливо, так какшутка, требующая явной записи типа в BsonDocument, потому что переменная, ссылающаяся на BsonDocument, происходит до (new BsonDocument ()), поэтому вывод типа слева направо не имеет достаточно информации (пока), а также потому, что шутка (по крайней мере, по-видимому) не может знать, что он должен получить доступ к неявному преобразованию из строки в 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 #

1 Ответ

4 голосов
/ 20 октября 2011

Это не проблема MongoDB. Проблема в том, что ("1", "2") - это string * string, поэтому вы создаете IDictionary<string,string> с вашим конструктором dict. F # вывел типы, которые вы ему дали. Его вывод типа не определит, что вы имели в виду obj в этом случае. Поэтому ты должен сказать это.

> 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";}]
...