Tôi có mô phỏng với nhiều cuộc gọi đến các chức năng của type F = A -> B -> C -> D
, trong đó A
.. D
là các loại cụ thể.Ghi lại đối số độc lập
Các đối tượng thuộc loại A
có tuổi thọ trung bình. (Đó là bộ gen của codegolf's ratrace.)
Tính toán đắt nhất phát sinh từ tham số A
. Tôi có thể dễ dàng memoize như thế này:
f1 :: F
f1 a = let expensive = trace "expensive computation!" $ expensiveComputation a
in \b c -> expensive
và giữ một số tiền xử lý expensive
giá trị thông qua ứng dụng phần:
preProz :: [B -> C -> D]
preProz = [f1 [], f1 [False], f2 []]
Các dấu vết cho thấy preProz <*> [[],[[]]] <*> [1,2]
không recompute các giá trị để tôi ưa thích.
Bây giờ tôi đã phát hiện ra rằng một số trong số F
của tôi cũng sẽ được hưởng lợi từ việc xử lý trước B
. tiền xử lý này là độc lập từ A
, và, trên thực tế, memoizing như thế này không có lợi ích
f2 a = let expensive = trace "expensive computation!" $ expensiveComputation a
in \b -> let dear = trace "expensive computation!" $ expensiveComputation b
in expensive + dear
vì dear
được tính toán lại, thậm chí là b
s bằng nhau.
Những gì tôi cần là một cái gì đó như:
(B -> e) -> A -> e -> C -> D
nơi e
nên memoized. Loại e
là loại tồn tại ở đây. Nhưng điều này buộc tôi phải tính lại tất cả các giá trị A
cho mỗi B
, điều này cũng không tốt, và tôi không thể lưu các số e
s, riêng tư cho hàm.
Làm cách nào để ghi nhớ cùng 2 thông số một cách độc lập?
Quá trình xử lý trước A có phụ thuộc vào B hay ngược lại không? Nếu tiền xử lý không phụ thuộc vào các đối số khác, tại sao không chỉ di chuyển nó của hàm: 'f1 <$> [procA a1, procA a2] <*> [procB b1, procB b2] <*> ...' Bây giờ tiền xử lý được đảm bảo để chạy chỉ một lần cho mỗi đối số. –
Tôi có nghĩa là "di chuyển nó ra khỏi chức năng". –
"không tính toán lại các giá trị được [như?] Dự định" là một cụm từ không rõ ràng: nó cũng có thể có nghĩa là "Tôi dự kiến nó sẽ tính lại, và nó không" – chi