“真正的”纯功能双链表和节点共享

时间:2012-02-16 10:32:19

标签: haskell functional-programming linked-list

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中同名的变量总是指相同的"事物" 或者可能分别出现同名的变量引用的单独副本同样的事情?(编辑增加重点)。

2 个答案:

答案 0 :(得分:6)

您可以使用名为vacuum-cairo的包来可视化数据结构的内存布局。使用cabal install vacuum-cairo从hackage安装,然后你应该能够在GHCi中通过类似的方式验证两个结构的差异:

> import System.Vacuum.Cairo
> view $ create [1..5]

在那里你可以看到节点是使用DList共享的,因为DL是两个列表,其间有一个元素(正如所指出的,这是一种拉链)。

注意:这是GHC特定的,不同的实现可能以不同的方式表示内存中的数据,但这是典型的。

答案 1 :(得分:3)

我建议后者是“正确的”实施,是的。

我没有事实可以支持这一点,但在我理解GHC实施的情况下,我认为后者应该可以解决你希望双链表工作的方式。