tôi tò mò làm thế nào để tối ưu hóa mã này:Tối ưu hóa tính toán một phần trong Haskell
fun n = (sum l, f $ f0 l, g $ g0 l)
where l = map h [1..n]
Giả sử rằng f
, f0
, g
, g0
, và h
đều tốn kém, nhưng việc tạo ra và lưu trữ của l
là cực kỳ đắt.
Khi được viết, l
được lưu trữ cho đến khi bộ trả về được đánh giá đầy đủ hoặc thu thập rác. Thay vào đó, length l
, f0 l
và g0 l
tất cả sẽ được thực hiện bất kỳ khi nào một trong số chúng được thực thi, nhưng f
và g
sẽ bị trì hoãn.
Nó xuất hiện hành vi này có thể được cố định bằng cách viết:
fun n = a `seq` b `seq` c `seq` (a, f b, g c)
where
l = map h [1..n]
a = sum l
b = inline f0 $ l
c = inline g0 $ l
Hoặc rất giống nhau:
fun n = (a,b,c) `deepSeq` (a, f b, g c)
where ...
Chúng tôi có lẽ có thể chỉ định một loạt các loại nội bộ để đạt được hiệu quả tương tự như tốt, trông rất đau đớn. Có sự lựa chọn nào khác không?
Ngoài ra, tôi rõ ràng là hy vọng với inline
s của tôi rằng trình biên dịch cầu chì sum
, f0
, và g0
vào một vòng lặp duy nhất xây dựng và tiêu thụ l
hạn bởi hạn. Tôi có thể làm cho điều này rõ ràng thông qua inlining hướng dẫn sử dụng, nhưng that'd suck. Có cách nào để ngăn chặn một cách rõ ràng danh sách l
từ khi được tạo và/hoặc bắt buộc nội tuyến không? Pragmas tạo ra cảnh báo hoặc lỗi nếu nội tuyến hoặc lỗi kết hợp thất bại trong quá trình biên dịch có lẽ?
Là một sang một bên, tôi rất tò mò về lý do tại sao seq
, inline
, lazy
, v.v. đều được xác định theo let x = x in x
trong chế độ Prelude. Điều này chỉ đơn giản là để cung cấp cho họ một định nghĩa cho trình biên dịch để ghi đè?
Để trả lời câu hỏi cuối cùng: http://stackoverflow.com/a/8654407/1011995 –
Có 'f0' và' g0' hoàn toàn tùy ý hoặc có thể được viết dưới dạng 'foldr' không? – dave4420
Sẽ không phải là một lần đơn giản với một (a, b, c) -accumulator đủ ở đây? – Sarah