2010-08-28 65 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