La déclaration suivante donne une erreur:
type Vec2d = (Float, Float)
type Vec3d = (Float, Float, Float)
-- Rect x y defines a rectangle spanning from (0,0) to (x,y)
data Obj2d = Rect Float Float
| Translate Vec2d Obj2d
-- Cuboid x y z defines a cuboid spanning from (0,0,0) to (x,y,z)
data Obj3d = Cuboid Float Float Float
| Translate Vec3d Obj3d
à savoir Multiple declarations of 'Translate'
.
Maintenant, je me demande pourquoi cette limitation a été introduite?
Si la limitation n'était pas là, on pourrait écrire
Translate (1, 1) Rect 2 2
et
Translate (1, 2, 3) Cuboid 1 1 1
, ce qui semble naturel.
Je ne vois pas (immédiatement) comment cela pourrait entraîner un problème d'analyse pour interdire d'utiliser le même nom, le type pourrait être déduit par l'argument ( Rect 2 2
est un Obj2d
, Cuboid 1 1 1
est un Obj3d
).
Je suis sûr qu'il y a une bonne raison pour laquelle les concepteurs de langage ont choisi de ne pas utiliser le même nom pour les constructeurs de données de différents types, mais j'aimerais savoir: pourquoi, quand ce n'est pas évidemment nécessaire?
(Et la désambiguïsation de type est l'affaire du pain et du beurre de Haskell!)
Réponses:
En effet, les constructeurs de données ne sont que des fonctions et la surcharge de fonctions n'est pas autorisée dans Haskell. Il pourrait être plus clair si vous utilisez la syntaxe GADT pour définir vos types:
Je pense qu'ils (les développeurs du GHC) travaillent sur des solutions possibles à ce problème en introduisant un nouveau
type class
pour tous les types qui partagent le même constructeur de données, ou quelque chose de similaire. Alors restez à l'écoute, une solution à votre problème pourrait bientôt arriver! (J'espère)la source
type class
constructions que vous stipulez. - La raison en est: je n'ai pas de problème, je peux le faireTranslate2
etTranslate3d
, mais je préfère ne pas polluer l'espace de noms.