15 votes

Classes de types dans les types de données Haskell

En Haskell, on peut définir un type de données comme suit :

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

Peut-on utiliser des classes de type pour les variables à l'intérieur d'un type de données ? Si oui, comment ? Je réalise qu'il est possible de faire cela comme un type de données algébrique, avec une définition différente pour chaque type de point, mais je me demande s'il y a un moyen d'accomplir cela d'une manière plus compacte et flexible.

Par exemple, quelque chose comme ceci pseudo-code qui utilise la syntaxe de déclaration de fonction :

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

L'objectif serait de permettre de stocker Int , Entier , Flotteur ou Double dans le type de données. Idéalement, j'aimerais le restreindre de sorte que x et y doivent être du même type.

19voto

Edward Kmett Points 18369

Vous devez décider si vous voulez une quantification existentielle ou universelle sur ce type. La quantification universelle, ala :

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

produit une obligation de preuve que les instances Num et Ord existent pour le type 'a' mais n'aide pas vraiment, parce que tout ce qu'il fait est de vous donner une obligation lorsque vous allez utiliser la classe Point en construisant une valeur de ce type ou lorsque vous allez faire un pattern match.

Dans presque tous les cas, il est préférable de définir

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

et en faisant dépendre chacune de vos instances des informations supplémentaires que vous souhaitez.

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

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

Cela vous permet de transmettre et de construire moins de dictionnaires superflus et augmente le nombre de scénarios dans lesquels votre type de données Point2 peut être utilisé.

D'un autre côté, la quantification existentielle peut vous permettre de dire que vous ne vous souciez pas du tout du type (ce qui est plus proche de ce que vous avez demandé, en termes de type), mais que vous ne pouvez rien utiliser sur ce type, à l'exception des opérations fournies par les contraintes que vous avez spécifiées - ce qui ne convient pas du tout ici.

7voto

newacct Points 42530

Quelque chose comme ça ?

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X