2010-07-10 30 views
5

tôi có chức năng này (tạo ra dãy Fibonacci):Làm thế nào tôi có thể nhân tố biểu thức Haskell này để tránh tính toán lặp lại?

unfoldr (\(p1, p2) -> Just (p1+p2, (p1+p2, p1))) (0, 1) 

Tại đây, tôi nhận thấy một biểu hiện lặp đi lặp lại, p1+p2, mà tôi muốn đến yếu tố để nó chỉ được tính một lần. Ngoài ra bản thân không phải là một tính đắt tiền, nhưng đối với một phiên bản tổng quát hơn:

unfoldr (\(p1, p2) -> Just (f p1 p2, (f p1 p2, p1))) (0, 1) 
    where f = arbitrary, possibly time-consuming function 

Trong tình hình trên, f p1 p2 được tính hai lần (trừ khi có một số trình biên dịch tối ưu hóa ma thuật Tôi không biết về), mà có thể tạo ra một nút cổ chai hiệu suất nếu f yêu cầu rất nhiều tính toán. Tôi không thể thêm hệ số f p1 p2 vào một số wherep1p2 không nằm trong phạm vi. Cách tốt nhất để nhân tố biểu thức này là gì để f chỉ được tính một lần?

Trả lời

9
unfoldr (\(p1, p2) -> let x = f p1 p2 in Just (x, (x, p1))) (0, 1) 
    where f = arbitrary, possibly time-consuming function 
+0

thankyou! cảm ơn vì đã dành thời gian cho những câu hỏi mới bắt đầu như thế này (: – guhou

2

trong Control.Arrow(&&&) mà có thể được sử dụng trong một cái gì đó như thế này:

unfoldr (\(p1,p2) -> (Just . (id &&& flip (,) p1)) (p1+p2)) (0,1) 

hoặc thậm chí:

unfoldr (Just . (fst &&& id) . (uncurry (+) &&& fst)) (0,1) 

Cũng trong ví dụ của bạn p1+p2 thực sự là tới p1 vì vậy bạn có thể viết lại nó như

tail (unfoldr (\(p1, p2) -> Just (p1, (p1+p2, p1))) (0, 1)) 
Các vấn đề liên quan