2012-03-03 26 views
17

Ý tôi là định nghĩa một thể hiện của một loại lớp áp dụng trong phạm vi địa phương (let hoặc where) trong một hàm. Quan trọng hơn, tôi muốn có các hàm trong trường hợp này là đóng, nghĩa là có thể đóng các biến trong phạm vi từ vựng trong đó cá thể được định nghĩa (có nghĩa là cá thể có thể hoạt động khác trong lần sau hàm được gọi).Có thể có một cá thể kiểu chữ "cục bộ" không?

Tôi có thể cung cấp cho bạn một trường hợp sử dụng đơn giản cho việc này. Giả sử tôi có một hàm hoạt động trên một kiểu dựa trên một lớp kiểu. Trong ví dụ này, tôi sử dụng bình phương, hoạt động trên bất kỳ loại nào có trường hợp Num (có, bình phương rất đơn giản và có thể dễ dàng được triển khai lại, nhưng nó đang ở trong cái gì đó có thể phức tạp hơn). Tôi cần để có thể sử dụng chức năng hiện tại như-là (không thay đổi hoặc thực hiện lại nó).

square :: Num a => a -> a 
square x = x * x 

Bây giờ, giả sử tôi muốn sử dụng thao tác này trong số học mô-đun, tức là nhân, v.v. mod một số. Điều này sẽ dễ thực hiện đối với bất kỳ cơ sở modulo cố định nào, nhưng tôi muốn có một cái gì đó chung chung mà tôi có thể tái sử dụng cho các cơ sở modulo khác nhau. Tôi muốn để có thể xác định một cái gì đó như thế này:

newtype ModN = ModN Integer deriving (Eq, Show) 

-- computes (x * x) mod n 
squareModN :: 
squareModN x n = 
    let instance Num ModN where 
    ModN x * ModN y = ModN ((x * y) `mod` n) -- modular multiplication 
    _ + _ = undefined   -- the rest are unimplemented for simplicity 
    negate _ = undefined 
    abs _ = undefined 
    signum _ = undefined 
    fromInteger _ = undefined 
    in let ModN y = square (ModN x) 
    in y 

Mục đích của việc này là tôi cần phải sử dụng các chức năng từ trên cao (square) mà yêu cầu đối số của nó là một loại đó là một thể hiện của một số loại lớp. Tôi định nghĩa một kiểu mới và biến nó thành một thể hiện của Num; tuy nhiên, để nó thực hiện đúng số học modulo, nó phụ thuộc vào cơ sở modulo n, do thiết kế chung của chức năng này, có thể thay đổi từ cuộc gọi đến cuộc gọi. Tôi muốn xác định các hàm mẫu như một lần gọi lại "callbacks" (nếu bạn muốn) cho hàm square để tùy chỉnh cách nó thực hiện các hoạt động lần này (và chỉ lần này).

Một giải pháp có thể là tích hợp "biến đóng" trực tiếp vào chính kiểu dữ liệu (tức là ModN (x, n) để đại diện cho số và căn cứ), và các thao tác có thể trích xuất thông tin này từ các đối số. Tuy nhiên, điều này có một số vấn đề: 1) Đối với các hàm đa đối số (ví dụ: (*)), nó sẽ cần phải kiểm tra vào thời gian chạy mà các thông tin này phù hợp, rất xấu; và 2) thể hiện có thể chứa 0 giá trị "đối số" mà tôi có thể muốn phụ thuộc vào các biến đóng, nhưng trong đó, vì chúng không chứa đối số, không thể trích xuất chúng từ các đối số.

+2

Không, bạn không thể có các phiên bản cục bộ. Đối với số học mô-đun Oleg Kiselyov và CC Shan đã giải quyết được vấn đề trong bài báo "Cấu hình ngầm định" của họ - http://www.cs.rutgers.edu/~ccshan/prepose/prepose.pdf. Cá nhân tôi có xu hướng tránh điều này và chỉ đơn giản là tạo một kiểu mới cho cơ sở mô-đun - tức là Z7, Z12. Conal Elliott có một mô hình khác để lựa chọn các lớp kiểu thay thế, xem CxMonoid trong bài báo "Tính toán theo hướng dữ liệu ứng dụng" - http://conal.net/papers/data-driven/paper.pdf –

+1

Thật vậy, gói phản chiếu về cơ bản là phiên bản đóng gói của giấy Oleg. – ehird

+0

Về trạng thái hiện tại của Haskell: không. Các cá thể sẽ đi khắp mọi nơi và mọi nơi mà chúng có thể đạt được. Về những điều chỉnh có thể xảy ra với Haskell trong tương lai: có thể. Về việc sử dụng cơ chế của riêng bạn thay vì typeclasses: có. –

Trả lời

11

Tiện ích mở rộng được đề xuất có cùng một vấn đề được minh họa trong this previous answer của tôi; bạn có thể sử dụng các cá thể cục bộ để tạo hai số Map s có cùng loại khóa nhưng khác nhau với Ord trường hợp, khiến tất cả các biến thể bị hỏng.

Tuy nhiên, gói reflection phép bạn định nghĩa như một loại ModN: bạn xác định một trường hợp duy nhất với một hạn chế Reifies, và kích hoạt Ví dụ cho một cụ thể n với reify. (Tôi tin rằng implicit parameters cũng sẽ thực hiện điều này có thể, nhưng tiện ích đó hiếm khi được sử dụng.)

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