2016-02-11 27 views
2

我有一个数据类型:为什么我会遇到这些类型错误?

data Tree = Empty | Node Int Tree Tree 

,我想功能

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

一对用于每个节点。第一个元素是标签(值),第二个元素是深度。

我的意图(原始代码)是这样的:

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) 

但是,这是行不通的。

有什么不对?我使用的弗雷格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. 
+1

弗雷格[与常规哈斯克尔不同](https://github.com/Frege/frege/wiki/Differences-between-Frege-and-Haskell);我认为使用[tag:frege]标签而不是[tag:haskell]更合适。 – Zeta

+0

您无法获取节点的深度。你只能得到它的高度(例如离树叶最远的距离)那么你想得到什么? – gen

+0

@Zeta感谢您的编辑。如果他使用ghci,类型错误将会是同构的。但没关系,我们关心这一点。 :) – Ingo

回答

1

至于错误考虑以下行例如:

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

因为Haskell的功能应用关联到左边,拉链取功能nodeDepth”作为它的第一个参数。要解决此特定错误您可能希望这样写:

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

但你仍然下落不明nodeDepth的”第二个参数,所以在括号中的表达式只返回一个函数,而不是一个列表。

另一个错误是,当您为非空树定义nodeDepth'时:您的模式匹配[level]将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)] 

你可能已经预期。

0

此:

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

zip功能expets两个列表,但既不nodeDepth'也不(Node ...)是列表。然后你将结果(这是一个列表)应用到其他列表[0],这解释了第二个最后的消息。我猜你的意思是写

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

但即使在这种情况下,有一种说法失踪nodeDepth”使括号中的列表中的表达式。

nodeDepth'第二个定义也不会去编译,有以下原因:

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

    一个表达式:B:C

c必须是一个列表(它不是在你的例子)和b不能是列表,并且必须具有与a相同。但是nodeDepth'应该返回一个列表。因此,整个RHS毫无意义,因此你会得到很多错误。

一个技巧在这里:因为你显然不希望的水平是一个列表,无处真传列表来nodeDepth”,难道不更好只需更换模式[level]level

相关问题