2012-06-05 16 views
15

Grałem około z typeclasses i uczynił to:Haskell Typeclass za krotki

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

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

Następnie próbowałem dodać implementację (,) i zrozumiałem, że mogę zrobić:

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

I jestem całkiem pewny, że to działa, ponieważ Secondable powinien mieć rodzaj (* -> *) gdzie ((,) a) ma ten typ, jednak nie wiem jak zastosować Firstable for ((,) * a) where * is zmienna związana, W mojej interpretacji próbuję wykonać równoważnik:

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

Czy istnieje sposób, aby to zrobić w Haskell? Najlepiej bez rozszerzeń?

Dzięki!

+0

AFAIK, nr: należałoby 'TypeSynonymInstances', ale Synonimy typu nie mogą być częściowo oceniany. Ale czy znasz alternatywę dla 'MultiParamTypeClasses'? To może trochę brzydka, ale działa. – leftaroundabout

+1

Możesz być zainteresowany tym, jak wygląda pakiet krotek: http://hackage.haskell.org/package/tuple –

+0

@JohnL naprawdę fajne, dzięki! –

Odpowiedz

1

Wersję o gorszych parametrowościach można uzyskać z MPTCS i Fundeps lub z 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 

...

ale ostatecznie trzeba będzie korzystać z niektórych rozszerzeń.

+0

Jest instancją typu Fst (a, b , c) = b' powinien odczytać 'type instance Fst (a, b, c) = a' zamiast? – mithrandi

+0

Tak, naprawiłem to. =) –

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

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

W ten sposób można utworzyć tylko 2-krotne egzemplarze tej klasy, nie? To by trochę zniweczyło cel posiadania klasy typu. – sepp2k

+0

@ sepp2k Po pierwsze, nigdy nie określił celu i zinterpretowałem go w ten sposób, że chciał tylko uogólnić konstruktory typów (przynajmniej) dwóch argumentów. Po drugie, jego dwie oryginalne klasy mają dokładnie taki sam podpis, co sugeruje, że albo je pomylił, albo powinien użyć jednej klasy do opisania obu pól. –

+0

@GabrielGonzalez tak, chciałem, aby krotki były możliwe do zaimplementowania dla (,), (,,) ... –

10

Można użyć typu rodziny (tak jak inne podejście do tego, co napisał Edward):

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