2012-12-01 51 views
8

Tôi vẫn đang bắt đầu khám phá Haskell. Tôi biết mã này "chạy" trong đơn vị IO. Khi nó đi từ dòng l <- ... đến dòng tiếp theo, số IO - bind được gọi.Tại sao không lười biếng

Người ta có thể nghĩ rằng vì Haskell là lười biếng, l không bao giờ được đánh giá. Nhưng "bind" luôn đánh giá lệnh trước đó, đúng không? Bởi vì chương trình tạo ra lỗi "không tìm thấy tệp".

main = do 
    l <- mapM readFile [ "/tmp/notfound" ] 
    return() 
+1

'l chưa bao giờ được đánh giá' - Hm? Lười biếng không có nghĩa là "không bao giờ", nó có nghĩa là "chưa" hoặc "chỉ khi nó thực sự là cần thiết." –

+1

@RobertHarvey Có, nhưng đối với những người không phải là Haskeller, hãy xem mã nguồn, 'l' không còn được sử dụng nữa. Nhưng nó được sử dụng ngầm, phải không? – Cartesius00

Trả lời

15

Người ta có thể nghĩ rằng vì Haskell là lười biếng, l không bao giờ được đánh giá.

Có, và nó không bao giờ được đánh giá. Tuy nhiên, do định nghĩa của (>>=) trong IO, hành động readFile "/tmp/notfound" được thực thi và điều đó có nghĩa là thời gian chạy cố gắng mở tệp. Nếu không có tệp như vậy, lỗi "Tệp không tìm thấy" được nâng lên. Nếu có một tập tin như vậy, nó sẽ được mở ra, nhưng nội dung của nó sẽ không được đọc cho đến khi được yêu cầu. Ở trên, chúng không được yêu cầu, vì vậy nội dung sẽ không được đọc.

Điều gì được đánh giá ở đây (và thậm chí được thực thi) là hành động sản xuất l. Vì tệp không tồn tại, điều đó làm tăng lỗi.

9

Nếu bạn mở rộng do ký hiệu trong mã của bạn, bạn nhận được:

main = (mapM readFile ["/tmp/notfound"]) >>= (\l -> return()) 

Vì vậy, có, l không bao giờ được đánh giá, nhưng điều đó không có nghĩa là các cuộc gọi đến mapM không bao giờ được đánh giá. >>= luôn luôn cần phải đánh giá toán hạng bên trái của nó để tạo ra một giá trị ít nhất ở mức độ nào đó (ít nhất là trong đơn nguyên IO và trong bất kỳ đơn nguyên nào khác xuất hiện trong tâm trí).

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