2012-10-21 27 views
8

Tôi cố gắng để tìm ra danh sách với tổng nhỏ nhất của các yếu tố .:Tại sao tôi nhận được lỗi Không thể suy luận (Ord a)?

shortest :: (Num a) => [[a]] -> [a] 
shortest [] = [] 
shortest (x:xs) = if sum x < sum (shortest xs) then x else shortest xs 

Điều đó mang lại cho tôi những lỗi sau:

Could not deduce (Ord a) arising from a use of `<' 
from the context (Eq a) 
    bound by the type signature for shortest :: Eq a => [[a]] -> [a] 
    at code.hs:(8,1)-(9,71) 
Possible fix: 
    add (Ord a) to the context of 
    the type signature for shortest :: Eq a => [[a]] -> [a] 
In the expression: sum x < sum (shortest xs) 
In the expression: 
    if sum x < sum (shortest xs) then x else shortest xs 
In an equation for `shortest': 
    shortest (x : xs) 
     = if sum x < sum (shortest xs) then x else shortest xs 

Tại sao không phải là chức năng typecheck?

+0

'ngắn nhất' không thực sự là tên phù hợp cho điều này, phải không? - Xem xét sử dụng 'minimumBy (so sánh \' trên \ 'tổng hợp)', với các hàm bậc cao hơn từ 'Data.List' và' Data.Function'. – leftaroundabout

+1

Để hiểu vấn đề này, điều quan trọng là phải biết rằng không phải tất cả các số đều có thể được đặt hàng. Ví dụ, hãy xem xét các số phức như '1 + 2i'; không có cách nào để sắp xếp chúng. – dflemstr

+1

@leftaroundabout đã đề xuất giải pháp sử dụng chức năng thư viện; nhưng nếu bạn vẫn muốn viết nó từ đầu như một bài tập, ngoài việc sửa chữa vấn đề chữ ký, bạn cần xem xét giá trị của 'shortest []' hay nói cách khác, cơ sở của đệ quy là gì gợi ý: 'tối thiểu' và' tối đa' thường không được xác định cho danh sách trống). –

Trả lời

15

Có hai loại lớp liên quan đến mã này: NumOrd. Lưu ý rằng một loại có thể là thành viên Num và không phải là Ord và ngược lại.

Loại sumNum a => [a] -> a để các yếu tố đầu vào là shortest cần phải là thành viên của Num. Bạn cũng làm như sau trong mã của bạn:

sum x < sum (shortest xs) 

Điều này có nghĩa rằng bạn đang sử dụng các nhà điều hành < trên a s, nhưng trong chữ ký kiểu của bạn, bạn chưa cần thiết rằng a s là một thể hiện của Ord trong đó xác định <:

class Eq a => Ord a where 
    compare :: a -> a -> Ordering 
    (<) :: a -> a -> Bool 
    ... 

Vì vậy, bạn cần phải thêm yêu cầu đó để chữ ký kiểu của bạn:

shortest :: (Ord a, Num a) => [[a]] -> [a] 

Hoặc bạn có thể loại bỏ chữ ký loại.

+4

Một cách để chẩn đoán loại vấn đề này và để tìm hiểu thêm về các loại và kiểu chữ cùng một lúc, là tạm thời loại bỏ chữ ký loại, nạp mô-đun vào GHCi, sau đó nhập ": t shortest" để xem loại trình biên dịch được gán cho nó. Tương tự, nếu bạn đã loại bỏ chữ ký loại, hãy thử thêm chữ ký để xem liệu hàm của bạn có chữ ký kiểu mà bạn mong đợi hay không. Tôi đã học được rất nhiều bằng cách sử dụng kỹ thuật này. – mhwombat

5

Num không bao gồm Ord, vì vậy bạn thiếu ràng buộc Ord trên a trong chữ ký loại. Nó phải là

shortest :: (Num a, Ord a) => [[a]] -> [a] 

Bạn có thể xóa chữ ký loại và GHC sẽ suy ra điều này cho bạn.

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