2013-09-04 21 views
7
data NestedList a = Elem a | List [NestedList a] 
flatten :: NestedList a -> [a] 
flatten (Elem element) = [element] 
flatten (List []) = [] 
flatten (List (first:rest)) = flatten first ++ flatten (List (rest)) 
main = print $ flatten $ List [] 

Tôi đã viết mã đã thấy ở trên trong haskell. Khi tôi thực hiện điều này với bất kỳ thông số khác, ví dụKhông có trường hợp nào cho (Hiển thị a0) phát sinh từ việc sử dụng `in 'Biến kiểu' a0 'là mơ hồ

main = print $ flatten $ List [Elem 1, Elem 2] 
main = print $ flatten $ Elem 1 

Nó cung cấp cho

[1, 2] 
[1] 

tương ứng.

Không thành công khi tôi thực thi nó bằng Danh sách trống.

main = print $ flatten $ List [] 

Thông báo lỗi

No instance for (Show a0) arising from a use of `print' 
The type variable `a0' is ambiguous 
Possible fix: add a type signature that fixes these type variable(s) 
Note: there are several potential instances: 
    instance Show Double -- Defined in `GHC.Float' 
    instance Show Float -- Defined in `GHC.Float' 
    instance (Integral a, Show a) => Show (GHC.Real.Ratio a) 
    -- Defined in `GHC.Real' 
    ...plus 23 others 
In the expression: print 
In the expression: print $ flatten $ List [] 
In an equation for `main': main = print $ flatten $ List [] 

Câu hỏi

  1. Tại sao nó thất bại và làm thế nào tôi có thể sửa lỗi này?
  2. Tôi có nên thay đổi định nghĩa NestedList để chấp nhận số trống List không? Nếu vậy, làm thế nào để tôi làm điều đó. Nó khá khó hiểu.
+3

GHC không có thông tin loại để sử dụng. Khi bạn có 'Elem 1', trong danh sách, cung cấp ràng buộc' Num a', và sau đó GHC có thể mặc định biến kiểu thành 'Integer'. Không có phần tử nào, nó không thể mặc định biến kiểu 'a0'. Cho nó một chữ ký kiểu, 'main = print $ flatten $ (List [] :: NestedList())', ví dụ, do đó trình biên dịch biết loại nào sẽ sử dụng. –

+0

Tại sao lại là downvote? – thefourtheye

Trả lời

7

Vấn đề là trình biên dịch không thể biết loại flatten $ List []. Hãy thử tự mình tìm ra loại hình này, bạn sẽ thấy nó là [a] đối với một số a, trong khi print yêu cầu đối số của nó là một thể hiện của Show[a] là một thể hiện của Show nếu a là một thể hiện của Show. Mặc dù danh sách của bạn trống, vì vậy không cần bất kỳ ràng buộc nào trên a để đại diện cho [], không có cách nào để trình biên dịch biết.

Như vậy, việc đưa một loại chú thích rõ ràng (đối với bất kỳ loại mà một thể hiện của Show tồn tại) nên làm việc:

main = print $ flatten $ List ([] :: [NestedList Int]) 

hoặc

main = print $ flatten $ List ([] :: [NestedList()]) 

hoặc

main = print fl 
    where 
    fl :: [()] 
    fl = flatten $ List [] 
+0

Parens trống có ý nghĩa gì sau 'NestedList' và trong' [()] '? – thefourtheye

+1

@thefourtheye '()' là một tuple có kích thước bằng không. Đó là loại tương đương với Haskell của 'void'. – MathematicalOrchid

+0

Và haskell biết làm thế nào để in một tuple rỗng? – thefourtheye

15

Loại danh sách có tính đa hình. Vì bạn không cung cấp phần tử, chỉ cần hàm tạo danh sách rỗng [], không có cách nào để suy ra loại danh sách này là gì.

Có: [] :: [Int]

hoặc [] :: [Maybe (Either String Double)]. Ai nói?

Bạn đang sử dụng. Cung cấp chú thích kiểu để giải quyết tính đa hình, sau đó GHC có thể gửi đến thể hiện chương trình chính xác.

Ví dụ:

main = print $ flatten $ List ([] :: [Int]) 
2

[] có thể là danh sách các phao, chuỗi, booleans hoặc thực sự bất kỳ loại nào l.Do đó, print không biết trường hợp nào là show để sử dụng.

Làm như thông báo lỗi cho biết và đưa ra loại rõ ràng, như trong ([] :: [Int]).

8

Để thêm vào câu trả lời ở đây, bạn có thể phản đối "nhưng loại danh sách của tôi có chứa gì? Nó không có bất kỳ thứ gì trong đó!"

Vâng, trước hết, nó rất dễ dàng để xây dựng tình huống trong đó nó không rõ ràng hay không danh sách là trống rỗng, và dù sao gõ kiểm tra ghét nhìn vào giá trị, nó chỉ muốn nhìn vào loại. Điều này giúp mọi thứ trở nên đơn giản hơn, bởi vì nó có nghĩa là khi nói đến việc đối phó với các giá trị, bạn có thể chắc chắn rằng bạn đã biết tất cả các loại.

Thứ hai của tất cả, nó thực sự không có vấn đề gì loại danh sách đó là, ngay cả khi nó rỗng:

ghci> print ([] :: [Int]) 
[] 
ghci> print ([] :: [Char]) 
"" 
Các vấn đề liên quan