haskell 如何在编写结构时正确使用构造函数?有哪些方法可以替代Null?

toiithl6  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(145)

我试图用haskell写一棵红黑树,在红黑树的属性中有一个注解,所有不包含数据的叶子都是黑色的。
我想写这样的东西:

data EmptyNode = EmptyNode{
data = ???,
color = ???,  <-- it should black (assume that it is False)
left = ???, 
right = ???
}
data NodeBR a = NodeBR {
  data :: a,
  color :: Bool,
  left :: NodeBR,
  right :: NodeBR
} 

data TreeBR a = EmptyNode | NodeBR a (TreeBR a) (TreeBR a)

我不明白两件事,什么类型适合我在通常的语言中替换Null(我理解你不能在这里使用undefined)并使用构造函数,我如何在EmptyNode中指定颜色默认为False?

ecbunoof

ecbunoof1#

一种解决方案是以更“Haskell”的方式来定义红黑树(简称RBT),因此有两种可能的方式来构造RBT:

  1. Leaf(代码中的EmptyNode
  2. Node a c l r(代码中为NodeBR),其中a是数据,c是颜色,lr也是RBT。
data RBT a = Leaf | Node a Bool (RBT a) (RBT a)

在上面的代码行中,我们定义了带有两个构造函数的数据类型RBT a

  1. Leaf :: RBT a
  2. Node :: a -> Bool -> RBT a -> RBT a -> RBT a
    这意味着:
  3. Leaf的类型为RBT a
  4. Node是一个函数,取aBool(颜色)、RBT a(左树)、RBT a(右树),返回一个RBT a
    因此,在这种情况下,我们不需要为Leaf指定NULL,因为根本不需要这样说(即,对于Leaf,我们想要说没有数据,没有左/右子树)。
    要将Leaf视为黑色,我们可以## Heading ##使用模式匹配在RBT a上定义一个函数:
color :: RBT a -> Bool
color Leaf = False
color (Node _ c _ _) = c

您在代码中提到的record syntax只是生成color函数的语法糖,但在这种情况下,使用记录语法无法生成Leaf情况下的正确代码,因为它们在声明中不相同。
因此,当您必须检查RBT a是否为Leaf时,您可以只使用模式匹配,而不用使用其他语言中的“if-with-null”。
更新:
正如amalloy在注解中提到的,为了更好的可读性,我们可以将颜色定义为一个单独的数据类型:

data Color = Red | Black

data RBT a = Leaf | Node a Color (RBT a) (RBT a)

color :: RBT a -> Color
color Leaf = Black
color (Node _ c _ _) = c

请注意,BoolColor是 * 同构的 *。

相关问题