Giống như tiêu đề nói: có gì đảm bảo cho đơn vị trả về hàm Haskell được đánh giá? Người ta sẽ nghĩ rằng không cần phải chạy bất kỳ loại đánh giá nào trong trường hợp như vậy, trình biên dịch có thể thay thế tất cả các cuộc gọi như vậy bằng một ()
giá trị ngay lập tức trừ khi có yêu cầu rõ ràng về tính nghiêm ngặt, trong trường hợp đó, mã có thể phải quyết định liệu có nên quyết định hay không trở lại ()
hoặc dưới cùng.
Tôi đã thử nghiệm điều này trong GHCi và có vẻ như điều ngược lại xảy ra, đó là, một chức năng như vậy dường như được đánh giá. Một ví dụ rất nguyên thủy sẽ là
f :: a -> ()
f _ = undefined
Đánh giá f 1
ném một lỗi do sự hiện diện của undefined
, vì vậy một số đánh giá chắc chắn xảy ra. Tuy nhiên, không rõ việc đánh giá đi sâu đến đâu; đôi khi nó dường như đi sâu đến mức cần thiết để đánh giá tất cả các lệnh gọi hàm trả về ()
. Thí dụ:
g :: [a] -> ()
g [] = ()
g (_:xs) = g xs
Mã này vòng lặp vô thời hạn nếu được trình bày với g (let x = 1:x in x)
. Nhưng sau đó
f :: a -> ()
f _ = undefined
h :: a -> ()
h _ = ()
có thể được sử dụng để hiển thị h (f 1)
lợi nhuận đó ()
, vì vậy trong trường hợp này, không phải tất cả các biểu thức con có giá trị đơn vị đều được ước tính. Quy tắc chung ở đây là gì?
ETA: tất nhiên tôi biết về sự lười biếng. Tôi đang hỏi điều gì ngăn cản các nhà văn trình biên dịch làm cho trường hợp cụ thể này thậm chí còn lười hơn bình thường.
ETA2: tóm tắt các ví dụ: GHC dường như đối xử ()
chính xác như bất kỳ loại nào khác, tức là như có một câu hỏi về giá trị thường xuyên nào sinh sống trong loại nên được trả về từ một hàm. Thực tế là chỉ có một giá trị như vậy dường như không được (ab) sử dụng bởi các thuật toán tối ưu hóa.
ETA3: khi tôi nói Haskell, ý tôi là Haskell-as-định-by-the-Report, không phải Haskell-the-H-in-GHC. Có vẻ như là một giả định không được chia sẻ rộng rãi như tôi tưởng tượng (chiếm 100% số độc giả), hoặc tôi có thể đã có thể đặt ra một câu hỏi rõ ràng hơn. Mặc dù vậy, tôi rất tiếc khi thay đổi tiêu đề của câu hỏi, vì ban đầu nó đã hỏi những gì đảm bảo có chức năng như vậy được gọi.
ETA4: có vẻ như câu hỏi này đã chạy đúng hướng của nó và tôi đang xem xét nó chưa được trả lời. (Tôi đang tìm kiếm một chức năng 'câu hỏi gần' nhưng chỉ tìm thấy 'trả lời câu hỏi của riêng bạn' và vì không thể trả lời được, tôi đã không đi theo con đường đó.) Không ai đưa ra bất cứ điều gì từ Báo cáo sẽ quyết định theo cách đó , điều mà tôi mong muốn diễn giải như một câu trả lời mạnh mẽ nhưng không chắc chắn 'không đảm bảo cho ngôn ngữ như vậy'. Tất cả những gì chúng ta biết là việc triển khai GHC hiện tại sẽ không bỏ qua việc đánh giá chức năng như vậy.
Tôi đã gặp phải vấn đề thực tế khi chuyển ứng dụng OCaml sang Haskell. Ứng dụng ban đầu có cấu trúc đệ quy lẫn nhau gồm nhiều loại và mã đã khai báo một số hàm được gọi là assert_structureN_is_correct
N trong 1..6 hoặc 7, mỗi hàm trả về đơn vị nếu cấu trúc thực sự chính xác và ném ngoại lệ nếu không phải là cấu trúc . Ngoài ra, các hàm này gọi nhau khi chúng phân tách các điều kiện chính xác. Trong Haskell, điều này được xử lý tốt hơn bằng cách sử dụng Either String
đơn nguyên, vì vậy tôi đã sao chép nó theo cách đó, nhưng câu hỏi như một vấn đề lý thuyết vẫn còn. Cảm ơn tất cả các đầu vào và trả lời.
f 1
được "thay thế" bởi undefined
trong mọi trường hợp.
... -> ()
có thể 1) chấm dứt và trả về ()
, 2) chấm dứt với lỗi ngoại lệ / thời gian chạy và không trả về bất cứ thứ gì, hoặc 3) phân kỳ (đệ quy vô hạn). GHC không tối ưu hóa mã chỉ giả sử 1) có thể xảy ra: nếu f 1
được yêu cầu, nó không bỏ qua đánh giá và trả về ()
. Ngữ nghĩa của Haskell là đánh giá nó và xem điều gì xảy ra giữa 1,2,3.
()
(loại hoặc giá trị) trong câu hỏi này. Tất cả các quan sát tương tự xảy ra nếu bạn thay thế () :: ()
bằng, nói, 0 :: Int
ở mọi nơi. Đây là tất cả chỉ là hậu quả cũ nhàm chán của đánh giá lười biếng.
()
loại, ()
và undefined
.
h1::()->() ; h1 () = ()
vàh2::()->() ; h2 _ = ()
. Chạy cả haih1 (f 1)
vàh2 (f 1)
, và thấy rằng chỉ có một yêu cầu đầu tiên(f 1)
.