为什么 F# 的 Set 没有实现 ISet<T> 接口?

8
.NET Framework在4.0版本中添加了一个ISet接口。同时,F#也被添加为一种一流的语言,并提供了一个不可变的Set<'T>类。虽然逻辑上应该将此类实现ISet,但它却没有这样做。有人知道为什么吗?我的猜想是他们不想实现旨在可变的接口,但我认为这个解释站不住脚。毕竟,他们的Map类实现了IDictionary,这是可变的。而且在框架的其他地方还有类实现了只部分适合的接口的例子。我认为可能是因为ISet是新的接口,所以他们还没有去处理它。但这似乎不太充分。是否因为ISet是泛型的(相对于IDictionary而言),所以没有这样做呢?欢迎留下您的想法。

在.NET框架本身中,ReadOnlyCollection<T>实现了可变接口ICollection<T> - Steven
@Steven 对,这是一个框架类实现接口的例子,但并不完全适合。 - Sean Devlin
2个回答

6
由于没有其他人参与讨论,我会加上我的猜测。首先,大部分 IDictionary<'k,'v> 接口对于不可变字典仍然有意义;只是添加或删除单个元素是行不通的。其次,已经编写了相当多依赖于 IDictionary 的代码,因此能够在该代码中使用 F# 值是一个好处。
另一方面,ISet<'t> 的几种方法需要进行更改,包括不仅是添加单个元素,还包括几个集合变异运算符,如并集和交集。此外,许多集合用例已经被 IEnumerable<'t> 接口所包含 - 我认为人们很少会依赖于 ISet<'t> 实现的不可变集合基础代码。
我认为泛型与此无关 - 请注意,尽管 MSDN 文档如此,但 F# 映射实现了通用的 IDictionary 接口,而不是非通用接口。

1
这听起来很有道理。但如果是真的,那就令人沮丧。对我来说,包括所有那些暗示实现类可变性的接口方法似乎是一个错误。同样地,我认为包括暗示类应该是不可变的方法也是一个错误。如果 ISet<T> 只包含“读取”成员将会很好。我认为现有的接口过于主观,并且现在我仍然没有一个简单的方法来表达“这是一组唯一项”的意思。(至少就 F# 互操作性而言。) - Sean Devlin
看起来并不是大多数:按我的计算,只有11个适当成员中的五个需要变异。如果包括从ICollection<T>继承的成员,则为18个中的8个。(而其中至少void Add(T item)可能会被明确实现。) - Sean Devlin
我本来想写一个类似的答案,但是后来我看了一下ISet<T>接口,发现它还有很多可以实现的操作(比如SetEqualsIsSubsetOfIsSupersetOfOverlapsIsProperSubsetOfIsProperSupersetOf),也许比IDictionary少一些,但还是有相当多的...另一个推理可能是没有.NET方法会使用ISet<T>,所以没有应用驱动的原因去实现它(我猜对于IDictionary可能有一些好的用例)。 - Tomas Petricek
@Tomas 这是真的,但我觉得不实现它会给编写新代码的人带来一些阻力。例如,我想定义一些传递集合的接口(不修改,只查询)。这给 F# 代码的消费者增加了一些阻力,所以现在对于我的接口来说,回退到 IEnumerable<T> 更有意义。有点遗憾,我真的很期待将此接口添加到框架中。看起来这将稍微抑制采用率。 - Sean Devlin
@Sean:我同意,我认为.NET BCL应该包括一组更好的接口来表示集合、集合、字典及其不可变版本等。考虑到我们必须与.NET 1遗留问题共存,这可能很难做到。 - Tomas Petricek
@Sean - 你说得对,不是绝大多数,我会更新我的帖子。 - kvb

6

我不确定先前是否意识到了ISet。 (实际上,我查看了旧电子邮件,只发现2008年BCL计划中提到了一次。所以我想我们并没有关注它。)

尽管如此,F# 力求在 .NET 2.0 和 .NET 4.0 位之间源代码兼容,甚至将 .NET 4.0 实体回溯到 FSharp.Core.dll 版本 2.0。例如,2.0 FSharp.Core 包含 System.Tuple System.BigInteger System.Threading.CancelationTokenSource (异步编程模型的一部分)等,而 ISet 也是可能需要回溯的工作(我不确定是否“必须”回溯它,但这也不清楚)。

我会提交一个问题来研究一下,尽管在这个时间点上这可能已经无关紧要了。


2
这很有道理。我没有意识到保持F#跨框架源代码兼容性的动机。只是好奇,这背后的原因是什么?官方立场是.NET 4.0不包含F#的“新”版本,而是将现有的F#作为官方的一流打包吗? - Sean Devlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接