2010-08-28 32 views
17

我正在经历Haskell O'Reilly书中的问题。我正在处理的问题是开始Haskell - 获取“不在范围内:数据构造函数”错误

Using the binary tree type that we defined earlier in this chapter, 
write a function that will determine the height of the tree. The height 
is the largest number of hops from the root to an Empty. For example, the 
tree Empty has height zero; Node "x" Empty Empty has height one; 
Node "x" Empty (Node "y" Empty Empty) has height two; and so on. 

我在一个名为ch3.hs的文件中编写我的代码。这里是我的代码:

36 data Tree a = Node a (Tree a) (Tree a) 
37    | Empty 
38    deriving (Show) 
39 
40 --problem 9:Determine the height of a tree 
41 height :: Tree -> Int 
42 height (Tree node left right) = if (left == Empty && right == Empty) then 0 else max (height left) (height right) 

在终端打开ghci并键入:load ch3.hs.当我这样做,我得到以下错误:

Prelude> :load ch3.hs 
[1 of 1] Compiling Main    (ch3.hs, interpreted) 

ch3.hs:42:7: Not in scope: data constructor `Tree' 
Failed, modules loaded: none. 

我想到的是,树的数据构造应该有,因为我在高处方法行定义它。但是当我尝试加载文件时,我被告知数据构造函数不在范围内。感谢您的帮助,并解释为何发生此错误。谢谢, 凯文

回答

21

变化

height (Tree node left right) 

height (Node node left right) 

这意味着匹配的algebraic data type(ADT)的构造作品的模式。 Tree不是构造函数,它是ADT的名称。

顺便说一句,你必须注释掉你的函数签名声明来编译代码,因为它包含一个错误。

您可以然后通过

 
:t height 

检查推断的类型ghcihugs

+1

谢谢,工作。我仍然不完全理解正在发生的事情,并且现在在运行时遇到错误,但会继续盯着思考和调试。 – 2010-08-28 20:17:23

+3

另一个例子可能会使它更容易理解。假设我们正在使用整数,而不是树。 Int是整数类型的名称。您不能添加“Int + Int”,因为Int是类型的名称,而不是返回该类型值的构造函数。像0,1,2这些东西是构造函数,如果你想使用整数,那就是你如何让它们进入你的程序。把这个应用到你的案例中,'Tree'是类型的名称,'Node'(或'Empty')是你如何获得*这种类型的值。 – jrockway 2010-08-29 01:44:34

+0

HaskellWiki也有一个有用的部分,它甚至使用Tree作为示例:http://www.haskell.org/haskellwiki/Constructor – jrockway 2010-08-29 01:45:48

2

您模式匹配对构造,即案件,你Tree ADT的。 Tree就是将它们总结起来。

它更直白就是这样,,最重要的是正确的:

height Empty = 0 
height (Node _ l r) = 1 + max (height l) (height r) 
+2

-1这是错误的。用'高度(节点1(节点2空空)'(节点3空空))'测试''。应该是2,是0 - 对于任何输入都是0,因为OP具有相同的错误。 – delnan 2010-08-28 20:36:26

+0

谢谢。我仍然试图习惯模式匹配。我标记另一个答案是正确的,因为问题是关于数据构造函数的,但这也有帮助。 – 2010-08-28 20:48:05

+0

固定 - 需要添加1的最大值(左侧高度)(右侧高度)的值,因此它不会继续返回0. – 2010-08-28 20:54:31

6

你的代码是错误的,在几个层次上。看起来你误解了代数数据类型。

  • 类型签名是错误的,一个Tree始终是一种特定类型的Tree - 你在其声明中呼吁a,并且其可以是任何类型的(因为你没有约束的话)。所以heigth必须采取某种Tree - Tree SomeType。您可以也应该使用最常用的类型SomeType,即类型变量,如a
  • 当模式匹配时,您指定一个特定的构造函数 - Node a (Tree a) (Tree a)Empty - 进行匹配,而不是整个类型。因此height (Node ...)将匹配Nodeheight (Empty)将匹配Empty,而height (Tree ...)将尝试匹配名为Tree的构造函数,但是没有。这是您收到的错误消息。
  • 你永远不会有比较(通过==)与一个构造函数。如果你写了deriving (Show, Eq)它实际上会工作。但是您应该使用模式匹配来确定您是否已达到Empty
  • 这导致:您只匹配Node,而不是Empty - 您应该为Empty添加子句。
  • 此外,如果您解决了所有上述问题,则对于所有输入,您的函数仍然返回0。你永远不会返回任何东西,但0或最大的儿童'height - 这可以反过来,只能返回0或他们的儿童的最大值,如无限期等。你必须增加每个级别的结果;)
+1

感谢您的帮助。刚开始的时候我还在习惯新语言。 – 2010-08-28 20:49:46