简体   繁体   English

为什么F#的默认集合集合是在C#的时候排序的?

[英]Why F#'s default set collection is sorted while C#'s isn't?

When migrating from a C# world to an F# (the most idiomatic possible) mindset, I've found this interesting difference. 当从C#世界迁移到F#(最可能的惯用语)时,我发现了这个有趣的区别。

In C#'s OOP&mutable world, the default set collection seems to be HashSet , which seems to be not sorted by default (because the comparer that it accepts is just for equality); 在C#的OOP&mutable世界中,默认的set集合似乎是HashSet ,它似乎没有默认排序(因为它接受的比较器只是为了相等); while if you wanted a sorted one you would have to use SortedSet . 如果你想要一个排序的,你必须使用SortedSet

However in F#'s world, the basic set is already sorted because it requires the element type used to implement equality and comparison. 但是在F#的世界中,基本set已经被排序,因为它需要用于实现相等比较的元素类型。 Any specific reason for this? 有什么具体的原因吗? Why not having an unordered set in the main collections for this language? 为什么不在这个语言的主要集合中设置无序集?

As a side-note, I'm wondering if it'd be possible to have a set collection that didn't allow duplicates, but that had a preference over certain elements when discarding some elements as duplicates. 作为旁注,我想知道是否有可能有一个不允许重复的集合集合,但是当将某些元素作为重复元素丢弃时,它优先于某些元素。 Example: a record { Name: string; Flag: Option<unit> } 示例:记录{ Name: string; Flag: Option<unit> } { Name: string; Flag: Option<unit> } so that when inserting { Name = "foo"; Flag = None } { Name: string; Flag: Option<unit> }以便在插入{ Name = "foo"; Flag = None } { Name = "foo"; Flag = None } and later { Name = "foo"; Flag = Some() } { Name = "foo"; Flag = None }以后{ Name = "foo"; Flag = Some() } { Name = "foo"; Flag = Some() } it ended up containing only the latter element (because Flag is present). { Name = "foo"; Flag = Some() }它最终只包含后一个元素(因为Flag存在)。

F# Set happens to be sorted, but it's more of an implementation detail resulting from the choice of the underlying data structure and should not generally be relied upon. F# Set碰巧被排序,但它更多的是由于选择底层数据结构而产生的实现细节,通常不应该依赖它。

F# sets and maps are based on a variant of AVL tree and that structure happens to maintain the invariant that elements stored in the tree are sorted. F#集和映射基于AVL树的变体,并且该结构恰好保持对存储在树中的元素进行排序的不变量。 The reason why it requires comparison constraint is because lookup in this tree structure depends on direct comparisons between elements to select the subtree that gets traversed. 它需要比较约束的原因是因为此树结构中的查找依赖于元素之间的直接比较来选择遍历的子树。

The selling point of these structures however is the fact that they can be used to implement reasonably efficient, immutable versions of maps and sets cheaply, and that's what F# needed at a time where the wider .NET platform didn't offer any alternatives. 然而,这些结构的卖点是它们可以用来实现合理有效,不可变的地图版本和廉价设置,而这正是F#在更广泛的.NET平台没有提供任何替代方案时所需要的。

Note that this is not the only viable choice in this context and JVM functional languages like Clojure or Scala opted for a different data structure as the base for their maps - hash array mapped trie - which is also immutable and persistent, arguably more complex to implement, arguably more efficient for larger collection sizes, but happens to store elements unordered. 请注意,这不是此上下文中唯一可行的选择,并且像Clojure或Scala这样的JVM函数语言选择了不同的数据结构作为其映射的基础 - 散列数组映射trie - 这也是不可变和持久的,可能实现起来更复杂,对于较大的集合大小,可以说更有效,但恰好存储无序的元素。 Unlike AVL trees, the traversal of the tree is based on hashes, so comparison constraint is not required. 与AVL树不同,树的遍历基于哈希,因此不需要比较约束。

So if you already know that your priority is immutability, a sorted set is actually easier to implement than an unsorted set. 因此,如果您已经知道优先级是不变的,那么排序集实际上比未排序集更容易实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM