提问人:Chris Taylor 提问时间:10/14/2013 更新时间:7/22/2015 访问量:650
是否有可能在 Haskell 中检测到共享?
Is it ever possible to detect sharing in Haskell?
问:
在 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 30
left tree
right tree
我不指望有一种简单的方法可以在 Haskell 中发现数据共享,但我想知道处理此类问题的典型方法是什么,何时出于效率目的检测共享(或例如检测循环数据结构)会很好。
是否有可以检测共享的基元?有没有一种众所周知的方法来构建具有显式指针的数据结构,以便您可以比较指针的相等性?unsafe
答:
1赞
Yuras
10/14/2013
#1
5赞
Joachim Breitner
10/14/2013
#2
这在Haskell(纯语言)中是不可能的。
但是在GHC的实施中,存在漏洞,例如
- 使用 reallyUnsafePtrEquality# 或
- 自省库,如 ghc-heap-view。
无论如何,在常规代码中使用它都是非常不惯用的;我最多可以想象,为某些东西(memoizatoin、哈希表等)构建一个高度专业化的库,然后提供一个理智的、纯粹的 API,可能是可以接受的。
16赞
Daniel Wagner
10/14/2013
#3
有很多方法。
- 生成唯一的 ID 并将所有内容粘贴到有限映射(例如
IntMap
)中。 - 最后一种选择的改进版本是制作一个显式图,例如使用 fgl。
- 使用稳定的名称。
- 使用
IORef
s(另请参阅),无论包含的类型如何,它都具有 和 实例。Eq
Ord
- 有用于可观察共享的库。
- 如上所述,有,但在使用它之前,您应该了解它真正不安全的地方!
reallyUnsafePtrEquality#
另请参阅有关完全避免相等性检查的答案。
评论