2012-05-01 18 views
11

Khi tôi chạy mã lỗi này ...Tại sao GHC không đưa ra cảnh báo thời gian biên dịch cho ngoại lệ "Không khớp trong bản ghi chọn"?

data Person = Adult { pName :: String} 
      | Kid { pName :: String 
        , pAge :: Int 
        } deriving Show 

getAge :: Person -> Int 
getAge p = pAge p 

getName :: Person -> String 
getName p = pName p 

main :: IO() 
main = do 

    let p1 = Kid "fred" 5 
     p2 = Adult "john" 
     ps = [p1, p2] 

    names = map getName ps 
    ages = map getAge ps 

    putStrLn $ "names: " ++ show names 
    putStrLn $ "ages: " ++ show ages 

... Tôi có được điều này trong ghci:

names: ["fred","john"] 

ages: [5,* * * Exception: No match in record selector pAge 

Tôi biết làm thế nào để tránh lỗi này, nhưng tôi đang tự hỏi tại sao biên dịch với "ghc -Wall" không cảnh báo tôi về vấn đề này. Có công cụ nào khác có thể giúp tôi ngăn chặn loại lỗi này không?

+3

Tôi đặt cược những người GHC sẽ sẵn sàng để cảnh báo về điều này. Bạn nên gửi yêu cầu tính năng trên [Trac] (http://hackage.haskell.org/trac/ghc/newticket?type=feature+request)! –

+2

Có một tình cảm chung về sự không hài lòng xung quanh hồ sơ trong biểu mẫu hiện tại của họ. Một số người đang điều tra lựa chọn thay thế. Trong khi chờ đợi, các bản ghi nhiều nhà xây dựng không được đề xuất và phải là cảnh báo của chính họ :-) –

+0

http://hackage.haskell.org/trac/ghc/ticket/7169 - bạn có thể tự thêm mình vào cc. – sdcvvc

Trả lời

6

Có [a] công cụ có thể giúp tôi ngăn chặn loại lỗi này không?

Không, nhưng có thể có.

Như bạn đã biết, cú pháp ghi sẽ tự động tạo các getters có cùng tên với các thuộc tính bạn xác định. Do đó, mã số

data Person = Adult { pName :: String} 
      | Kid { pName :: String 
        , pAge :: Int 
        } deriving Show 

tạo các chức năng pName :: Person -> StringpAge :: Person -> Int. Bây giờ, giả sử Haskell đã loại phụ. Nếu có, thì Kid có thể là loại phụ của PersonpAge có thể có loại thích hợp hơn Kid -> String. Tuy nhiên, Haskell không không có loại phụ và do đó không có loại Kid.

Bây giờ, cho rằng Person -> String là loại cụ thể nhất chúng tôi có thể cung cấp cho pAge, tại sao không cảnh báo rằng pAge là một chức năng một phần tại thời gian biên dịch? Hãy để tôi chuyển hướng các câu hỏi bằng cách tham khảo Danh sách các ví dụ

data List a = Cons { head :: a, tail :: List a } | Empty 

Trong ví dụ này, headtail là hàm từng phần: hai thành phần của một danh sách không rỗng, nhưng (do thiếu subtyping Haskell) accessors vô nghĩa trên danh sách trống. Vì vậy, tại sao không có cảnh báo theo mặc định? Vâng, theo mặc định, bạn biết mã bạn đã viết. Trình biên dịch không cung cấp cảnh báo nếu bạn sử dụng unsafePerformIO, bởi vì bạn là lập trình viên ở đây, bạn dự kiến ​​sẽ sử dụng những thứ như vậy một cách có trách nhiệm.

Vì vậy tl; dr: nếu bạn muốn cảnh báo ở đây:

getAge :: Person -> Int 
getAge p = pAge p 

sau đó bạn đang trên may mắn, bởi vì hệ thống kiểu không có đủ thông tin để suy ra rằng đây là một vấn đề.

Nếu bạn muốn cảnh báo ở đây:

data Person = Adult | Kid { pAge :: Int } 

sau đó tôi chắc chắn rằng nó sẽ là tầm thường để thực hiện: chỉ cần kiểm tra rằng một lĩnh vực nhất định tồn tại trong một số nhà xây dựng nhưng không phải người khác. Nhưng tôi không thấy trước cảnh báo này được sử dụng rộng rãi cho mọi người; một số người có thể phàn nàn rằng đó chỉ là tiếng ồn.

+0

Trình biên dịch có thể nhận thấy, tuy nhiên, * pAge * là một chức năng một phần và có thể cảnh báo người dùng về chức năng đó. Tuy nhiên, có những trường hợp tổng thể của các chức năng không thể được công nhận, do đó người ta cũng sẽ nhận được cảnh báo ở đó. – Ingo

+2

Loại phụ không cần thiết ở đây. @Tad có thể có loại 'Adult' và' Kid' nếu anh ta muốn. Nếu anh ta muốn có một giao diện chung để truy cập vào độ tuổi, anh ta có thể sử dụng một kiểu chữ, hoặc một kiểu 'Person'. –

+0

Dan cho biết: Vì vậy, tại sao không có cảnh báo theo mặc định? Vâng, theo mặc định, bạn biết mã bạn đã viết. Trình biên dịch không cung cấp cảnh báo nếu bạn sử dụng unsafePerformIO, bởi vì bạn là lập trình viên ở đây, bạn dự kiến ​​sẽ sử dụng những thứ như vậy một cách có trách nhiệm. - – Tad

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