permet de dire que nous avons cette déclaration de type: 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: p> au lieu de correspondre à chaque constructeur séparément. P> 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. P> p>
6 Réponses :
Edit: Si tous les constructeurs ont le même type de champs, vous pouvez abuser du fonctionnement du fonctionnement: Vous pouvez essayer p>
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] CODE> 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] code> 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, ()))) Code> (hier, j'ai vu cela dans les liaisons LLVM pour l'indexation)
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
Vous n'avez pas besoin x code>, il suffit d'utiliser () code> comme un espace réservé.
@DJV: Je voulais un espace réservé explicite, pour le distinguer des autres types. Mais oui, () code> ou presque toute autre chose fonctionnerait aussi bien.
J'ai essayé de généraliser la réponse de @kennyTM avec: mais par une raison quelconque, il ne fonctionne pas pour le constructeur C code> p> p> < / p>
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: avec une telle fonctionnalité d'assistance, la définition de g code> peut être simplifiée comme suit: p> peut-être code> fonction: p>
Cela semble être la solution la plus propre pour moi.
Je souhaite que les motifs Haskell auraient un moyen de spécifier le "ou" de deux motifs, similaire à | code> dans ocaml:
Quel sera si a code>, b code> et c code> aura des types différents? Comment 1 code> peut fonctionner avec v code> s'il correspondait à trois constructeurs différents? Quel sera si c code> prendra deux valeurs? Comment 2 code> saura qu'il existe un autre nom pour la deuxième valeur correspondant au constructeur C code> au contraire à d code> où seul v code > est disponible?
Eh bien, je mets v code> là-bas pour montrer que vous pouvez obtenir la valeur des trois. Mais puisque v code> n'est pas utilisé, bien sûr, vous pouvez simplement faire A _ | B _ | C _ code> et cela n'a pas d'importance s'ils avaient des types différents. Et si C code> prend deux valeurs (dans OCAML, vous ne pouvez pas prendre deux valeurs), vous n'écrirais pas c _ _ code>. De cette façon, le vérificateur de type serait capable de vérifier qu'il est correct.
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).