Tóm lại, không thường xuyên như bạn nghĩ. Lý do là "các kỹ thuật ưa thích" như hợp nhất luồng được sử dụng khi các thư viện được triển khai và người dùng thư viện không cần phải lo lắng về chúng.
Cân nhắc Data.List.map
. Các gói phần mềm cơ sở xác định map
như
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
này map
là tự đệ quy, vì vậy GHC sẽ không inline nó.
Tuy nhiên, base
cũng định nghĩa các quy tắc viết lại như sau:
{-# RULES
"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f
"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f.g)
#-}
này thay thế sử dụng của map
qua foldr/build fusion, sau đó, nếu chức năng không thể hợp nhất, thay thế nó bằng bản gốc map
. Bởi vì phản ứng tổng hợp xảy ra tự động, nó không phụ thuộc vào người dùng đang nhận thức được nó.
Như bằng chứng cho thấy tất cả các công trình này, bạn có thể kiểm tra những gì GHC tạo cho đầu vào cụ thể. Đối với chức năng này:
proc1 = sum . take 10 . map (+1) . map (*2)
eval1 = proc1 [1..5]
eval2 = proc1 [1..]
khi biên soạn với -O2, GHC cầu chì tất cả các proc1
thành một dạng đệ quy đơn (như đã thấy trong đầu ra cốt lõi với -ddump-simpl
).
Tất nhiên, có những giới hạn cho những kỹ thuật này có thể thực hiện được.Ví dụ: chức năng trung bình ngây thơ, mean xs = sum xs/length xs
có thể dễ dàng được chuyển đổi thành một lần và frameworks exist that can do so automatically, tuy nhiên hiện tại không có cách nào để tự động dịch giữa các hàm chuẩn và khung kết hợp. Vì vậy, trong trường hợp này, người dùng cần phải nhận thức được các hạn chế của mã trình biên dịch tạo ra.
Vì vậy, trong nhiều trường hợp, trình biên dịch đủ nâng cao để tạo mã nhanh và thanh lịch. Biết khi nào họ sẽ làm như vậy, và khi trình biên dịch có khả năng rơi xuống, IMHO là một phần lớn trong việc học cách viết mã Haskell hiệu quả.
Tôi đã chỉnh sửa trong các liên kết cho bạn và upvoted. Câu trả lời chính xác! – ehird
Ahh, tuyệt vời, điều này vẽ một bức tranh rõ ràng hơn nhiều, cảm ơn bạn! –
Ý của bạn là 'g (x: xs) = 2 * x: g xs'? – pat