2011-01-27 32 views
6

Tôi muốn tạo một số kiểu dữ liệu không tương thích, nhưng bằng nhau. Đó là, tôi muốn có một kiểu tham số Foo a, và các chức năng nhưTôi có đang suy nghĩ và sử dụng các loại singleton trong Haskell đúng không?

bar :: (Foo a) -> (Foo a) -> (Foo a) 

mà không thực sự quan tâm về những gìa là. Để làm rõ hơn nữa, tôi muốn hệ thống loại để ngăn chặn tôi từ làm

x :: Foo Int 
y :: Foo Char 
bar x y 

trong khi tôi cùng một lúc không thực sự quan tâm đến IntChar (Tôi chỉ quan tâm rằng họ đang không giống nhau) .

Trong mã thực tế của tôi, tôi có loại cho đa thức trên một vòng nhất định. Tôi không thực sự quan tâm những gì không xác định được, miễn là hệ thống kiểu dừng tôi thêm một đa thức trong t với một đa thức trong s. Cho đến nay tôi đã giải quyết điều này bằng cách tạo ra một typeclass Indeterminate, và parameterizing loại đa thức của tôi như

data (Ring a, Indeterminate b) => Polynomial a b 

Cách tiếp cận này cảm thấy hoàn toàn tự nhiên cho phần Ring vì tôi làm chăm sóc về mà đặc biệt là vòng một đa thức nhất định là hơn . Nó cảm thấy rất phấn khởi cho phần Indeterminate, như được mô tả chi tiết bên dưới.

Cách tiếp cận ở trên hoạt động tốt, nhưng cảm thấy bị giả tạo. Đặc biệt là phần này:

class Indeterminate a where 
    indeterminate :: a 

data T = T 

instance Indeterminate T where 
    indeterminate = T 

data S = S 

instance Indeterminate S where 
    indeterminate = S 

(và cứ như vậy có thể thêm một vài xác định). Nó cảm thấy lạ và sai. Về cơ bản, tôi đang cố gắng yêu cầu các trường hợp của Indeterminate là những người độc thân (trong this sense). Cảm giác kỳ quặc là một dấu hiệu cho thấy tôi có thể tấn công sai lầm này. Khác là một thực tế là tôi cuối cùng phải chú thích rất nhiều của tôi Polynomial a b s kể từ khi loại thực tế b thường không thể suy ra (đó là không lạ, nhưng là gây phiền nhiễu tuy nhiên).

Mọi đề xuất? Tôi có nên tiếp tục làm như thế này không, hay tôi đang thiếu cái gì đó?

PS: Đừng cảm thấy bị xúc phạm nếu tôi không upvote hoặc chấp nhận câu trả lời ngay lập tức. Tôi sẽ không thể kiểm tra lại sau vài ngày.

+0

Có lý do chính đáng để không mô hình hóa đa thức như chuỗi các phần tử của vòng hay thứ gì đó tương tự (chuỗi các khoản tiền một phần chẳng hạn)? –

+0

Ok, tôi hơi lạc lõng ở đây. Tôi không hiểu tại sao bạn cần 'Vô định'. Nếu bạn chỉ muốn thực thi rằng hai bs là như nhau, hãy để nó trong chữ ký loại, và đó là điều đó? – sclv

+0

@ Alexandre C .: Tôi đang làm điều đó. Nhưng tôi muốn chữ ký loại để làm cho nó vô nghĩa, nói, thêm "2 + 5t" đến "6s". Với đa thức là chuỗi các phần tử vòng, hệ thống kiểu (đúng) ngăn tôi thêm một đa thức với các hệ số trong một vòng với một hệ số với một hệ số khác, nhưng nó không phân biệt trên không xác định. Bây giờ, tất nhiên, có hay không tôi thực sự cần indeterminates là một câu hỏi rất hợp lệ :-) – gspr

Trả lời

7

Trước hết, tôi không chắc chắn này:

data (Ring a, Indeterminate b) => Polynomial a b 

... là làm những gì bạn mong đợi nó. Các bối cảnh trên các định nghĩa data không hữu ích một cách khủng khiếp - xem the discussion here vì một số lý do tại sao, phần lớn số tiền đó buộc chúng phải thêm chú thích bổ sung mà không thực sự cung cấp nhiều loại bảo đảm bổ sung.

Thứ hai, bạn có thực sự quan tâm đến thông số "không xác định" không phải để đảm bảo rằng các loại được giữ riêng biệt không? Một cách khá chuẩn để thực hiện điều đó là những gì được gọi là phantom types - các tham số trong constructor kiểu không được sử dụng trong hàm tạo dữ liệu. Bạn sẽ không bao giờ sử dụng hoặc cần một giá trị của các loại ma, vì vậy chức năng có thể được như đa hình như bạn muốn, ví dụ:

data Foo a b = Foo b 

foo :: Foo a b -> Foo a b 
foo (Foo x) = Foo x 

bar :: Foo a c -> Foo b c 
bar (Foo x) = Foo x 

baz :: Foo Int Int -> Foo Char Int -> Foo() Int 
baz (Foo x) (Foo y) = Foo $ x + y 

Rõ ràng điều này không đòi hỏi phải chú thích, nhưng chỉ ở những nơi mà bạn đang cố tình thêm hạn chế .Nếu không, suy luận sẽ hoạt động bình thường đối với tham số kiểu phantom. Có vẻ như với tôi rằng cách tiếp cận ở trên là đủ cho những gì bạn đang làm ở đây - kinh doanh với các loại singleton chủ yếu là về khoảng cách giữa các công cụ loại phức tạp hơn và tính toán mức giá trị thông thường bằng cách tạo loại proxy cho các giá trị. Điều này có thể hữu ích cho việc đánh dấu vectơ với các loại cho biết cơ sở của chúng hoặc đánh dấu các giá trị số với các đơn vị vật lý - cả hai trường hợp chú thích có ý nghĩa nhiều hơn chỉ là "không xác định được gọi là X".

+1

Với '-XEmptyDataDecls' bạn có thể làm cho nó để các loại" đánh dấu "của bạn không có biểu diễn thời gian chạy, ví dụ. 'dữ liệu T', và sau đó một dòng mới và contine mã của bạn. Điều này nói 'T' là một kiểu không có các hàm tạo, và do đó nó thực sự chỉ có nghĩa là một cái gì đó cho hệ thống kiểu. – luqui

+0

Cảm ơn bạn! Tôi nghĩ rằng bạn đã chính xác những gì tôi đã hỏi và tự hỏi. Tôi không biết về các loại ma, vì vậy cảm ơn vì đã dạy tôi. Việc làm sáng tỏ về việc khi nào những người độc thân được sử dụng thực sự cũng rất khai sáng, và đi thẳng vào cốt lõi của những gì tôi đang gặp vấn đề (thực sự, bạn đã đọc được suy nghĩ của tôi chưa?). (Lưu ý: Tôi biết rằng ngữ cảnh trên các định nghĩa 'dữ liệu 'không hữu ích - tôi sử dụng chúng để hỗ trợ suy nghĩ của tôi khi viết mã, nhưng sau đó đưa chúng ra. Tôi nên loại bỏ chúng trước khi yêu cầu). – gspr

+1

@gspr: Tại một thời điểm nào đó, bạn có thể muốn đọc về GADT và các phần mở rộng ngôn ngữ có liên quan - quyền lực biểu cảm mà chúng cung cấp có vẻ như bạn có thể thấy hữu ích, cho phép (trong số những thứ khác) ngữ cảnh về định nghĩa dữ liệu thực sự có ý nghĩa. –

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