Oop 功能性数据结构、相等和比较的OO概念、结构相等和引用透明性

Oop 功能性数据结构、相等和比较的OO概念、结构相等和引用透明性,oop,f#,functional-programming,comparison,equality,Oop,F#,Functional Programming,Comparison,Equality,我有一个非常CPU密集的F#程序,它依赖于持久数据结构——大约40%的总CPU时间花在Map模块上。所以我想在FSharpX系列中试用PersistentHashMap。(顺便说一句,与VS2013中F#的前一个版本相比,这已经是一个很大的改进,在VS2013中,同一个程序的70%时间都花在Map上。我还注意到,运行带有调试器的程序不会像以前那样受到巨大的惩罚-好工作的家伙们…)还有一个热点,我一直在重新排序,相反,我应该添加到堆中,所以我想我也应该尝试一下。 两个问题立即显现出来: (1) 从

我有一个非常CPU密集的F#程序,它依赖于持久数据结构——大约40%的总CPU时间花在Map模块上。所以我想在FSharpX系列中试用PersistentHashMap。(顺便说一句,与VS2013中F#的前一个版本相比,这已经是一个很大的改进,在VS2013中,同一个程序的70%时间都花在Map上。我还注意到,运行带有调试器的程序不会像以前那样受到巨大的惩罚-好工作的家伙们…)还有一个热点,我一直在重新排序,相反,我应该添加到堆中,所以我想我也应该尝试一下。 两个问题立即显现出来:

(1) 从接口的角度来看,将一个映射替换为另一个被证明比看起来更难-即,制作一个垫片,让我从映射切换到持久映射,同时保留使用每个映射所需的基于模块的let绑定函数和类型。我知道拥有完整的HM类型推断(并且没有类型类)在很大程度上与LSP风格的引用透明性是正交的——但也许我缺少了一些方法,可以用最少的代码来更好地做到这一点

(2) 最大的问题(我想在这里重点讨论)是F#functional数据结构依赖于oo风格,并通过IComparson(when't:comparison)等接口族进行比较

即使对于OO程序来说,分派相等和比较的想法也是一个坏主意——对象“知道”如何执行自己的领域特定任务,但它不“知道”在大多数情况下,出于各种目的,在程序的各个点上需要什么样的相等概念——因此相等/比较不应该是对象接口的一部分,但是当需要这些概念时,应该始终明确地提到它们。例如,不应该有.Sort(),而应该只有.SortWith(…)。有人可能会说,即使像F#中的结构等式这样的基本内容也可以是显式的a.StructEq(b)或a~=b——否则你总是得到object.Equals——但即使规定这样做对一种多范式语言来说是最好的,它是一流的.Net公民,似乎至少应该有使用传入比较函数和相等函数的选项,但事实并非如此

这意味着:(a)即使您不想要类型约束,也会强制执行它们,从而导致中断的推断类型的涟漪(以及数百条波浪形红线,不清楚实际的“问题”在哪里)和(b)通过实现相等或比较的概念,使一个容器类型在程序的某个部分感到满意(在我的例子中,我希望使用相同的容器和项目类型,并在两个不同的位置使用两种不同的订购概念),它可能会在依赖于默认/先前实现的代码的其他部分中无声地中断(或者导致效率低下,如果一个包含另一个)

我能想到的唯一解决方法是使用new…with object expression将每个项包装为适配器对象,但我真的不想为了让代码正常工作而创建这么多垃圾

因此,我认为我们可以拥有每个持久数据结构的“纯”版本,如果需要的话可以加载(甚至是基本的,如列表等),它不依赖于调度的相等/比较/散列,也不施加类型约束-所有这些需要都应该在调用时通过传入fn。(分派的eq/cmp将仅用于与不接受委托的BCL集合的互操作。)然后我们可以有一个[EQCMPhashThrownNotImplemented]属性,我可以确保根本没有发生默认操作,并且我对代码的效率和可预测性会感觉更好。(这也让我们从一个记录更改为一个类,或者从一个类更改为另一个类,不必担心由于默认实现而导致的任何行为变化。)同样,这是可选的,但通过简单的导入即可完成。(这意味着每个基本核心集合类型都必须被分解成自己的模块,这其实不是一个坏主意。)


如果我忽略了一种更好的做事方式,或者这里有一些人们正在使用的模式,我会感兴趣。

选择其中的一部分,并将其作为一个问题来表达。寻求更好的东西是主观的。StackOverflow是关于具体的客观问题和答案。因此,我投票决定结束,因为
太宽泛了。
忠告是,如果你在你的问题中有状态,你不喜欢用F来让它工作,那么考虑使用一种不同的语言,或者至少部分地使用不同的语言。我需要坚持。DSS和很少的“状态”。这就是我使用DSs系列的原因。租户是:让持久性数据结构使用调度相等和比较作为唯一的选择是不可伸缩的,使一次跳过不必要的环,并导致容易出错和/或效率低下的代码。关于争用调度比较/相等,也有类似的问题虽然“具体”的答案很有用,但它们强调需要一种更普遍的方法。如果讨论“过于广泛”,需要转移到其他地方,那就好了。