2009-07-05 38 views
14

En Haskell, se puede definir un tipo de datos de este modo:clases de tipos en los tipos de datos de Haskell

data Point1 = Point1 { 
    x :: Integer 
    , y :: Integer 
} 

Can clases de una utilización de tipo de variables dentro de un tipo de datos? ¿Si es así, cómo? Me doy cuenta de que es posible hacer esto como un tipo de datos algebraicos, con una definición diferente para cada tipo de punto, pero me pregunto si hay una manera de lograr esto de una manera más compacta y flexible.

p. Ej. Algo a lo largo de las líneas de este pseudocódigo que utiliza la sintaxis de declaración de la función:

data Point2 = Point2 { 
    x :: (Num a, Ord a) => a 
    , y :: (Num a, Ord a) => a 
} 

El objetivo sería permitir una para almacenar Int, Entero, flotador o dobles valores de los datos tipo. Idealmente, me gustaría restringirlo para que xey deban ser del mismo tipo.

Respuesta

18

Debe decidir si desea una cuantificación existencial o universal de ese tipo. cuantificación universal, Ala:

data (Num a, Ord a) => Point2 a = Point2 a a 

produce una obligación prueba de que existen casos Num y Ord para el tipo 'A', pero en realidad no ayudan a casi nada, porque todo lo que hace es darle una obligación cuando se va para usar la clase Point construyendo un valor de ese tipo o cuando vas al patrón.

En casi todos los casos que están en mejor definición

data Point2 a = Point2 a a deriving (Eq,Ord,Show,Read) 

y hacer que cada una de las instancias de contingentes en la información adicional que usted desee.

instance Num a => Num (Point2 a) where 
    ... 

instance (Num a, Ord a) => SomeClass (Point2 a) where 
    ... 

Esto le permite pasar alrededor y un menor número de diccionarios superfluos construir y aumenta el número de escenarios en los que se puede utilizar el tipo de datos Point2.

Por otro lado la cuantificación existencial puede permitirle decir que no le importa qué tipo de letra es (más cerca de lo que realmente solicitó, escriba sabio) a expensas de que no puede usar nada excepto para las operaciones provistas por las restricciones que especificó; un ajuste bastante pobre aquí.

+2

Woohoo, ese es exactamente el punto que estaba viendo en mi comentario a la respuesta de newacct pero era demasiado vago para escribir :) – ephemient

+1

Eso es muy informativo. Terminé usando el comentario de ephemient en mi código. Y tu explicación me ayudó a comprender mucho. (RWH aún no ha cubierto "instancia" pero es evidente lo que hace desde el contexto.) Muchas gracias. – Gregyski

7

algo como esto?

data (Num a, Ord a) => Point2 a = Point2 { 
    x :: a 
    , y :: a 
} 
+8

Más comúnmente, uno deja el contexto en la declaración de datos y usa "(Num a, Ord a) => Point2 a" en las ubicaciones donde realmente se usa el tipo, pero esto también funciona. – ephemient

+0

Gracias. Eso funciona perfectamente e incluso tiene sentido ahora que lo veo. – Gregyski

+3

Este no es el código de haskel legal para ghc 7.4.1 – mentatkgs

Cuestiones relacionadas