是否有可能在 Haskell 中检测到共享?

Is it ever possible to detect sharing in Haskell?

提问人:Chris Taylor 提问时间:10/14/2013 更新时间:7/22/2015 访问量:650

问:

在 Scheme 中,原语测试其参数是否为同一对象。例如,在以下列表中eq?

(define lst
  (let (x (list 'a 'b))
    (cons x x)))

结果

(eq? (car x) (cdr x))

是真的,而且它是真的,不必窥视和.这允许您为具有大量共享的数据结构编写有效的相等性测试。(car x)(cdr x)

在哈斯克尔中也有同样的事情吗?例如,请考虑以下二叉树实现

data Tree a = Tip | Bin a (Tree a) (Tree a)

left  (Bin _ l _) = l
right (Bin _ _ r) = r

mkTree n :: Int -> Tree Int
mkTree 0 = Tip
mkTree n = let t = mkTree (n-1) in Bin n t t

在各个层面都有共享。如果我创建一棵树,并且我想查看 和 是否相等,那么天真地我必须遍历超过 10 亿个节点才能发现它们是同一棵树,这应该是显而易见的,因为数据共享。let tree = mkTree 30left treeright tree

我不指望有一种简单的方法可以在 Haskell 中发现数据共享,但我想知道处理此类问题的典型方法是什么,何时出于效率目的检测共享(或例如检测循环数据结构)会很好。

是否有可以检测共享的基元?有没有一种众所周知的方法来构建具有显式指针的数据结构,以便您可以比较指针的相等性?unsafe

Haskell 函数式编程

评论

0赞 Yuras 10/14/2013
另见 stackoverflow.com/questions/1717553/pointer-equality-in-haskell
0赞 7/22/2015
执行此操作时,请始终考虑数据结构包含 NaN 或其他与自身不相等的值的可能性。您的优化可能是一个破坏性的优化。

答:

1赞 Yuras 10/14/2013 #1

真的有UnsafePtrEquality#。另请参阅此处

5赞 Joachim Breitner 10/14/2013 #2

这在Haskell(纯语言)中是不可能的。

但是在GHC的实施中,存在漏洞,例如

无论如何,在常规代码中使用它都是非常不惯用的;我最多可以想象,为某些东西(memoizatoin、哈希表等)构建一个高度专业化的库,然后提供一个理智的、纯粹的 API,可能是可以接受的。

16赞 Daniel Wagner 10/14/2013 #3

有很多方法。

  1. 生成唯一的 ID 并将所有内容粘贴到有限映射(例如 IntMap)中。
  2. 最后一种选择的改进版本是制作一个显式图,例如使用 fgl
  3. 使用稳定的名称
  4. 使用 IORefs另请参阅),无论包含的类型如何,它都具有 和 实例。EqOrd
  5. 有用于可观察共享的库。
  6. 如上所述,有,但在使用它之前,您应该了解它真正不安全的地方!reallyUnsafePtrEquality#

另请参阅有关完全避免相等性检查的答案