2013-01-11 36 views
5

Theo dõi < Thế giới thực Haskell >, người ta nói foldl' là phiên bản nghiêm ngặt của foldl.Ý nghĩa của phiên bản nghiêm ngặt trong haskell là gì?

Nhưng thật khó cho tôi để hiểu, nghĩa là gì strict có nghĩa là gì ??

foldl f z0 xs0 = lgo z0 xs0 
     where 
      lgo z []  = z 
      lgo z (x:xs) = lgo (f z x) xs 


foldl' f z0 xs0 = lgo z0 xs0 
    where lgo z []  = z 
      lgo z (x:xs) = let z' = f z x in z' `seq` lgo z' xs 
+2

So sánh mã nguồn cho hai phiên bản nếp gấp và bạn có thể khai sáng. – augustss

+0

@augustss có thể, bạn có thể trả lời câu hỏi này không? – jackalope

+0

Như bạn có thể thấy, foldl 'tính toán đối số đầu tiên để lgo trước khi cuộc gọi, trong khi foldl sẽ (nói chung) vượt qua một thunk sẽ được đánh giá khi cần thiết. – augustss

Trả lời

6

nếp gấp và nếp gấp (gần đúng) gần giống với ngữ nghĩa tương đương. Sự khác biệt là hiệu suất, đặc biệt là khi bạn đang vượt qua một danh sách lớn. Sự lười biếng có một chi phí của việc xây dựng một thunk và foldl 'là cách hiệu quả hơn để đạt được kết quả đó bởi vì nó không xây dựng một thunk lớn.

Có một bài viết thực sự tốt giải thích điều này một cách chi tiết về Haskell Wiki

chức năng nghiêm ngặt hoạt động giống như chức năng trong C hoặc các ngôn ngữ khác ở chỗ lập luận của họ được đánh giá thường háo hức.

0

Chức năng nghiêm ngặt là hàm có đối số được đánh giá trước cơ thể.

+0

vẫn khó hiểu ... – jackalope

+1

Không, nó không phải là một hàm có đối số được đánh giá trước cuộc gọi. Một chức năng nghiêm ngặt là, một cách chính thức, một hàm đánh giá các đối số của nó. – augustss

+0

@augustss: * vô điều kiện (phải không?) –

12

Nó không được biết đến rộng rãi, nhưng foldl' thực sự không nghiêm ngặt trong đối số tích lũy của nó! Nhớ lại những loại:

foldl' :: (a -> b -> a) -> a -> [b] -> a 

nghiêm minh của nó trong lập luận 2 phụ thuộc vào tính nghiêm minh của hàm trao cho lập luận 1, như bạn thấy nếu bạn vượt qua const:

Prelude Data.List> foldl' (const (+1)) undefined [1] 
2 
Prelude Data.List> foldl' (const (+1)) undefined [1..4] 
5 

Bạn sẽ phải suy nghĩ, ngây thơ, rằng "foldl" là nghiêm ngặt "có nghĩa là" nghiêm ngặt trong các đối số accumulator ". Những mâu thuẫn trên.

Tuy nhiên, nó thậm chí còn xảo quyệt hơn, vì mức độ nghiêm ngặt chỉ là kết quả của ứng dụng chức năng trong trường hợp khuyết điểm của vòng lặp. Vì vậy, bạn vẫn nhận được đáy nếu bạn nhập trường hợp cơ sở, nhưng không phải là trường hợp quy nạp:

Prelude Data.List> foldl' (const (+1)) undefined [] 
*** Exception: Prelude.undefined 

Vì vậy, sự nghiêm khắc in argument 2cũng phụ thuộc vào giá trị lập luận 3!

Đây là cách tôi viết nó: "hoàn toàn" nghiêm ngặt trong đối số thứ 2 của nó.

foldl' f z0 xs0 = go z0 xs0 
    where 
    go !z []  = z 
    go !z (x:xs) = go (f z x) xs 

Đó là thực sự nghiêm ngặt trong số thứ hai của nó, như bạn có thể thấy:

Prelude Data.List.Stream> foldl' (\a b -> 1) undefined [undefined] 
*** Exception: Prelude.undefined 

So với phiên bản Haskell2010:

Prelude Data.List.Stream> Data.List.foldl' (\a b -> 1) undefined [undefined] 
1 

actuall này có một tác động thực tế - các định nghĩa hiện tại sẽ không unbox đối số tích lũy của nó một cách nhất quán.

Lưu ý lịch sử: điều này được phát hiện khi chúng tôi xác định ngữ nghĩa nghiêm ngặt của thư viện danh sách cho giấy kết hợp luồng trong năm 2007 và cách tiếp cận để xác định độ chặt được đưa ra trong số PhD thesis của Duncan Coutt.

Các vấn đề liên quan