为什么我会收到这些类型错误?

时间:2016-02-11 01:42:55

标签: tree frege

我有一个数据类型:

data Tree = Empty | Node Int Tree Tree

我希望功能

nodeDepth :: Tree -> [(Int, Int)] 

每个节点一对。第一个元素是label(值),第二个元素是它的深度。

我的意图(原始代码)就像:

nodeDepth (Node label left right) = zip nodeDepth' (Node label left right) [0]
nodeDepth' Empty _ = []
nodeDepth' (Node label left right) [level] = label : nodeDepth' (Node label left right) level : (1 + level)

但这不起作用。

出了什么问题?我正在使用Frege REPL

Error message are like :

E <console>.fr:22: t19906 occurs in type [t19906] rendering expression level{19727} untypable.

E <console>.fr:22: type error in  expression level
    type is   t19906
    used as   [t19906]

E <console>.fr:22: type error in  expression
    nodeDepth' (Node label left right) level:+ 1 level
    type is   [[t19909]]
    used as   [Int]


E <console>.fr:22: [[Int]] is not an instance of Num


E <console>.fr:20: type error in expression nodeDepth'
    type is apparently [t19961]
    used as function


H <console>.fr:20: too many or too few arguments perhaps?


E <console>.fr:20: type error in  expression Node label left right
    type is   Tree
    used as   [t19964]


E <console>.fr:20: type error in expression
    zip nodeDepth' (Node label left right)
    type is apparently [(t19961,t19964)]
    used as function


H <console>.fr:20: too many or too few arguments perhaps?


W <console>.fr:20: application of nodeDepth will diverge.

2 个答案:

答案 0 :(得分:1)

至于错误,请考虑以下行:

nodeDepth (Node label left right) = zip nodeDepth' (Node label left right) [0]

由于Haskell功能应用程序关联到左侧,因此zip将函数nodeDepth'作为其第一个参数。要修复此特定错误,您可能需要写:

zip (nodeDepth' (Node label left right)) [0]

但是你仍然缺少nodeDepth'的第二个参数,所以括号中的表达式只返回一个函数而不是一个列表。

另一个错误是当您为非空树定义nodeDepth'时:您的模式匹配[level]将级别捕获为单个元素并将其传递给同一行上的自身。这只能通过假设级别本身是一个列表来解决,但这也没有太大意义,因为在行的末尾,添加假定级别为数字类型。

nodeDepth' (Node label left right) [level] = label : nodeDepth' (Node label left right) level : (1 + level)

以下函数nodeDepth使用深度优先搜索迭代树,并构造标签列表和各个节点的深度。

data Tree = Empty | Node Int Tree Tree

wikiTree = Node 2 (Node 7 (Node 2 Empty Empty) (Node 6 (Node 5 Empty Empty) (Node 11 Empty Empty))) (Node 5 Empty (Node 9 (Node 4 Empty Empty) Empty))

nodeDepth :: Tree -> [(Int, Int)]
nodeDepth Empty = []
nodeDepth (Node label left right) = nodeDepthAccumulator (Node label left right) 0

nodeDepthAccumulator :: Tree -> Int -> [(Int, Int)]
nodeDepthAccumulator Empty _ = []
nodeDepthAccumulator (Node label left right) depth = (label,depth) : nodeDepthAccumulator left (depth+1) ++ nodeDepthAccumulator right (depth+1)

The tree given by wikiTree

在示例wikiTree上执行nodeDepth:

> nodeDepth wikiTree
> [(2, 0),(7, 1),(2, 2),(6, 2),(5, 3),(11, 3),(5, 1),(9, 2),(4, 3)]

正如您所料。

答案 1 :(得分:0)

此:

zip nodeDepth' (Node label left right) [0]

zip函数会提供两个列表,但nodeDepth'(Node ...)都不是列表。然后将结果(列表)应用于其他列表[0],这解释了最后一条消息。我想你打算写

zip (nodeDepth' (Node label left right)) [0]

但即使在这种情况下,nodeDepth也缺少一个参数&#39;使括号中的表达式成为一个列表。

nodeDepth'的第二个定义也不会编译,原因如下:

  • 使用模式[level]匹配单元素列表,并调用单个元素level。精细。但是你使用level作为nodeDepth&#39;的第二个参数。 (这是一个列表),在表达式1+level中,您将其用作数字。
  • 在像

    这样的表达式中

    a:b:c

c必须是一个列表(在您的示例中不是),b不能是列表,并且必须与a具有相同的类型。但是nodeDepth&#39;应该返回一个列表。因此,整个RHS完全没有意义,因此你会遇到很多错误。

这里有一个提示:因为你显然不希望级别成为一个列表,并且没有真正将列表传递给nodeDepth&#39;,不能用{替换模式[level]更好{1}}?