数据StableName a
稳定名称具有以下属性: 如果sn1 :: StableName和sn2 :: StableName和sn1 == sn2,那么sn1和sn2是通过对同一对象调用makeStableName创建的。
反过来不一定如此:如果两个稳定名称不相等,那么它们命名的对象可能仍然相等。
reallyUnsafePtrEquality# :: a - > a - > INT#
reallyUnsafePtrEquality#返回GHC堆上的两个对象是否是同一个对象。这真的是不安全的,因为垃圾收集器移动东西,闭包等。据我所知,它可以返回假阴性(它说两个对象不一样,但它们是),但不是误报(说它们当它们不相同时,它们会一样。
他们两个似乎都做了同样的基本事情:他们可以告诉你两个对象是否绝对相同,但不是它们是否绝对不是。
我可以看到StableNames的优点是:
我可以在reallyUnsafePtrEquality#:
中看到的优势我的问题是:
我错过了什么吗?
是否存在StableNames与其所命名的对象分开的事实是否有用?
是否比另一个更准确(不太可能返回假阴性)?
如果你不需要散列,不关心可移植性,并且不会被使用名为reallyUnsafe的东西打扰,是否有理由更喜欢StableNames而不是reallyUnsafePtrEquality#?
答案 0 :(得分:9)
持有对象的StableName
并不能防止它被垃圾收集,而持有对象本身(以后与reallyUnsafePtrEquality#
一起使用)可以。当然,您可以使用System.Mem.Weak
,但此时,为什么不使用StableName
? (实际上,弱指针添加了StableName
s。)
能够散列它们是StableName
的主要动力,正如文档所说:
我们不能使用对象的地址作为键来构建哈希表,因为对象会被垃圾回收器移动,这意味着每次垃圾回收后都需要重新哈希。
一般情况下,如果StableName
s适用于您的目的,即使您需要使用unsafePerformIO
,我也会使用它们。如果你真的需要reallyUnsafePtrEquality#
,你就会知道。我能想到reallyUnsafePtrEquality#
工作的唯一示例和StableName
s不会加速昂贵的Eq
实例:
x == y =
x `seq` y `seq`
case reallyUnsafePtrEquality# x y of
1# -> True
_ -> slowEq x y
可能还有其他一些我想不到的例子,但它们并不常见。