2013-07-01 9 views
11

Bir tipin bir yazım tipinin parçası olması mümkün mü? Şunlar gibi:Haskell: Tipleri tanımlayabilir tipler (ala tip özellikleri)

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

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

instance KeyTraits TableRow where 
    keyType = Date 
    key = date 

Bu "tip seviyesi" işlevleri başka yerlerde de kullanılabilir mi? Örneğin:

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

ben tamamen yanlış bir şey yapıyor olabilir, ama temelde yukarıda biri (örn Bazı değerler zaten Anahtar olarak kullanılabilecek veri olabilir) gibi tip ilişkileri tanımlama yeteneği istiyorum. Bu mümkün değilse veya zorsa, daha idiomatik olan daha iyi bir tasarım önerebilir misiniz?

Teşekkür ederiz!

cevap

26

type families'a bir göz atın.

{-# 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

Tipi aileleri Aradığınız tam olarak ne olduğunu, fakat bunların işlevi, functional dependencies ile yani multi-parameter type classes ulaşmak için başka bir yol da vardır. Bu uzantıların ile size kod aşağıdaki gibi görünebilir:

İşte
{-# 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 

ilişkili tip sınıfı parametreyi yazın göç ve daha önce örtük v ve k arasındaki ilişki, artık fonksiyonel bağımlılık ile açık hale gelir.

Bu, ilişkili türlere tamamen eşdeğerdir, ancak IMO özellikle tip sınıfınızı kullanan işlevlerde çok daha temiz bir sözdizimi sağlar. Karşılaştırma:

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

ve

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

daha türleri ve daha tip sınıfları tek tip bildiriminde göründüğünde bu daha belirgin hale gelir. Ancak, tip aileler haskell topluluğu tarafından tercih ediliyor gibi görünmektedir ve aslında tüm uzantılar MPTC + FD'den daha güçlüdür, çünkü tip aileleri tip sınıfları olmadan beyan edilebilir ve ayrıca veri aileleri de vardır.

+0

Alternatif için çok teşekkürler! Diğer cevap soru başlığına daha doğrudan bağlı olsa da, çözümünüz de konuyla ilgili. –

+0

MPTC + FD'nin karmaşık bağımlılıkları olan bazı uç durumlarda TF'den daha etkileyici olduğunu düşündüğüm izlenim altındaydım ... –