0

这里有一个小问题,关于为什么在我想出的最终答案中需要向上转换(在此底部);还有一个关于我是否只是想念“房间里的大象”的宏观问题:一些非常明显简洁的方式来做我想做的事[请不要问我-为什么-我想要我想要的;只是把它当作我想要这个的给定,它是......]

我想通过 MongoDB.Bson CLR 组件从 F# 初始化一个 BsonDocument。我认为我应该使用的 BsonDocument 构造函数的特定重载是

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

这就是为什么我认为这是我应该使用的(以下是在类型花园中漫步......)

来自 MongoDB 站点MongoDB CSharp Driver Tutorial的 C# 示例使用集合初始化器语法,该语法映射到 BsonDocument 公开的接口上的一个或多个 .Add 调用。教程示例类似于以下内容:

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

我不肯定正在使用 .Add 的哪个重载(并且不知道如何在 Visual Studio 中检查),但是所有基于字典的重载都输入为 <string, object>。在这种情况下,每对中的第二个值,即字符串类型的“1”和“2”,自动(通过继承)也是对象类型,所以一切正常。.Add 的其他重载要求第二项的类型为 BsonValue,这是 BsonString 的抽象超类型,无论使用哪种重载,它都具有从 .NET 字符串的隐式转换;所以那里也一切正常。调用构造函数的哪个重载并不重要。

这有点难以操作到 F# 等效项,因为很难使用 BsonDocument 的 .Add 方法。我想到了

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

但这不起作用,因为 BsonDocument.Add 不是静态方法;我可以实例化 BsonDocument,然后编写一个有趣的 lambda,它调用 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# 中执行此操作的适当、最佳实践、超酷、简洁的方法?

4

1 回答 1

4

这不是 MongoDB 问题。问题在于它("1", "2")是 a string * string,因此您正在IDictionary<string,string>使用dict构造函数创建 a 。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";}]
于 2011-10-19T23:09:50.333 回答