Recently我被介绍给this OCaml code,在Haskell中可以写成:{/ p>
data DL a = DL [a] a [a]
create [] = error "empty list"
create (x:xs) = DL [] x xs
next (DL pr x (h:tl)) = DL (x:pr) h tl
next _ = error "end of dlist"
prev (DL (p:pr) x tl) = DL pr p (x:tl)
prev _ = error "start of dlist"
我认为不是一个正确的双向链表实现,因为它在遍历上创建了新的存储。 OTOH那里this Haskell code:
data DList a = Leaf | Node { prev::(DList a), elt::a, next::(DList a) }
create = go Leaf
where go _ [] = Leaf
go prev (x:xs) = current
where current = Node prev x next
next = go current xs
我们可以说仅 dl-list?
我们是否可以依赖此代码来引入dl-list节点的真正共享,以便在遍历时不会创建新存储?
Haskell中同名的变量总是指相同的"事物" 或者可能分别出现同名的变量引用的单独副本同样的事情?(编辑增加重点)。
答案 0 :(得分:6)
您可以使用名为vacuum-cairo的包来可视化数据结构的内存布局。使用cabal install vacuum-cairo
从hackage安装,然后你应该能够在GHCi中通过类似的方式验证两个结构的差异:
> import System.Vacuum.Cairo
> view $ create [1..5]
在那里你可以看到节点是使用DList共享的,因为DL是两个列表,其间有一个元素(正如所指出的,这是一种拉链)。
注意:这是GHC特定的,不同的实现可能以不同的方式表示内存中的数据,但这是典型的。
答案 1 :(得分:3)
我建议后者是“正确的”实施,是的。
我没有事实可以支持这一点,但在我理解GHC实施的情况下,我认为后者应该可以解决你希望双链表工作的方式。