正如我所知,Haskell中的变量是不可变的(因此,它们不是真正的“变量”)。
在这种情况下,如果我们有一个复杂的大数据结构,比如红黑树,我们应该如何实现实际改变数据结构的操作?
每次插入或删除元素时都创建树的副本?
答案 0 :(得分:33)
是的,解决方案是返回一个表示修改后的值的新数据结构,但是不需要复制示例的整个结构(红黑树),因为您可以只复制路径上的节点插入节点的根目录。这允许插入操作与命令式版本具有相同的复杂性。
Chris Okasaki的Purely functional data structures包含许多不可变数据结构的实现 - 这本书是他的博士论文的修改版本,你可以找到here
答案 1 :(得分:27)
你对复制的直觉正是你应该思考的正确方向。但是,Haskell运行时智能地实现了“复制”。例如,给定
data Tree = Empty | Branch Tree Integer Tree
您可以实现一个替换左分支的函数:
replaceLeft :: Tree -> Tree -> Tree
replaceLeft (Branch _ i r) newLeft = Branch newLeft i r
结果不是您创建新树的整个副本,因为这不是必需的。值i
和树r
和newLeft
未更改,因此我们无需将其内容复制到新内存中。
创建的新Branch
(这是此示例中唯一真正的分配:在Integer
上创建保留左/右树的结构)仍引用完全相同的值来自旧的分支,不需要复制!
由于数据结构是不可变的,因此这样做没有任何害处。