提问人:radrow 提问时间:3/30/2022 最后编辑:radrow 更新时间:5/13/2023 访问量:278
如何测试Haskell对象的引用相等性?
How to test Haskell objects for reference equality?
问:
在 Haskell 中,相等性检验通常使用来类来执行。这个函数(在大多数情况下)是在纯Haskell术语下定义的,所以它遵循递归应用于大数据结构的所有后果。因此,看似微不足道的比较可能需要花费大量时间。来吧,这应该是即时的(关于懒惰的提醒):==
Eq
ghci> let x = [1..100000000] in x == x
True
(2.81 secs, 14,400,130,800 bytes)
为什么Haskell在这里不使用引用比较?如果我真的愿意,Haskell甚至允许我这样做吗?
答:
简短的回答:不,这在 Haskell 中是不可能的,而且有很好的理由。引用相等是语言设计的基本组成部分,保留它使Haskell有别于语言设计领域的许多其他语言。
一个稍长的答案:这是一个经过充分研究的话题,通常被称为可观察共享,至少可以追溯到 2000 年代初:
Claessen 和 Sands 解释了 Observable Sharing 在哪些情况下是有用的,以及如何将其整合到语言中。这是一篇非常容易阅读的论文,它详细解释了这个问题,并提出了一个非保守的扩展。有利于理解基本问题。
Gill 对这个问题的解决方案是一种在实践中使用的非常可行的方法,称为类型安全的可观察共享。这里的想法是,你可以在纯代码中创建等式,但你只能在一元 IO 上下文中观察它们;这保留了引用的平等性。它没有假阴性,也很少有假阳性。在hackage上也有这个想法的实现,你可以很容易地使用。
长话短说:不,你不能做引用相等,或者指针相等,或者直接在Haskell中观察共享,这是有充分理由的。这个问题得到了很好的研究和理解,并且有切实可行的解决方案可以在Haskell生态系统中解决这个问题,而不会破坏引用的透明度。
如果搜索比较引用的替代方法以加快相等计算速度,请尝试 System.Mem.StableName。 两个对象的 StableName 相等保证两个对象实际上是同一个对象。但不等式并不意味着什么,因为对象可以被运行时系统复制和移动。
评论
xs = [1, 2, 3]
ys = id xs
xs == ys
==
ys
xs == ys
reallyUnsafePtrEquality#
和以下其他问题感兴趣:stackoverflow.com/q/9649500、stackoverflow.com/q/19355772、stackoverflow.com/q/30175974 stackoverflow.com/q/48163259。