11
votes

Correspondant à plusieurs constructeurs de types de données à la fois

permet de dire que nous avons cette déclaration de type: xxx

et souhaitez définir une fonction sur celle-ci qui divise les constructeurs de données dans 2 ensembles. Ce serait bien d'écrire quelque chose comme ça: xxx

au lieu de correspondre à chaque constructeur séparément.

Y a-t-il un moyen d'y parvenir? J'ai regardé uniplate mais je n'ai pas pu trouver un moyen de le faire.


0 commentaires

6 Réponses :


4
votes

Edit: Si tous les constructeurs ont le même type de champs, vous pouvez abuser du fonctionnement du fonctionnement: xxx


Vous pouvez essayer xxx < / p>


5 commentaires

J'ai trouvé la même solution. Le problème est avec les littéraux à chaîne. Ce sera mieux si nous pouvons faire correspondre [A, B, C] comme dans l'exemple que j'ai donné.


Cela va de mieux, mais si je veux que cela fonctionne pour des constructeurs avec des champs de nombre différents?


@DJV: Alors [A, B, C, D, F] n'a pas de type valide.


Hm, oui tu as raison. Mais il devrait y avoir une certaine solution de contournement. Peut-être que je devrai utiliser le gabarit Haskell à la fin.


@KennyTM: Il est probablement possible d'utiliser Tuple comme (A -> D A, (B -> B -> D B, ()))) (hier, j'ai vu cela dans les liaisons LLVM pour l'indexation)



0
votes

C'est un peu de hack, mais comment de cela, en utilisant data.data ​​code> et un "espace réservoir"?

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data 

data X = X deriving (Show, Data, Typeable)
data D a = A a | B a | C a | D a a | E a a | F a a
    deriving (Show, Data, Typeable)


matchCons :: (Data a) => D a -> [D X] -> Bool
matchCons x ys = any ((== xc) . toConstr) ys
    where xc = toConstr x

g :: (Data a) => D a -> Int
g x | matchCons x [A X, B X, C X] = 1
    | matchCons x [D X X, E X X, F X X] = 2


2 commentaires

Vous n'avez pas besoin x , il suffit d'utiliser () comme un espace réservé.


@DJV: Je voulais un espace réservé explicite, pour le distinguer des autres types. Mais oui, () ou presque toute autre chose fonctionnerait aussi bien.



2
votes

J'ai essayé de généraliser la réponse de @kennyTM avec: xxx

mais par une raison quelconque, il ne fonctionne pas pour le constructeur C < / p>


0 commentaires

5
votes

Si vous avez souvent besoin de faire correspondre le même ensemble de constructeurs, une fonction d'assistance pourrait être la solution la plus simple. Par exemple: xxx

avec une telle fonctionnalité d'assistance, la définition de g peut être simplifiée comme suit: xxx < p> ou, en utilisant le peut-être fonction: xxx


1 commentaires

Cela semble être la solution la plus propre pour moi.



0
votes

Je souhaite que les motifs Haskell auraient un moyen de spécifier le "ou" de deux motifs, similaire à | dans ocaml: xxx


2 commentaires

Quel sera si a , b et c aura des types différents? Comment 1 peut fonctionner avec v s'il correspondait à trois constructeurs différents? Quel sera si c prendra deux valeurs? Comment 2 saura qu'il existe un autre nom pour la deuxième valeur correspondant au constructeur C au contraire à d où seul v est disponible?


Eh bien, je mets v là-bas pour montrer que vous pouvez obtenir la valeur des trois. Mais puisque v n'est pas utilisé, bien sûr, vous pouvez simplement faire A _ | B _ | C _ et cela n'a pas d'importance s'ils avaient des types différents. Et si C prend deux valeurs (dans OCAML, vous ne pouvez pas prendre deux valeurs), vous n'écrirais pas c _ _ . De cette façon, le vérificateur de type serait capable de vérifier qu'il est correct.



0
votes

J'ai eu la même question. Ma solution consisterait à utiliser une vue, bien que personnellement, j'aimerais quelque chose qui est plus équivalent canoniquement équivalent (dans une partie du code que j'écris, la préservation de la paresse est essentielle, de sorte que tout match de motif supplémentaire inutile pourrait rendre la technique inutilisable). xxx


0 commentaires