2012-06-17 29 views
85

Trong GHCi:Ngoại lệ trong công việc của Haskell như thế nào?

Prelude> error (error "") 
*** Exception: 
Prelude> (error . error) "" 
*** Exception: *** Exception: 

Tại sao ngôn ngữ đầu tiên không phải là ngoại lệ lồng nhau?

+9

Đây là một phép biến đổi mà GHC được phép thực hiện: "Tôi là người biên dịch tự điều hành, và tất cả _ | _s giống với tôi". Bạn có yêu cầu các chi tiết thực hiện khiến hai dòng đó biên dịch khác nhau không? – shachaf

+3

'lỗi' là đặc biệt và không thực sự là một cơ chế ngoại lệ. Đối với các ngoại lệ thực, có thể bắt được, hãy xem đơn vị ['Error'] (http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Error.html). –

+1

Lưu ý, ví dụ, lỗi lỗi '(\ f g x -> f (g x))' '' hoạt động khác với '(.) Lỗi lỗi" "', mặc dù hàm đó tương đương với '(.)'. Có lẽ nó đã làm với các cờ tối ưu hóa mà Prelude đã được biên soạn với. – shachaf

Trả lời

99

Câu trả lời là đây là (hơi ngạc nhiên) ngữ nghĩa của trường hợp ngoại lệ không chính xác

Khi mã tinh khiết có thể được hiển thị để đánh giá một thiết các giá trị đặc biệt (tức là giá trị của error hoặc undefined, và rõ ràng không phải loại ngoại lệ generated in IO), sau đó ngôn ngữ cho phép bất kỳ giá trị nào của tập hợp đó được trả về. Các giá trị vượt trội trong Haskell giống như NaN trong mã dấu chấm động, thay vì các ngoại lệ dựa trên dòng điều khiển trong các ngôn ngữ bắt buộc.

Một Gotcha thỉnh thoảng cho Haskellers thậm chí tiên tiến là một trường hợp như:

case x of 
    1 -> error "One" 
    _ -> error "Not one" 

Kể từ mã để đánh giá một tập hợp các trường hợp ngoại lệ, GHC là miễn phí để chọn một. Với việc tối ưu hóa, bạn có thể tìm thấy điều này luôn luôn đánh giá thành "Không một".

Tại sao chúng tôi thực hiện việc này? Vì nếu không, chúng tôi sẽ hạn chế quá mức thứ tự đánh giá của ngôn ngữ, ví dụ: chúng tôi sẽ phải sửa một kết quả xác định cho:

f (error "a") (error "b") 

bằng ví dụ, yêu cầu nó được đánh giá từ trái sang phải nếu có giá trị lỗi. Rất un-Haskelly!

Vì chúng tôi không muốn làm tê liệt các tối ưu có thể được thực hiện trên mã của chúng tôi chỉ để hỗ trợ error, giải pháp là xác định kết quả là một lựa chọn không xác định từ tập hợp các giá trị ngoại lệ: ngoại lệ không chính xác! Theo một cách nào đó, tất cả các trường hợp ngoại lệ đều được trả về và một trường hợp được chọn.

Thông thường, bạn không quan tâm - ngoại lệ là ngoại lệ - trừ khi bạn quan tâm đến chuỗi bên trong ngoại lệ, trong trường hợp này sử dụng error để gỡ lỗi rất khó hiểu.


Tài liệu tham khảo: A semantics for imprecise exceptions, Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Ngôn ngữ lập trình thiết kế và thực hiện (PLDI'99), Atlanta. (PDF)

+0

Đây là một giải thích tuyệt vời về lý do tại sao GHC được phép thực hiện hai lựa chọn khác nhau tại đây, cảm ơn! Vậy giải thích tại sao nó thực hiện tự do này ở đây là gì? Những biểu hiện này trông rất giống nhau! –

+1

Tôi hiểu rằng GHC chọn một trong các ngoại lệ có thể gặp phải. Nhưng trong ví dụ "trường hợp" của bạn, ngoại lệ "Không một" không thể gặp phải đối với đầu vào là 1, vì vậy tôi vẫn phân loại đó là lỗi. – Peaker

+8

@Peaker xóa mã chết - trình tối ưu hóa không cần xem x để thấy rằng lỗi là kết quả, tất cả các nhánh tạo ra giá trị "giống nhau", vì vậy nó có thể bỏ qua toàn bộ giá trị đầu vào. Không phải là lỗi, trong trường hợp ngoại lệ không chính xác! –

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