2012-06-05 4 views
15

Я играл вокруг с классами типов и сделал это:Haskell класс типы для кортежей

class Firstable f where 
    fst :: f a -> a 

class Secondable f where 
    snd :: f a -> a 

Затем я попытался добавить реализацию (,) и понял, что я мог бы сделать:

instance Secondable ((,) a) where 
    snd (x,y) = y 

I 'm довольно уверен, что это работает, потому что Secondable должен иметь kind (* -> *), где ((,) a) имеет этот тип, однако я не знаю, как реализовать Initialable for ((,) * a) где * is связанная переменная. В моей интерпретации я пытаюсь сделать эквивалент:

instance Firstable (flip (,) a) where ... 

Есть ли способ сделать это в Haskell? Предпочтительно без расширений?

Спасибо!

+0

AFAIK, нет: вам нужно 'TypeSynonymInstances', но тип синонимы не могут быть частично оценены. Но знаете ли вы об альтернативе с «MultiParamTypeClasses»? Это, наверное, немного уродливо, но это работает. – leftaroundabout

+1

Вам может быть интересно, как пакет кортежей обрабатывает это: http://hackage.haskell.org/package/tuple –

+0

@JohnL действительно круто, спасибо! –

ответ

1

Версия с худшими параметрическими гарантиями может быть выполнена с MPTCS и Fundeps или с TypeFamilies.

type family Fst p 
type instance Fst (a,b) = a 
type instance Fst (a,b,c) = a 

...

class First p where 
    fst :: p -> Fst p 

instance Fst (a,b) where 
    fst (a,_) = a 

instance Fst (a,b,c) where 
    fst (a,_,_) = a 

...

, но в конечном счете, вы должны будете использовать некоторые расширения.

+0

Является ли тип экземпляра Fst (a, b , c) = b' должен читать «экземпляр типа Fst (a, b, c) = a' вместо? – mithrandi

+0

Да, исправлено. знак равно –

1
class Firstable f where 
    fst :: f a b -> a 

class Secondable f where 
    snd :: f a b -> b 
+0

Таким образом, только 2-х кортежей можно было бы сделать экземпляром этого класса, нет? Это вроде бы поразило бы цель иметь класс типа для начала. – sepp2k

+0

@ sepp2k Во-первых, он никогда не указывал цель, и я интерпретировал ее как означающую, что он просто хотел обобщить конструкторы типа (по крайней мере) двух аргументов. Во-вторых, его два оригинальных класса имеют одну и ту же подпись, подразумевая, что он либо ошибался, либо просто должен использовать один класс для описания обоих полей. –

+0

@GabrielGonzalez Да, я намеревался, чтобы кортежи могли быть реализованы для (,), (,,) ... –

10

Вы можете использовать семьи типа как так (другой взгляд на то, что написал Эдвард):

{-# LANGUAGE TypeFamilies #-} 

class Firstable a where 
    type First a :: * 
    fst :: a -> First a 

class Secondable a where 
    type Second a :: * 
    snd :: a -> Second a 

instance Firstable (a,b) where 
    type First (a, b) = a 
    fst (x, _) = x 

instance Secondable (a,b) where 
    type Second (a, b) = b 
    snd (_, y) = y 
Смежные вопросы