如何测试 Haskell 对象的引用相等性?

rad*_*row 3 haskell equality reference

在 Haskell 中,相等测试通常是使用类==来执行的Eq。该函数(在大多数情况下)是在纯 Haskell 术语下定义的,因此它遵循将其递归应用于大数据结构的所有后果。因此,看似微不足道的比较可能会花费大量时间。来吧,这应该是即时的(关于懒惰的提醒):

ghci> let x = [1..100000000] in x == x
True
(2.81 secs, 14,400,130,800 bytes)
Run Code Online (Sandbox Code Playgroud)

为什么 Haskell 在这里不使用引用比较?如果我真的愿意的话,Haskell 是否允许我这样做?

ali*_*ias 11

简短的回答:不,这在 Haskell 中是不可能的,并且有很好的理由。引用相等是语言设计的基本部分,保留它使 Haskell 与语言设计领域中的许多其他语言不同。

一个稍长的答案:这是一个经过充分研究的主题,通常称为可观察共享,至少可以追溯到 2000 年代初:

  • Claessen 和 Sands 解释了可观察共享在哪些情况下有用以及如何将其合并到语言中。这是一篇非常容易阅读的论文,它详细解释了这个问题并提出了非保守的扩展。有助于理解基本问题。

  • Gill 针对这个问题的解决方案是一种在实践中使用的非常可行的方法,称为类型安全的可观察共享。这里的想法是,您可以在纯代码中创建相等性,但只能在单子 IO 上下文中观察它们;它保留了引用平等。它没有假阴性,假阳性也很少。您还可以轻松使用hackage上的这种想法的实现。

长话短说:不,你不能在 Haskell 中进行引用相等、指针相等或直接观察共享,这是有充分理由的。这个问题已经得到了很好的研究和理解,并且在 Haskell 生态系统中有一些实用的解决方案可以在不破坏引用透明度的情况下解决这个问题。