Đây là một tính năng của trình biên dịch GHC. Về cơ bản, GHC có thể nhận ra khi một danh sách được sử dụng trong một "đường ống", và có thể chuyển đổi toàn bộ cấu trúc thành tương đương với while
vòng trong C mà không phân bổ một danh sách nào cả.
Lý do tại sao tính năng này hoạt động với foldr
và không foldl
phụ thuộc vào chức năng g
mà bạn đang sử dụng trong ví dụ của mình. Kể từ foldr
, trái ngược với foldl
, tích lũy kết quả của hàm được đưa ra làm tham số (aka: foldl
cần toàn bộ danh sách trước khi nó có thể bắt đầu thực sự đánh giá hàm g
, do đó, nó tạo ra một lượng lớn các hàm không được đánh giá và phần tử cuối cùng trong danh sách là kết quả của nó - đó là lý do tại sao nó sử dụng nhiều bộ nhớ hơn trong trường hợp này - trong khi foldr
có thể bắt đầu đánh giá g
ngay khi nó nhận được bất kỳ đầu vào danh sách nào), nó được gọi là "nghiêm ngặt" trong bộ tích lũy của nó, và một số giả định có thể được thực hiện bởi trình biên dịch có thể dẫn đến tối ưu hóa.
Nếu, ví dụ, hàm g
mang lại giá trị là danh sách, nó có thể tiếp tục chiến lược tối ưu hóa "đường ống" nói trên, về cơ bản xử lý foldr
như map
và tạo toàn bộ cấu trúc (từ danh sách tạo danh sách) thành một vòng lặp nghiêm ngặt. Điều này chỉ có thể bởi vì các foldr
sản lượng chính xác một yếu tố danh sách cho mỗi yếu tố danh sách nó tiêu thụ, mà foldl
không được đảm bảo để làm (đặc biệt là cho danh sách vô hạn).
cảm ơn. tôi chọn câu trả lời này vì nó phân biệt rõ ràng giữa foldr và foldl. – vis