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

时间:2013-10-14 08:00:03

标签: haskell functional-programming

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

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

的结果
(eq? (car x) (cdr x))

是真的,而且没有必须与(car x)(cdr x)对等。这允许您为具有大量共享的数据结构编写有效的相等性测试。

Haskell是否可以做同样的事情?例如,请考虑以下二叉树实现

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

在每个级别都有共享。如果我创建一个let tree = mkTree 30的树,我想看看left treeright tree是否相等,天真地我必须遍历十亿个节点才能发现它们是同一棵树,因数据共享而应该是显而易见的。

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

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

3 个答案:

答案 0 :(得分:16)

有很多方法。

  1. 生成唯一ID并将所有内容粘贴在有限地图中(例如IntMap)。
  2. 最后一个选择的精炼版本是制作一个明确的图表,例如:使用fgl
  3. 使用stable names
  4. 使用IORefssee also),其中包含EqOrd个实例,无论包含的类型如何。
  5. observable sharing的图书馆。
  6. 如上所述,有reallyUnsafePtrEquality#但你应该在使用之前了解它真正不安全的地方!
  7. 另见this answer about avoiding equality checks altogether

答案 1 :(得分:4)

在Haskell中,纯语言是不可能的。

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

无论如何,在常规代码中使用它将是非常单一的;至多我可以想象,构建一个高度专业化的库(memoizatoin,哈希表,无论如何),然后提供一个理智的纯API,可能是可以接受的。

答案 2 :(得分:1)

reallyUnsafePtrEquality#。另请参阅here