Haskell树 - 搜索树

时间:2015-01-25 16:22:57

标签: haskell tree

我的任务有问题:我正在尝试编写一个代码,列出我告诉他的所有节点值(例如,所有节点值为4的整个列表)。 / p>

我写了以下内容:

findValue :: a -> (MyTree a) -> [a]
findValue x Leaf = []
findValue x (Node a l r)
    |a == x = x++(findValue x l)++(findValue x r)
    |a /= x = (findValue x l)++(findValue x r)

我已将树定义如下:

data MyTree a = Leaf  | Node a (MyTree a) (MyTree a)

我收到以下错误消息:

Couldn't match expected type ‘[a]’ with actual type ‘a’
      ‘a’ is a rigid type variable bound by
          the type signature for findValue :: a -> MyTree a -> [a]
          at assignment.hs:10:14
    Relevant bindings include
      r :: MyTree a (bound at assignment.hs:12:25)
      l :: MyTree a (bound at assignment.hs:12:23)
      a :: a (bound at assignment.hs:12:21)
      x :: a (bound at assignment.hs:12:11)
      findValue :: a -> MyTree a -> [a]
        (bound at assignment.hs:11:1)
    In the first argument of ‘(++)’, namely ‘x’
    In the expression: x ++ (findValue x l) ++ (findValue x r)

如果有人向我解释错误消息,我会很高兴。提前谢谢!

2 个答案:

答案 0 :(得分:2)

(++)的类型为[a] -> [a] -> [a],但x的类型为a。因此你可以写

x : (findValue x l) ++ (findValue x r) (使用" cons"运算符(:) :: a -> [a] -> [a])或

[x] ++ (findValue x l) ++ (findValue x r)

以下是您应该自行确定的方法:

错误说Couldn't match exptected type '[a]' with actual type 'a' ... in the first argument of '(++)', namely 'x'

这意味着参数x(++)(在指示的行上)应该具有类型[a] 预期类型),但实际上有a类型(推断类型)。

然后,您应该查找(++)的类型签名,看看问题可能是什么(例如使用hooglehayooghci)在您的情况下,问题是(++)的第一个和第二个参数的类型不一样,但它们应该是。

答案 1 :(得分:2)

想想你在做什么。 findValue属于a -> MyTree a -> [a]类型,这意味着x属于a类型。

但是,(++)运算符属于[a] -> [a] -> [a]类型,但您正在编写x ++ (findValue x l) ++ (findValue x r)。因此它会给你一个错误说:

Couldn't match expected type ‘[a]’ with actual type ‘a’
      ‘a’ is a rigid type variable bound by
          the type signature for findValue :: a -> MyTree a -> [a]
          at assignment.hs:10:14
    Relevant bindings include
      r :: MyTree a (bound at assignment.hs:12:25)
      l :: MyTree a (bound at assignment.hs:12:23)
      a :: a (bound at assignment.hs:12:21)
      x :: a (bound at assignment.hs:12:11)
      findValue :: a -> MyTree a -> [a]
        (bound at assignment.hs:11:1)
    In the first argument of ‘(++)’, namely ‘x’
    In the expression: x ++ (findValue x l) ++ (findValue x r)

错误消息清楚地表明它是Couldn't match expected type ‘[a]’ with actual type ‘a’。它进一步告诉你问题在哪里,In the first argument of ‘(++)’, namely ‘x’。它甚至会告诉您在哪里找到该表达式In the expression: x ++ (findValue x l) ++ (findValue x r)

Haskell错误消息可能看起来非常可怕,但它们实际上非常有用且容易理解。不要让像‘a’ is a rigid type variable bound by这样的短语吓到你。

我理解当你读到的第二句话是你不理解的东西时很容易放弃,而且我理解在SO上发表关于它的问题会更容易。帮自己一个忙,不要。了解如何理解错误消息。

给一个男人一条鱼,他会吃一天。教一个人钓鱼,他一辈子都会吃。


顺便说一下,你为什么需要findValue类型的a -> MyTree a -> [a]函数?拥有:

会更有意义
hasValue :: a -> MyTree a -> Bool
hasValue x Leaf         = False
hasValue x (Node a l r)
    | a == x            = True
    | otherwise         = findValue x l || findValue x r

numValue :: a -> MyTree a -> Int
numValue x Leaf         = 0
numValue x (Node a l r)
    | a == x            = depth + 1
    | otherwise         = depth
    where depth = findValue x l + findValue x r

对我来说,拥有findValue函数没有任何意义,因为给定findValue x t结果是:

  1. 空列表或非空列表(分别为FalseTrue)。因此hasValue
  2. 重复的x值列表,在这种情况下只有长度很重要。因此numValue

    findValue :: a -> MyTree a -> [a]
    findValue x t = replicate (numValue x t) x