2010-08-28 25 views
17

Tôi đang gặp phải các vấn đề trong cuốn sách Haskell O'Reilly. Vấn đề tôi đang làm việc làBắt đầu Haskell - nhận lỗi "không nằm trong phạm vi: người tạo dữ liệu"

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. 

Tôi đang viết mã của mình trong tệp có tên là ch3.hs. Đây là mã của tôi:

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) 

mở ghci trong thiết bị đầu cuối và nhập: tải ch3.hs. Khi tôi làm điều đó tôi nhận được lỗi sau:

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. 

Tôi mong rằng trình tạo dữ liệu Tree sẽ ở đó, vì tôi đã xác định nó trong các dòng phía trên phương pháp chiều cao. Nhưng khi tôi cố tải tệp, tôi được thông báo rằng trình tạo dữ liệu không nằm trong phạm vi. Tôi đánh giá cao sự giúp đỡ của bạn và giải thích lý do tại sao lỗi này xảy ra. Cảm ơn, Kevin

Trả lời

21

Thay đổi

height (Tree node left right) 

để

height (Node node left right) 

đó có nghĩa là mô hình phù hợp với các công trình trên các nhà thầu của algebraic data type (ADT). Tree không phải là một hàm tạo, nó là tên của ADT.

Btw, bạn phải nhận xét khai báo chữ ký hàm của bạn để biên dịch mã vì mã này chứa lỗi.

Sau đó bạn có thể kiểm tra các loại suy ra qua

 
:t height 

trong ghci hoặc hugs.

+1

Cảm ơn, điều đó đã hiệu quả. Tôi vẫn không hoàn toàn hiểu những gì đang xảy ra, và bây giờ nhận được lỗi trong thời gian chạy, nhưng sẽ tiếp tục nhìn chằm chằm và suy nghĩ và gỡ lỗi. –

+3

Ví dụ khác có thể giúp dễ hiểu hơn. Giả sử chúng ta đang làm việc với các số nguyên chứ không phải cây cối. Int là tên của kiểu số nguyên. Bạn không thể thêm "Int + Int" bởi vì Int là tên của loại, không phải là một hàm tạo trả về một giá trị của kiểu đó. Những thứ như 0, 1, 2, ... là các nhà xây dựng, và nếu bạn muốn làm việc với các số nguyên, đó là cách bạn đưa chúng vào chương trình của bạn. Áp dụng điều này cho trường hợp của bạn, 'Tree' là tên của kiểu, và' Node' (hoặc 'Empty') là cách bạn nhận được một giá trị * của * kiểu đó. – jrockway

+0

HaskellWiki cũng có một phần hữu ích và thậm chí còn sử dụng Tree làm ví dụ: http://www.haskell.org/haskellwiki/Constructor – jrockway

2

Bạn mẫu-trận đấu với constructors, ví dụ: các trường hợp, của Tree ADT của bạn. Tree chỉ là những gì tổng tất cả chúng lên.

Đó là nhiều hơn nữa đơn giản như thế này, , hầu hết tất cả, chính xác:

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

-1 Điều này là sai. Kiểm tra với 'chiều cao (Nút 1 (Node 2 Empty Empty) (Node 3 Empty Empty))'. Nên là 2, là 0 - nó là 0 cho bất kỳ đầu vào nào, vì cùng một lỗi mà OP có. – delnan

+0

Cảm ơn. Tôi vẫn đang cố gắng làm quen với mô hình phù hợp. Tôi đánh dấu câu trả lời khác chính xác bởi vì câu hỏi là về các nhà xây dựng dữ liệu nhưng điều này cũng hữu ích. –

+0

Cố định - cần phải thêm 1 vào giá trị tối đa (chiều cao bên trái) (chiều cao bên phải) để nó không tiếp tục trả về 0. –

6

Mã của bạn là sai, trên nhiều cấp độ. Có vẻ như bạn đã hiểu nhầm các loại dữ liệu đại số.

  • Các loại chữ ký là sai, một Tree luôn luôn là một Tree của một loại hình cụ thể - mà bạn gọi là a trong tuyên bố của mình, và có thể là bất kỳ loại (kể từ khi bạn không hạn chế nó). Vì vậy, heigth phải mất một số Tree của một số loại - một số Tree SomeType. Bạn có thể và nên sử dụng loại chung nhất cho SomeType, tức là biến kiểu như a.
  • Khi đối sánh mẫu, bạn đặt tên cho một hàm tạo cụ thể - Node a (Tree a) (Tree a) hoặc Empty - để khớp với, chứ không phải với toàn bộ loại.Vì vậy, height (Node ...) sẽ khớp với một số Node, height (Empty) sẽ khớp với một số Emptyheight (Tree ...) sẽ cố gắng khớp với một hàm tạo có tên là Tree, nhưng không có giá trị nào. Đó là thông báo lỗi bạn nhận được.
  • Bạn chưa bao giờ từng là so sánh (qua ==) với Trình tạo. Nó thực sự sẽ hoạt động nếu bạn viết deriving (Show, Eq). Nhưng bạn nên sử dụng đối sánh mẫu để xác định xem bạn đã đạt đến một số Empty
  • dẫn đến: Bạn chỉ phù hợp với Node, không phải Empty - bạn nên thêm mệnh đề cho Empty.
  • Ngoài ra, hàm của bạn vẫn trả về 0 cho tất cả các yếu tố đầu vào nếu bạn khắc phục tất cả các vấn đề trên. Bạn không bao giờ trả lại bất cứ điều gì trừ 0 hoặc tối đa của trẻ em 'height - có thể, lần lượt, chỉ trả lại 0 hoặc tối đa của trẻ em' height, v.v ... vô hạn. Bạn phải tăng kết quả ở mỗi cấp;)
+1

Cảm ơn sự giúp đỡ. Tôi mới bắt đầu cách đây một thời gian và tôi vẫn quen với ngôn ngữ mới. –

Các vấn đề liên quan