hGetContents
không quá lười, nó chỉ cần được sáng tác với những thứ khác một cách thích hợp để có được hiệu quả mong muốn. Có thể tình hình sẽ rõ ràng hơn nếu nó được đổi tên thành exposeContentsToEvaluationAsNeededForTheRestOfTheAction
hoặc chỉ listen
.
withFile
mở tệp, làm điều gì đó (hoặc không có gì, như bạn vui lòng - chính xác những gì bạn yêu cầu trong mọi trường hợp) và đóng tệp.
Nó sẽ hầu như không đủ để đưa ra tất cả những bí ẩn của 'lười biếng IO', nhưng xem xét tại sự khác biệt này trong bracketing
good file operation = withFile file ReadMode (hGetContents >=> operation >=> print)
bad file operation = (withFile file ReadMode hGetContents) >>= operation >>= print
-- *Main> good "lazyio.hs" (return . length)
-- 503
-- *Main> bad "lazyio.hs" (return . length)
-- 0
thô sơ đặt, bad
sẽ mở ra và đóng lại các tập tin trước khi nó bất cứ điều gì; good
thực hiện mọi thứ ở giữa việc mở và đóng tệp. Hành động đầu tiên của bạn là giống như bad
.withFile
nên chi phối tất cả các hành động bạn muốn thực hiện mà phụ thuộc vào xử lý.
Bạn không cần người thực thi nghiêm ngặt nếu bạn đang làm việc với String
, tệp nhỏ, v.v., chỉ là ý tưởng về cách bố cục hoạt động. Một lần nữa, trong bad
tất cả những gì tôi 'làm' trước khi đóng tệp là exposeContentsToEvaluationAsNeededForTheRestOfTheAction
. Trong good
tôi soạn exposeContentsToEvaluationAsNeededForTheRestOfTheAction
với phần còn lại của hành động mà tôi có trong đầu, sau đó đóng tệp.
Các quen thuộc length
+ seq
lừa được đề cập bởi Patrick, hoặc length
+ evaluate
đáng để biết; hành động thứ hai của bạn với putStrLn txt
là một biến thể. Nhưng tổ chức lại là tốt hơn, trừ khi lười biếng IO là sai cho trường hợp của bạn.
$ time ./bad
bad: Prelude.last: empty list
-- no, lots of Chars there
real 0m0.087s
$ time ./good
'\n' -- right
()
real 0m15.977s
$ time ./seqing
Killed -- hopeless, attempting to represent the file contents
real 1m54.065s -- in memory as a linked list, before finding out the last char
Nó đi mà không nói rằng ByteString và văn bản có giá trị biết về, nhưng tổ chức lại với đánh giá trong tâm trí là tốt hơn, vì ngay cả với họ các biến thể Lazy thường những gì bạn cần, và sau đó họ đòi hỏi nắm bắt sự phân biệt tương tự giữa các hình thức thành phần. Nếu bạn đang đối phó với một trong những trường hợp (bao la) các trường hợp loại IO này không phù hợp, hãy xem enumerator
, conduit
và đồng sự, tất cả đều tuyệt vời.
Bạn có thể hiển thị mã nơi bạn sử dụng 'hClose' không? Có vẻ như bạn đang đóng cửa trước khi yêu cầu đầu vào. –