2013-07-01 39 views
11

Có thể có một kiểu là một phần của typeclass không? Một cái gì đó như:Haskell: Các kiểu chữ có thể xác định các loại (các đặc điểm kiểu ala)

class KeyTraits v where 
    keyType :: * 
    key :: v -> keyType 

data TableRow = { date :: Date, metaData :: String, value :: Int } 

instance KeyTraits TableRow where 
    keyType = Date 
    key = date 

Và các chức năng "cấp loại" này có thể được sử dụng ở nơi khác không? Ví dụ:

-- automatically deduce the type for the key, from the value type, using 
-- the typeclass 
data MyMap v = { getMap :: (KeyTraits v) => Map (keyType) v } 

tôi có thể làm một cái gì đó hoàn toàn sai, nhưng tôi về cơ bản muốn khả năng xác định các mối quan hệ kiểu như trên (ví dụ một số giá trị có thể đã có dữ liệu có thể được sử dụng như một chìa khóa). Nếu điều đó là không thể, hoặc là khó khăn, bạn có thể đề xuất một thiết kế tốt hơn là thành ngữ hơn?

Cảm ơn bạn!

Trả lời

26

Hãy xem type families.

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE RankNTypes #-} 

class KeyTraits k where 
    type KeyType k :: * 
    key :: v -> KeyType k 

data TableRow = TableRow { date :: Date, metaData :: String, value :: Int } 

instance KeyTraits TableRow where 
    type KeyType TableRow = Date 
    key = date 

data MyMap v = MyMap { getMap :: (KeyTraits v) => Map (KeyType v) v } 
11

Loại gia đình là chính xác những gì bạn đang tìm kiếm, nhưng đó cũng là một cách để đạt được chức năng của họ, cụ thể là multi-parameter type classes với functional dependencies. Với những phần mở rộng bạn mã có thể trông như thế này:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} 

class KeyTraits v k | v -> k where 
    key :: v -> k 

data TableRow = { date :: Date, metaData :: String, value :: Int } 

instance KeyTraits TableRow Date where 
    key = date 

Đây là loại liên quan đến di chuyển đến gõ tham số lớp, và mối quan hệ giữa vk, trước đây tiềm ẩn, bây giờ trở nên rõ ràng với sự phụ thuộc chức năng.

Điều này hoàn toàn tương đương với các loại được liên kết, nhưng IMO cung cấp cú pháp rõ ràng hơn nhiều, đặc biệt là trong các hàm sử dụng loại lớp của bạn. Hãy so sánh:

getMap :: (KeyTraits v) => Map (KeyType v) v 

getMap :: (KeyTraits k v) => Map k v 

Điều này trở nên rõ ràng hơn khi có nhiều chủng loại và các lớp học kiểu xuất hiện nhiều hơn trong khai báo kiểu duy nhất.

Tuy nhiên, loại gia đình dường như được cộng đồng haskell ưa thích và trên thực tế, toàn bộ phần mở rộng mạnh hơn MPTC + FD, vì họ có thể khai báo loại gia đình mà không cần loại lớp và cũng có cả họ dữ liệu.

+0

Cảm ơn rất nhiều vì sự thay thế! Mặc dù câu trả lời khác được gắn trực tiếp hơn với tiêu đề câu hỏi, giải pháp của bạn cũng có liên quan. –

+0

Tôi đã được ấn tượng rằng MPTC + FD là biểu cảm hơn TF trong một số trường hợp cạnh với phụ thuộc phức tạp ... –

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