Question

J'essaie de faire de l'abstraction dans Haskell98 mais je ne sais pas comment le faire.

Ce que je veux faire est de définir une classe pour les types pouvant être convertis en listes.

toList :: a -> [b]

Mais je ne sais pas comment définir une classe pour cette méthode. J'ai évoqué les trois idées suivantes:

class ToList a b where
    toList :: a -> [b]

class ToList a where
    toList :: a -> [b]

class ToList a where
    toList :: a b -> [b]

Le premier ne fonctionne pas car Haskell98 n'autorise pas plusieurs classes de paramètres.

Le second ne fonctionne pas car b dépend de a et ne peut pas être mis en œuvre pour chaque b.

Le troisième ne fonctionne pas non plus parce que je ne sais pas comment instancier la classe avec un type où "b" n'est pas le dernier paramètre de type.

data HTree a b = Nil | Node a b (HTree a b) (HTree a b)

toList Nil = []
toList Node x y l r = toList l ++ [(x,y)] ++ toList r

ou

toList Nil = []
toList Node x y l r = toList l ++ [x] ++ toList r

Comment pourrais-je faire quelque chose comme ça?

Était-ce utile?

La solution

Voir aussi Data.Foldable dans la bibliothèque standard, qui fournit une fonction toList pour toute instance Foldable . Foldable nécessite un peu de sophistication pour être instancié, mais ce serait une bonne pratique. En prime, votre type HTree est presque identique à l'exemple de la documentation.

De plus, je vous recommande de remplacer votre HTree par:

data HTree a = Nil | Node a (HTree a) (HTree a)

Puis utilisez HTree (a, b) au lieu de HTree a b . Cette version à un seul paramètre sera plus facilement composable avec des types et des instances standard, et elle va plus loin que ce qui se passe, car elle dépend de la même façon des deux paramètres. C’est aussi un Functor , et la définition d’une telle instance rendra ce type très agréable à utiliser.

Autres conseils

Je recommanderais Les classes de types ne sont pas aussi utile comme ils semblent au premier abord - si la classe putative a une seule méthode d'interface, envisagez plutôt de déclarer un type de fonction. Je viens aussi d’un milieu OO et j’ai constaté que j’avais passé beaucoup trop de temps à essayer de faire "classe". signifie ce que je pensais que cela signifiait, alors que j’aurais vraiment dû utiliser "données".

Il est beaucoup plus simple d'écrire votre fonction toList puis de la "soulever" pour qu'elle fonctionne sur votre structure de données. En fait, le Encore un didacticiel de Haskell , fait l’objet d’une longue exercice montrant comment cela se passe, et utilise un arbre binaire comme exemple. L’atout majeur de l’ascenseur est qu’il distingue ce qui est important - la structure du type de données, et non l’implémentation de toList '. Ainsi, une fois que l’ascenseur est prêt à fonctionner, vous pouvez utiliser l’ascenseur pour: faire n'importe quoi - liste, imprimer, peu importe. La prise en charge de toList n’est pas la partie importante de la structure de données, elle ne devrait donc pas figurer dans une déclaration de classe. L’important est de savoir comment parcourir la structure de données.

Vous voudrez probablement choisir la dernière option pour la classe ToList et créer une instance (HTree a) de ToList. Puis toList a le type (HTree a b) - > [b] , pas par exemple (HTree a b) - > [(a, b)] . Je suppose que vous pensez en tant que "clé". et b comme "valeur" type.

class ToList a where
    toList :: a b -> [b]

data HTree a b = Nil | Node a b (HTree a b) (HTree a b)

instance ToList (HTree a) where
    toList Nil = []
    toList (Node x y l r) = toList l ++ [y] ++ toList r

test = toList (Node "a" 1 (Node "b" 2 Nil Nil) Nil)
-- test == [2,1]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top