【发布时间】:2016-07-24 10:42:38
【问题描述】:
在研究Learn You A Haskell For Great Good 和Purely Functional Data Structures 时,我想尝试重新实现Red Black tree,同时尝试在结构上强制执行另一个树不变量。
解释冈崎的代码,他的节点看起来像这样:
import Data.Maybe
data Color = Red | Black
data Node a = Node {
value :: a,
color :: Color,
leftChild :: Maybe (Node a),
rightChild :: Maybe (Node a)}
红黑树的一个属性是a red node cannot have a direct-child red node,所以我尝试将其编码如下:
import Data.Either
data BlackNode a = BlackNode {
value :: a,
leftChild :: Maybe (Either (BlackNode a) (RedNode a)),
rightChild :: Maybe (Either (BlackNode a) (RedNode a))}
data RedNode a = RedNode {
value :: a,
leftChild :: Maybe (BlackNode a),
rightChild :: Maybe (BlackNode a)}
这会输出错误:
Multiple declarations of `rightChild'
Declared at: :4:5
:8:5
Multiple declarations of `leftChild'
Declared at: :3:5
:7:5
Multiple declarations of `value'
Declared at: :2:5
:6:5
我已尝试对之前的代码进行多次修改,但都无法编译。这样做的正确方法是什么?
【问题讨论】:
-
遗憾的是,您不能以相同的方式命名两个不同类型的两个字段。尝试将它们命名为
blackValue,..,blackRightChild,红色对应物也类似。 -
@chi 愿你与你同在!那行得通!我很惊讶 Haskell 有这个限制 - 永远不会猜到。你会写这个作为答案吗?我已经花了几个小时来解决这个问题并在整个互联网上进行搜索 - 也许它会对其他人有所帮助。
-
虽然您当然可以强制执行“没有红色节点和红色子节点”不变量,但事实证明,在不破坏性能的情况下强制执行完整的红黑树不变量是非常困难的。在您浏览过有关它的论文之后,我怀疑您会得出与我相同的结论——通常情况下,您最好还是硬着头皮使用 2-3-4 棵树。
-
实际上有一个新的 GHC 功能可以在即将发布的 8.0 版本中解除此限制。
-
@dfeuer 感谢您的评论。如果您愿意分享链接,我将不胜感激。是否有可能强制执行所有内容?我不知道如何强制执行基本的搜索树不变量(即左子树的键是 \leq,而右子树的键是 \geq)。
标签: haskell red-black-tree recursive-datastructures