2016-09-22 15 views
6

Vì vậy, chức năng Haskell seq buộc đánh giá tham số đầu tiên của nó và trả về giá trị thứ ba. Do đó nó là một toán tử infix. Nếu bạn muốn ép buộc việc đánh giá một biểu thức, tính năng trực quan như vậy sẽ là một toán tử đơn nhất. Vì vậy, thay vìSeq của Haskell được sử dụng như thế nào?

seq :: a -> b -> b 

nó sẽ là

seq :: a -> a 

Do đó, nếu giá trị bạn muốn là a, tại sao trở b và làm thế nào để bạn xây dựng cho sự trở lại của b. Rõ ràng, tôi không nghĩ Haskell. :)

+1

Nếu bạn nhìn vào định nghĩa [đã được định dạng rất kém) của 'foldl''] (https://wiki.haskell.org/Seq), bạn thấy rằng bạn thường chỉ muốn đánh giá nghiêm ngặt một số biến giới hạn trong 'a' mà bạn nạp vào giá trị' b' của bạn. –

Trả lời

15

Cách suy nghĩ về a `seq` b không phải là nó "đánh giá a" nhưng mà nó tạo ra một sự phụ thuộc giữa ab, do đó khi bạn đi đến đánh giá b bạn đánh giá a là tốt.

Điều này có nghĩa là, ví dụ: a `seq` a là hoàn toàn dư thừa: bạn đang yêu cầu Haskell đánh giá a khi bạn đánh giá a. Theo cùng một logic, seq a chỉ với một đối số sẽ không khác biệt gì so với việc chỉ viết a một mình.

Chỉ cần có seq a bằng cách nào đó đánh giá a sẽ không hoạt động. Vấn đề là seq a chính nó là một biểu thức có thể không được đánh giá — nó có thể là sâu bên trong một số khối lồng nhau, ví dụ. Vì vậy, nó sẽ chỉ trở nên có liên quan khi bạn nhận được để đánh giá toàn bộ biểu thức seq a - lúc này bạn sẽ tự mình đánh giá a.

@ Ví dụ của Rhymoid về cách nó được sử dụng trong một nếp gấp nghiêm ngặt (foldl') là tốt. Mục tiêu của chúng tôi là viết một nếp gấp sao cho giá trị lũy kế trung gian của nó (acc) được đánh giá hoàn toàn ở mỗi bước ngay sau khi chúng tôi đánh giá kết quả cuối cùng. Này được thực hiện bằng cách thêm một seq lệch giữa giá trị tích lũy và cuộc gọi đệ quy:

foldl' f z (x:xs) = 
    let z' = f z x in z' `seq` foldl' f z' xs 

Bạn có thể hình dung đây là một chuỗi dài của seq giữa mỗi ứng dụng của f trong nếp gấp, kết nối tất cả trong số họ để kết quả cuối cùng . Bằng cách này khi bạn đánh giá biểu thức cuối cùng (tức là số bạn nhận được bằng cách tổng hợp một danh sách), nó đánh giá các giá trị trung gian (tức là một phần tổng khi bạn gấp trong danh sách) một cách nghiêm ngặt.

+0

Tôi bây giờ nghĩ rằng sự phụ thuộc được tạo ra bởi 'seq' là dư thừa ít nhất trong trường hợp' foldl' như được mô tả ở trên vì 'foldl' thông thường đã áp đặt một ràng buộc phụ thuộc vào' z'' bằng cách sử dụng nó. .dường như. – George

+2

@George 'foldl (\ x y -> 1) undefined [2]' đánh giá thành 1, thay vì cố gắng đánh giá 'undefined'. Bằng cách so sánh, sử dụng các lỗi 'foldl'', vì nó đánh giá nó. – chi

+7

@George Một trong những đặc điểm mà bạn quen với các ngôn ngữ khác không áp dụng cho Haskell là: ứng dụng chức năng không rõ ràng là "sử dụng" tất cả các đối số trong ứng dụng. Đặc biệt, chỉ vì ứng dụng 'foldl 'f z' xs' có' z'' làm đối số không * nhất thiết * (tức là không kiểm tra định nghĩa 'foldl'') có nghĩa là' z'' được sử dụng. Đây là nơi mà đối số của bạn về 'z'' được sử dụng rơi xuống:' z'' là một đối số cho một hàm, do đó không nhất thiết phải được sử dụng. –

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