Làm thế nào để x có nghĩa là sửa chữa x trong định nghĩa đầu tiên?
fix f = let x = f x in x
Hãy bindings trong Haskell là đệ quy
Trước hết, nhận ra rằng Haskell phép bindings let đệ quy. Những gì Haskell gọi là "let", một số ngôn ngữ khác gọi là "letrec". Điều này cảm thấy khá bình thường đối với các định nghĩa chức năng. Ví dụ:
ghci> let fac n = if n == 0 then 1 else n * fac (n - 1) in fac 5
120
Nhưng nó có vẻ khá lạ đối với định nghĩa giá trị. Tuy nhiên, các giá trị có thể được định nghĩa đệ quy, do tính không nghiêm ngặt của Haskell.
ghci> take 5 (let ones = 1 : ones in ones)
[1,1,1,1,1]
Xem A gentle introduction to Haskell mục 3.3 và 3.4 để biết thêm chi tiết về tính lười biếng của Haskell.
thunks trong GHC
Trong GHC, một biểu hiện như-chưa-unevaluated được bọc trong một "thunk": một lời hứa để thực hiện các tính toán. Các khối chỉ được đánh giá khi chúng hoàn toàn là phải là. Giả sử chúng tôi muốn fix someFunction
. Theo định nghĩa của fix
, đó là
let x = someFunction x in x
Bây giờ, những gì GHC thấy là một cái gì đó như thế này.
let x = MAKE A THUNK in x
Vì vậy, vui vẻ tạo một đoạn cho bạn và di chuyển ngay cho đến khi bạn yêu cầu biết thực tế là x
.
đánh giá mẫu
Cái vẻ thunk của chỉ xảy ra để đề cập đến bản thân. Hãy lấy ví dụ ones
và viết lại để sử dụng fix
.
ghci> take 5 (let ones recur = 1 : recur in fix ones)
[1,1,1,1,1]
Vậy nội dung đó sẽ như thế nào?
Chúng tôi có thể nội tuyến ones
làm chức năng ẩn danh \recur -> 1 : recur
để có trình diễn rõ ràng hơn.
take 5 (fix (\recur -> 1 : recur))
-- expand definition of fix
take 5 (let x = (\recur -> 1 : recur) x in x)
Bây giờ sau đó, những gì làx
? Vâng, mặc dù chúng tôi không hoàn toàn chắc chắn x
là gì, chúng tôi vẫn có thể đi qua với các ứng dụng chức năng:
take 5 (let x = 1 : x in x)
Hey nhìn, chúng tôi lại định nghĩa chúng tôi đã có trước đó.
take 5 (let ones = 1 : ones in ones)
Vì vậy, nếu bạn tin rằng bạn hiểu làm thế nào rằng một công trình, sau đó bạn có một cảm giác tốt về cách fix
công trình.
Có lợi thế nào để sử dụng định nghĩa đầu tiên trong lần thứ hai?
Có. Vấn đề là phiên bản thứ hai có thể gây ra rò rỉ không gian, ngay cả khi tối ưu hóa. Xem GHC trac ticket #5205, cho một vấn đề tương tự với định nghĩa của forever
. Đây là lý do tại sao tôi đề cập đến khối: bởi vì let x = f x in x
chỉ phân bổ một đoạn: đoạn x
.
Định nghĩa đầu tiên hiệu quả hơn vì nó liên kết với nhau. Ví dụ, so sánh 'fix1 (1 :) !! 1000000' và 'fix2 (1 :) !! 1000000'. – is7s
'Quan hệ hôn' nghĩa là gì? Bạn có thể chỉ cho tôi một liên kết? –
@VansonSamuel http://www.haskell.org/haskellwiki/Tying_the_Knot –