2012-06-05 25 views
15

Yo estaba jugando con clases de tipos e hizo esto:Haskell clase de tipos de tuplas

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

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

Luego trató de añadir una implementación para (,) y se dio cuenta de que podía hacer:

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

I Estoy bastante seguro de que esto funciona porque Secondable debería tener kind (* -> *) donde ((,) a) tiene ese tipo, sin embargo, no sé cómo implementar Firstable para ((,) * a) donde * es la variable vinculada, en mi interpretación, estoy tratando de hacer el equivalente de:

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

¿Hay alguna manera de hacer esto en Haskell? Preferiblemente sin extensiones?

Gracias!

+0

yo sepa, no: lo que se necesita 'TypeSynonymInstances', pero escribir los sinónimos no pueden ser evaluados parcialmente. ¿Pero conoce la alternativa con 'MultiParamTypeClasses'? Eso es quizás un poco feo, pero funciona. – leftaroundabout

+1

Puede que le interese cómo maneja el paquete tuple esto: http://hackage.haskell.org/package/tuple –

+0

@JohnL realmente genial, gracias! –

Respuesta

1

Se puede tener una versión con peores garantías de parametrización con MPTCS y Fundeps o con 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 

...

pero en última instancia, tendrá que utilizar algunas extensiones.

+0

Es 'tipo instancia Fst (a, b , c) = b 'se supone que debe leer 'tipo instancia Fst (a, b, c) = a' en su lugar? – mithrandi

+0

Sí, lo arreglaron. =) –

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

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

De esta forma, solo 2-tuplas se podrían convertir en una instancia de esa clase, ¿no? Eso sería una especie de derrota para el propósito de tener la clase de tipo para comenzar. – sepp2k

+0

@ sepp2k Primero, él nunca especificó el propósito y lo interpreté como que quería generalizar constructores de tipos de (al menos) dos argumentos. En segundo lugar, sus dos clases originales tienen exactamente la misma firma, lo que implica que o las malinterpretó, o que debería usar una clase para describir ambos campos. –

+0

@GabrielGonzalez Sí, pretendí que las tuplas se puedan implementar para (,), (,,) ... –

10

Puede usar familias de tipo como así (una opinión diferente sobre lo que escribió Eduardo):

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