2010-07-19 35 views
14

Đến với Haskell từ một nền trong các ngôn ngữ OO khác nhau, một điều có vẻ như một nhược điểm đối với tôi là hàm và tên trường không bị scoped được liên kết với, vì vậy thật dễ dàng để chạy vào các xung đột nếu các kiểu dữ liệu khác nhau có các trường có cùng tên.Tên xung đột giữa các nhãn trường của các kiểu dữ liệu khác nhau trong Haskell

Nếu tôi đã ba module:

module One where 

data Foo a = Foo { value :: a } 

---- 

module Two where 

data Bar a = Bar { value :: a } 

---- 

module Three where 

import One 
import Two 

foo = Foo { value = 42 } -- compile error here 
n = value foo -- and here 

tài liệu tham khảo không đủ tiêu chuẩn để value trong mô-đun Three được coi là mơ hồ mặc dù chỉ là một trong hai tên nhập khẩu có ý nghĩa trong bối cảnh này. (Trong một ngôn ngữ OO, tham chiếu đến foo.valuebar.value sẽ rõ ràng.)

Tất nhiên tôi có thể làm mất uy tín bằng cách viết Foo { One.value = 42 }, nhưng trông có vẻ khó xử. Tôi cũng có thể đặt tên cho các trường khác nhau, ví dụ: "fooValue" và "barValue", nhưng dự phòng trong Foo { fooValue = 42 } cũng có vẻ khó xử.

Đây thực sự là trường hợp đặc biệt của vấn đề tổng quát hơn về chức năng trong các mô-đun khác nhau có cùng tên nhưng hoạt động trên các loại khác nhau, không liên quan. Tôi dường như chạy vào nó thường xuyên hơn với tên trường, mặc dù. Ví dụ, tôi có một số kiểu dữ liệu, không liên quan đến một loại lớp nhưng thường được sử dụng cùng nhau, có chứa các giá trị màu, vì vậy tôi muốn mỗi một có một trường có tên là "màu".

Nhà phát triển Haskell có kinh nghiệm đặt tên cho mọi thứ và sắp xếp chúng thành các mô-đun để tránh tình huống này như thế nào?

+0

Điểm nhỏ: bạn đang thiếu hàm tạo trong định nghĩa 'Bar'. –

+0

@Travis Brown: Rất tiếc, đó là lỗi đánh máy. Cảm ơn đã chỉ ra điều đó. – Wyzard

Trả lời

9

Phần mở rộng GHC -XDisambiguateRecordFields sẽ cho phép foo = Foo { value = 42 } (nhưng không phải n = value foo).

Có một số large body of literature về những thiếu sót của hệ thống hồ sơ hiện tại của Haskell và các ứng cử viên để thay thế, cũng như một số thư viện cố gắng cung cấp các giải pháp đẹp hơn ngay bây giờ. fclabels là người duy nhất tôi đã sử dụng cá nhân.

This StackOverflow question tương tự và một số câu trả lời cũng có thể hữu ích cho bạn.

Đây thực sự là một trường hợp đặc biệt của vấn đề tổng quát hơn các chức năng trong module khác nhau có cùng tên nhưng hoạt động trên, loại liên quan khác nhau.

Qualified imports và bí danh thường đủ để giải quyết vấn đề này.

1

Bạn có thể xem xét một loại lớp, nếu có chức năng truy cập chung trên tất cả các loại này. Ví dụ.

class Fieldable a where 
    field :: a -> b 

instance Fieldable (a,b) where 
    field = fst 

vv

+1

Tên trường dữ liệu có thể là một phần của cá thể lớp không? Nếu tôi tạo một 'class Valued ab với giá trị :: a -> b' sau đó kết hợp hai kiểu của tôi với nó, tôi sẽ phải làm một cái gì đó như' instance Valued (Foo a) a value value = value' và đó không phải là hợp lệ (hai nghĩa của xung đột 'giá trị'). Có vẻ như tôi không thể định nghĩa một hàm như là một phần của cá thể lớp nếu tên của nó đã được định nghĩa trước đó. – Wyzard

2

Làm thế nào để các nhà phát triển có kinh nghiệm Haskell tên sự vật, và sắp xếp chúng vào mô-đun, để tránh kiểu này tình hình?

tôi đã chỉ làm việc với một vài nhà phát triển Haskell có kinh nghiệm, và họ làm công cụ khủng khiếp như

data Foo a = Foo { foo_value :: a } 

data Bar a = Bar { bar_value :: a } 

hoặc thậm chí

data Apocalypse a = A { ap_value :: a } 

Nói chung, tôi có cảm giác rằng rất nhiều Người Haskellers thời xưa không thích những cái tên đủ điều kiện và thực sự muốn giả vờ rằng thế giới chỉ có một không gian tên lớn, thẳng ra khỏi thời đại đen tối. (Có một thời gian mà trình biên dịch C có những hạn chế tương tự trên tên trường, đó là lý do tại sao chế độ trong một struct stat được gọi st_mode và không chỉ đơn giản mode.)

Bạn có thể quá tải tên với lớp loại, nhưng các nhà phát triển có kinh nghiệm Tôi biết không thích các lớp học vô cớ. Tôi không bao giờ có thể tìm ra khi họ nghĩ rằng một lớp loại sẽ là vô cớ hay không.

Tôi hy vọng một ngày nào đó, người Haskell sẽ đến với điều khoản có không gian tên phân cấp và sẽ bắt đầu sử dụng tên đủ điều kiện. Như Chúa đã định.

+0

Khi bạn không thực sự muốn các bộ chọn bản ghi đa hình, thì điều đó có ý nghĩa với tôi để không ép buộc chúng chỉ cho một số tiện ích cú pháp nhỏ. Ngay cả khi bạn có thể sử dụng những thứ đủ điều kiện, có vẻ như với tôi rằng yêu cầu một tên chung cho một lĩnh vực hiếm khi được sử dụng, đặc biệt là một trong đó thường chỉ nên được truy cập thông qua một hàm trợ giúp, là hình thức xấu. – sclv

+0

Tôi đã sử dụng tên đủ điều kiện càng nhiều càng tốt. Ngôn ngữ chính nó đề với nó chỉ tốt; vấn đề duy nhất là Haddock trở nên kém hữu ích hơn nhiều với các tên đủ điều kiện vì nó vẫn giả định một không gian tên lớn. (Bạn có thể đặt tên kiểu hiển thị của Haddock đủ điều kiện, nhưng nó vẫn sẽ hiển thị siêu liên kết không đủ tiêu chuẩn.) –

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