haskell - "True"纯功能双向链表和节点共享

标签 haskell functional-programming linked-list

Recently我被介绍给 this OCaml code在 Haskell 中可以写成:

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 中的同名变量是否总是指代相同的“事物”,或者可能单独出现的同名变量引用同一事物的单独副本? (编辑以增加重点)。

最佳答案

您可以使用名为 Vacuum-cairo 的包来可视化数据结构的内存布局。使用 cabal install vacuum-cairo 从 hackage 安装那么您应该能够通过 GHCi 中的类似方法来验证这两种结构的差异:

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

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

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

关于haskell - "True"纯功能双向链表和节点共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9309675/

相关文章:

c++ - 与模板成员函数的接口(interface)

scala - 为什么 Finatra 使用 flatMap 而不仅仅是 map ?

c - 从队列中删除偶数

pointers - 使用指针的 Fortran 链表中的内存泄漏

haskell - 在 Haskell 中更改字符串

haskell /米兰达 : Find the type of the function

macos - 无法在 OSX 10.9.5 上安装 haskell-src-exts-1.16.0

减少 R 中函数的额外参数

Java indexof() 搜索

haskell - 为什么不懒惰