6
votes

Utilisation des types de données dans HASKELLL

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


3 commentaires

Ce que vous demandez serait un sous-type de A . Il ne serait pas déclaré avec le mot-clé data , 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 ..


4 Réponses :


13
votes

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 x et Y .

Si vous pouviez le faire, quel devrait le type de x être - c , a ou < Code> B ? La réponse la plus évidente serait C , mais vous ne seriez pas en mesure de l'utiliser dans un contexte où un A ou un B sont requis (notez que Haskell n'a pas de sous-typing), de sorte que cela vaincrait le but de l'ensemble de la construction.

Le meilleur que vous puissiez faire est d'envelopper C dans un constructeur d'A et B, c'est-à-dire: xxx

puis vous pouvez envelopper un c avec le AC ou le constructeur bc pour créer une valeur de type A ou b respectivement.


2 commentaires

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 pour créer une valeur de type A et bc x pour créer une valeur de type b . x par lui-même ne peut pas avoir deux types différents.



4
votes

La raison pour laquelle vous ne pouvez pas faire ce xxx pré>

est la suivante. Dis que vous écrivez du code plus tard sur: p> xxx pré>

qui construit une paire composée de 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> xxx pré>

car x code> est un constructeur de type A code>, mais également valide >

foo :: a -> B -> (a,B)


0 commentaires

1
votes

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"


0 commentaires

0
votes

Vous ne pouvez pas faire ce que vous voulez parce que vous déclarez plusieurs constructeurs de données. Dans xxx pré>

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


0 commentaires