在Haskell中将值插入有序树中

时间:2010-02-08 14:46:50

标签: sorting haskell insert tree

基本上我已经定义了一个Tree数据类型,其定义如下:

data Tree a = Empty
| Leaf a
| Node (Tree a) a (Tree a)
deriving (Eq, Ord, Show)

现在我必须创建一个函数来将值插入到有序树中(它不必对树进行排序,只需添加值)。这是我到目前为止所提出的:

insert :: a -> Tree a -> Tree a
insert x Empty      = Leaf x
insert x (Leaf m)   | m < x     = Node (Leaf x) m Empty
                    | otherwise = Node Empty m (Leaf x)
insert x (Node l m r)   | x > m     = Node (Leaf l) m (insert x r)
                        | otherwise = Node (insert x l) m (Leaf r)

但是,当我运行此命令时,我收到以下错误消息:

  

无法匹配预期类型'a'(刚性变量)              反对推断类型'树a'       'a'受Main.hs:11:10中'insert'类型签名的约束       在'Leaf'的第一个参数中,即'l'       在'Node'的第一个参数中,即'(Leaf l)'       在表达式中:Node(Leaf l)m(insert x r)

我认为这与类型有关,但我看不出哪里放了任何不应该存在的类型。

3 个答案:

答案 0 :(得分:10)

你的问题是那个

insert x (Node l m r)   | x > m     = Node (Leaf l) m (insert x r)
                        | otherwise = Node (insert x l) m (Leaf r)

应该是

insert x (Node l m r)   | x > m     = Node l m (insert x r)
                        | otherwise = Node (insert x l) m r

因为lr已经是树。

答案 1 :(得分:9)

大致从type-checker-ese翻译成英文:

  

无法匹配预期类型'a'(a   刚性变量)

这意味着它期待一个任意类型a,它也在其他地方使用(因此“僵硬”),所以它不能只采用任何旧类型。

  

针对推断类型'Tree a'

这意味着它发现了Tree包含预期的刚性多态类型的元素。这显然没有意义,所以它抱怨。

  

'a'受Main.hs:11:10

的'insert'类型签名的约束

这只是表示该类型受到限制,因为您在该类型签名中指定了它。

  

在'Leaf'的第一个参数中,即'l'在第一个参数中   'Node'的参数,即'(Leaf l)'在表达式中:Node(Leaf l)m(insert x r)

这只是告诉你它正在抱怨哪个特定术语,并带有一些背景。

因此,要解决问题:变量lTree a,只需要a的上下文。在这种情况下,l显然具有正确的类型,因此错误在于如何使用它。为什么类型检查器要查找类型a?因为您将Tree数据构造函数应用于它。但等等,l已经是Tree a了! et voila ,鳞片从我们的眼睛落下,真相被看到了。

......这只是解释为什么 Edward Kmett 的快速答案是正确的,以及可以用什么样的推理来得出这样的答案的漫长方式。< / p>

答案 2 :(得分:2)

lNode的第一个参数,因此它的类型为Tree a(整个左子树)。另一方面,Leaf只取一个值作为参数,而不是整个树。因此Leaf l给出了类型错误,因为它试图从整棵树中创建一个Leaf。可能你只是想在这个地方l而不是Leaf l

另外,Leaf xNode Empty x Empty之间有什么区别?你确定你需要两个构造函数吗?