2011-07-10 21 views
13

Câu hỏi chung là cấu trúc mô đun nào thuận tiện hơn khi thêm đối tượng cho các đối tượng hiện có? Những ưu và khuyết điểm nào?Làm thế nào để tổ chức các mô-đun Haskell với các cá thể: dính vào kiểu dữ liệu và loại lớp?

Giả sử tôi muốn thêm cá thể NFData cho loại Seq. Tôi có thể đặt nó vào:

  • Data.Sequence.Extra (như điều tương tự được thực hiện trong gói vty)
  • Data.Sequence.Instances.NFData (chính xác hơn)
  • Control.DeepSeq.Instances
  • Control.DeepSeq.Instances.Sequence

Đó là trường hợp khi tôi không sở hữu cả lớp kiểu cũng như kiểu dữ liệu. Tình huống phổ biến khác là khi tôi sở hữu một loại kiểu lớp và muốn thêm các thể hiện cho các kiểu dữ liệu từ một số gói "nặng" từ Hackage, như OpenGL. Giả sử loại lớp tôi thiết kế rất nhẹ và không có mối quan hệ trực tiếp với OpenGL. Tôi không muốn lớp của tôi phụ thuộc vào gói "nặng", vì vậy tôi muốn đặt các trường hợp OpenGL trong một mô-đun riêng biệt (đó là cảm giác trực quan của tôi, nếu bạn có ý kiến ​​khác, hãy thảo luận về nó). Vì vậy, những gì mô-đun này sẽ là:

  • MyClass.Instances.OpenGL
  • Graphics.Rendering.OpenGL.Extra (cùng với trường hợp cho các lớp khác)
  • Graphics.Rendering.OpenGL.Instances.MyClass

giải pháp linh hoạt hơn là gì? Tại một số điểm OpenGL có thể được thay thế bằng thư viện khác, hoặc MyClass có thể được thay thế quá. Có bất kỳ sắc thái tinh tế nào không?

Ngoài ra, trong đó kế hoạch là tốt hơn nếu chọn MyClass.Instances biến thể:

  • MyClass.Class mô-đun cho các lớp riêng của mình và các trường hợp cơ bản và MyClass mô-đun và tái xuất nó (và có thể MyClass.Instances)
  • MyClass mô-đun cho các lớp và cơ bản các trường hợp và MyClass.All reexports mọi thứ
  • MyClass mô-đun cho lớp và các phiên bản cơ bản và không có mô-đun để kiểm tra lại.
+0

Việc bạn đang làm được gọi là "trường hợp trẻ mồ côi" và được coi là xấu vì chúng dễ dàng xác định nhiều trường hợp cùng loại cho cùng loại và làm cho các thư viện khác không tương thích với nhau. Có một câu hỏi khác thảo luận chi tiết về chúng: http://stackoverflow.com/questions/3079537/orphaned-instances-in-haskell. – Rotsor

+0

Đối với vấn đề của Rotsor - một thư viện "chung" không nên trong kinh doanh thực hiện các cá thể cho các lớp/kiểu dữ liệu mà nó không định nghĩa. Nó là tốt cho một thư viện riêng hoặc một thực thi/ứng dụng để làm điều này - nhưng một thư viện công cộng không nên làm điều đó. Đối với vấn đề ban đầu - vấn đề không thực sự ở đâu trong không gian tên cá thể được định nghĩa nhưng có thể có nhiều hơn một thư viện cung cấp một cá thể. Giải pháp tốt nhất có lẽ là có các gói "các cá thể" trên Hackage, nơi các nhà phát triển cung cấp các cá thể kinh điển cho các lớp/kiểu dữ liệu bên ngoài Base. –

+0

@Rotsor, đó là một điểm tốt (trong khi không có ý kiến ​​chung tại các bình luận tại liên kết). Liệu nó có làm theo từ đó khi tôi sở hữu một loại lớp, tôi sẽ ràng buộc các trường hợp với nó không? – modular

Trả lời

12

Quá trình bình thường của việc quyết định nơi để đặt một ví dụ đi một cái gì đó như thế này:

  1. Nếu bạn đang thực hiện một kiểu dữ liệu mới và muốn một thể hiện cho một lớp học hiện có:

    Đặt thể hiện trong cùng một mô-đun như loại dữ liệu.

  2. Nếu bạn đang tạo lớp loại mới và muốn tạo phiên bản cho các loại hiện có.

    Đặt các phiên bản trong cùng một mô-đun với loại lớp.

  3. Cả loại loại và loại dữ liệu đã tồn tại (trường hợp của bạn).

    Nếu thể hiện đủ chung chung, tôi sẽ liên hệ với tác giả của lớp loại hoặc kiểu dữ liệu và cố gắng thuyết phục họ thêm cá thể trong gói của họ.

    Nếu không, hãy tạo một bao bọc newtype và viết một ví dụ cho điều đó.

    Chỉ là phương sách cuối cùng xem xét việc tạo một trường hợp trẻ mồ côi.

+0

Tôi đồng ý với tất cả những gì bạn đã nói, nhưng rất nhiều thời gian trong trường hợp trẻ mồ côi là giải pháp khả thi duy nhất. – augustss

+2

Tôi đang hạnh phúc xây dựng các trường hợp trẻ mồ côi vào thực thi của tôi, nhưng tôi cố gắng tránh nó cho các thư viện. –