Làm chậm fix
gọi f
trên mỗi bước đệ quy, trong khi gọi nhanh f
chính xác một lần. Nó có thể được hình dung với tracing:
import Debug.Trace
fix f = f (fix f)
fix' f = let x = f x in x
facf :: (Int -> Int) -> Int -> Int
facf f 0 = 1
facf f n = n * f (n - 1)
tracedFacf x = trace "called" facf x
fac = fix tracedFacf
fac' = fix' tracedFacf
Bây giờ thử một số hoạt động:
> fac 3
called
called
called
called
6
> fac' 3
called
6
Cụ thể hơn, let x = f x in x
kết quả trong một thunk lười biếng được phân bổ cho x
, và một con trỏ đến thunk này sẽ được chuyển cho f
. Khi đánh giá lần đầu tiên fix' f
, đoạn thunk được đánh giá và tất cả các tham chiếu đến nó (cụ thể là: cái chúng tôi chuyển đến f
) được chuyển hướng đến giá trị kết quả. Nó chỉ xảy ra rằng x
được cung cấp một giá trị cũng chứa tham chiếu đến x
.
Tôi thừa nhận điều này có thể khá khó khăn. Đó là điều mà một người nên quen với khi làm việc với sự lười biếng.
Nguồn
2016-05-21 18:01:47
trên cơ sở nào bạn xác nhận quyền sở hữu là hiệu quả hơn cái kia - bạn có thể cung cấp một số bằng chứng – epsilonhalbe
Vâng, đối với một, có vẻ như nó chạy nhanh hơn. Và ngoài ra, hãy xem tại đây http://h2.jaguarpaw.co.uk/posts/polymorphic-recursion-combinator/ –