2012-01-31 35 views
13

Với tôi một Closure là một hàm (lồng nhau?) Với dữ liệu đồng vị trí.Đóng cửa (trong Haskell)

Khi bạn viết phần mềm trong Haskell và xem qua phần sau, bạn thường xuyên tìm thấy các bao đóng mà bạn đã tạo không chủ ý.

Tôi hoàn toàn không nhận được quyền này cho bản thân mình. Trong trường hợp nào tôi cố ý muốn đóng mã? Xét cho cùng, trong tất cả các ví dụ, tôi thấy số lượng dữ liệu đồng vị là tầm thường/nhỏ và do đó nó không hoàn toàn giống với tôi như thể trong thực tế có thể biện minh cho sự sáng tạo (cố ý) của họ. Có mô-đun Haskell nào hỗ trợ tôi trong việc cố ý tạo các bao đóng và ví dụ: lưu trữ chúng trong một bản đồ?

+4

Câu hỏi thú vị… Ý của bạn chính xác là gì khi bị đóng không chủ ý? –

+0

@ Jonathan Sterling chủ yếu là khi bạn tạo các hàm lồng nhau. Thông thường, họ hoàn thành các tiêu chí được gọi là "đóng cửa" –

+0

vì dflemstr chỉ ra rằng bạn đang tạo "đóng cửa" mọi lúc. Đây thậm chí không phải là một khái niệm đáng để có một cái tên trong haskell. Bạn có hiểu currying và một phần ứng dụng, và làm thế nào kiểu chữ ký 'Int -> Int -> Int' tương đương với' Int -> (Int -> Int) '? – jberryman

Trả lời

25

Trong Haskell, các chức năng là một phần thiết yếu của ngôn ngữ, chủ yếu là do Haskell dựa trên Lambda Calculus.

Trong phép tính Lambda, có các hàm có "biến tự do", có nghĩa là chúng sử dụng các biến không được chuyển thành tham số trực tiếp cho chúng. Các hàm có biến miễn phí là những gì bạn sẽ gọi là "đóng cửa" trong trường hợp này.

Bởi vì các hàm có biến miễn phí rất phổ biến trong LC, chúng cũng là một phần không thể tách rời của ngôn ngữ Haskell. Ví dụ, khi bạn viết này:

f a b c = a * b + c 

... bạn cũng có thể viết những dòng này, với cùng một kết quả chính xác:

f a b = \ c -> a * b + c 

... hay thậm chí là:

f a b = let product = a * b in \ c -> product + c 

... các thay đổi tương đương khác:

f a = \ b -> let product = a * b in \ c -> product + c 

Điều này là do Haskell về cơ bản tạo ra các chức năng với các biến miễn phí ở mọi nơi, và do đó, các bao đóng được tạo ra mọi lúc. Một số trong số này có thể được tối ưu hóa bởi trình biên dịch, nhưng nó là an toàn để giả định rằng sẽ có nhiều bao đóng được sử dụng hơn bao giờ bạn có thể tự mình khám phá.

Vì vậy, đừng cố định vị trí đóng cửa; chúng không có gì đặc biệt trong Haskell và được sử dụng mọi lúc.

+0

Tất cả đều hiểu. Vẫn còn những gì không rõ ràng với tôi: Tôi có thể trong Haskell (a) cố ý tạo bao đóng và (b) lưu trữ chúng trong một bản đồ và (c) serialize chúng mà không phiền phức như tôi có thể làm trong Erlang với term_to_binary()? –

+0

@JFritsch, bạn có thể dễ dàng lưu trữ các chức năng trong bản đồ và về "cố ý tạo các bao đóng"; Haskell không có sự phân biệt giữa các bao đóng và các chức năng bình thường, vì vậy nó dễ dàng như việc lưu trữ các chức năng bình thường trong bản đồ. Tuy nhiên, rất khó để tuần tự hóa các hàm, và trong khi có một số hỗ trợ thử nghiệm trong GHC cho nó, thì không có cách nào đáng tin cậy để thực hiện nó. Nhớ lại rằng các biến có thể tham chiếu đến ví dụ: tập tin xử lý, và nếu một đóng cửa dựa trên một biến như vậy, bạn có thể không thực sự chuyển đổi nó thành một dòng bit. – dflemstr

+0

Vì vậy, tôi sẽ không thể tuần tự hóa bản đồ kết quả của mình với Data.Binary? –

3

Thông thường, nếu tôi cần tính toán trước các bảng hoặc một cái gì đó cho một hàm, hoặc có một hàm đòi hỏi nhiều dữ liệu, vâng, điều đó sẽ được thực hiện như là một đóng. Ví dụ, trên bài tập về nhà AI của tôi ngày hôm kia, tôi đã viết một điều học được từ rất nhiều mẫu và sau đó bật ra một hàm (Point -> Bool), nhưng hàm đó phải phụ thuộc vào rất nhiều dữ liệu mà tôi đã tích luỹ từ quá trình học tập .

+0

Bạn có thể giải thích thêm một chút hoặc đăng một số mã mẫu không? –