J'ai commencé cela une nouvelle question car elle est devenue un suivi de ma question précédente.
Si j'ai deux types de données composés de constructeurs similaires: P>
data A = X | Y | Z data B = X | Y
4 Réponses :
Non seulement vous ne pouvez pas faire cela, vous ne pouvez pas également faire votre première option - c'est-à-dire que vous ne pouvez pas avoir deux types dans le même module que les deux ont des constructeurs nommés Si vous pouviez le faire, quel devrait le type de Le meilleur que vous puissiez faire est d'envelopper C dans un constructeur d'A et B, c'est-à-dire: P > puis vous pouvez envelopper un c avec le x code> et Y code>. x code> être - c code>, a code> ou < Code> B code>? La réponse la plus évidente serait C code>, mais vous ne seriez pas en mesure de l'utiliser dans un contexte où un A code> ou un B code> sont requis (notez que Haskell n'a pas de sous-typing), de sorte que cela vaincrait le but de l'ensemble de la construction. P> AC code> ou le constructeur bc code> pour créer une valeur de type A code> ou b code> respectivement. p> p>
Just édité de dire que ma première option ne fonctionne pas. Lorsque vous dites "wrap", vous voulez dire littéralement "incluent un autre morceau de syntaxe devant C, pour distinguer de l'original C"?
@Dan oui. Dans mon exemple, vous écrivez ac x code> pour créer une valeur de type A code> et bc x code> pour créer une valeur de type b code>. x code> par lui-même ne peut pas avoir deux types différents.
La raison pour laquelle vous ne pouvez pas faire ce est la suivante. Dis que vous écrivez du code plus tard sur: p> qui construit une paire composée de car n code> dans la première fente et x code> x code> dans la deuxième fente. Quel type doit-il déduire le compilateur? Un type valide serait p> x code> est un constructeur de type A code>, mais également valide > foo :: a -> B -> (a,B)
Vous ne pouvez pas faire ceci:
foo :: A -> String foo (A_Other X) = "X" foo (A_Other Y) = "Y" foo ( Z) = "Z" bar :: B -> String bar (B_Other X) = "X" bar (B_Other Y) = "Y" foobar :: C -> String foobar X = "X" foobar Y = "Y"
Vous ne pouvez pas faire ce que vous voulez parce que vous déclarez plusieurs constructeurs de données. Dans vous introduisez réellement le type a code> qui comporte 3 constructeurs (valeurs) x code>, y code> et z code>. C'est pourquoi votre premier morceau de code ne compilera pas, il voit le même nom indiqué que des constructeurs pour deux types différents! Si vous pouviez faire cela, vous devez vous demander est P> data A = CForA C | Z
data B = CForB C
data C = X | Y
Ce que vous demandez serait un sous-type de
A code>. Il ne serait pas déclaré avec le mot-clédata code>, qui crée un nouveau type, disjoint des types existants antérieurs. Je ne pense pas que Haskell a une telle caractéristique, mais je ne suis pas un coup avec toutes les extensions de Haskell.@Gilles: Non, Haskell n'a pas de polymorphisme sous-type. Il a seulement un polymorphisme paramétrique et un polymorphisme ad hoc par des classes de type. La chose la plus proche que vous puissiez obtenir est un type existentiel, mais c'est presque, mais pas tout à fait une chose tout à fait différente.
Je vais mettre cela comme une réponse, mais parce que ce n'est pas tout à fait. Vous pourrez peut-être vous rapprocher de ce que vous voulez en déclarant une typlass puis des opérations dont vous avez besoin pour ces "choses communes". C'est un moyen assez courant de retourner des choses à résoudre (une version de) ce problème ..