开始Haskell - 得到"不在范围内:数据构造函数"错误

Kev*_*rke 20 haskell scope

我正在查看Haskell O'Reilly书中的问题.我正在处理的问题是

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.
Run Code Online (Sandbox Code Playgroud)

我正在将我的代码写在一个名为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) 
Run Code Online (Sandbox Code Playgroud)

在终端中打开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.
Run Code Online (Sandbox Code Playgroud)

我希望Tree数据构造函数应该在那里,因为我在height方法上面的行中定义了它.但是当我尝试加载文件时,我被告知数据构造函数不在范围内.感谢您对此错误发生原因的帮助和解释.谢谢,凯文

max*_*zig 22

更改

height (Tree node left right) 
Run Code Online (Sandbox Code Playgroud)

height (Node node left right)
Run Code Online (Sandbox Code Playgroud)

这意味着模式匹配适用于代数数据类型(ADT)的构造函数.Tree不是构造函数,它是ADT的名称.

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

然后,您可以通过检查推断类型

:t height

ghci拥抱.

  • 另一个例子可能会让它更容易理解.让我们假装我们正在使用整数,而不是树.Int是整数类型的名称.您不能添加"Int + Int",因为Int是类型的名称,而不是返回该类型值的构造函数.像0,1,2 ......这样的东西是构造函数,如果你想使用整数,那就是你如何将它们运用到你的程序中.将此应用于您的案例,`Tree`是该类型的名称,`Node`(或`Empty`)是您获得该类型*的值*. (3认同)

小智 5

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

  • 类型签名是错误的,a Tree始终是Tree特定类型的 - 您a在其声明中调用,并且可以是任何类型(因为您没有约束它).所以heigth必须采取Tree某种类型 - a Tree SomeType.您可以而且应该使用最通用的类​​型SomeType,例如类型变量a.
  • 在模式匹配时,您将特定构造函数命名为 - Node a (Tree a) (Tree a)Empty- 以匹配,而不是作为整体类型.所以height (Node ...)匹配a Node,height (Empty)匹配a Empty,并height (Tree ...)尝试匹配一个名为的构造函数Tree,但没有.这是你收到的错误信息.
  • 你永远不会比较(通过==)一个构造函数.如果你写的话它实际上会起作用deriving (Show, Eq).但是你应该使用模式匹配来确定你是否达到了Empty
  • 这导致:你只是匹配Node,而不是Empty- 你应该添加一个条款Empty.
  • 此外,如果您修复了上述所有问题,您的函数仍会为所有输入返回0.除了0或者最大的孩子之外,你永远不会返回任何东西height- 反过来,这可以只返回0或者他们孩子的最大值height等等.你必须在每个级别增加结果;)

  • 谢谢您的帮助。我才刚开始不久,但仍对新语言已经习以为常。 (2认同)