Warum sind gleichnamige Datenkonstruktoren in verschiedenen Typkonstruktoren nicht zulässig?

11

Die folgende Erklärung gibt einen Fehler aus:

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

nämlich Multiple declarations of 'Translate'.

Nun frage ich mich, warum diese Einschränkung eingeführt wurde?

Wenn die Einschränkung nicht da wäre, könnte man schreiben

Translate (1, 1) Rect 2 2 und Translate (1, 2, 3) Cuboid 1 1 1das klingt natürlich.

Ich sehe nicht (sofort), wie dies zu einem Analyseproblem führen könnte, das die Verwendung desselben Namens verbietet. Der Typ könnte durch das Argument abgeleitet werden ( Rect 2 2ist ein Obj2d, Cuboid 1 1 1ist ein Obj3d).

Ich bin mir sicher, dass es einen guten Grund gibt, warum die Sprachdesigner die Verwendung des gleichen Namens für Datenkonstruktoren unterschiedlichen Typs nicht zulassen, aber ich möchte lernen: Warum, wenn dies nicht offensichtlich erforderlich ist?

(Und Typendisambiguierung ist das Brot-und-Butter-Geschäft von Haskell!)

Ein Sz
quelle
3
In Bezug auf den Typ, auf den das Argument schließen lässt: Ist Ihnen bewusst, dass der Typ des Arguments manchmal vom Typ der Funktion abgeleitet wird ?
@delnan Das war mir nicht bewusst ... klingt nach einer Antwort für mich. Ich hatte immer gedacht, dass die Inferenz von unten nach oben ist, obwohl ich die Mehrdeutigkeitsauflösung anhand von Typinformationen auf der anderen Seite des Typdiagramms sehen konnte, die Sie als entscheidenden Faktor beschreiben ... mein mentales Bild dafür sind Rückgabetypen am unteren Rand des Grafik- und Funktionsaufrufe oben, die Auflösung ist ein Aggregat, das durch Zusammenklappen von unten gebildet wird, aber das ist nicht ganz das ganze Bild, sagen Sie? Es überrascht nicht, dass dies in einer abhängig getippten Sprache mit perfekter Schlussfolgerung wahrscheinlich genauer ist.
Jimmy Hoffa

Antworten:

13

Dies liegt daran, dass Datenkonstruktoren nur Funktionen sind und das Überladen von Funktionen in Haskell nicht zulässig ist. Es ist möglicherweise klarer, wenn Sie die GADT-Syntax verwenden, um Ihre Typen zu definieren:

{-# LANGUAGE GADTs #-}
data Obj2d where
    Rect :: Float -> Float -> Obj2d   -- a function from floats to obj2d's
    Translate :: Vec2d -> Obj2d       -- a function from vec2d's to Obj2d's

Ich glaube, sie (die GHC-Entwickler) arbeiten an möglichen Lösungen für dieses Problem, indem sie eine neue type classfür alle Typen einführen , die denselben Datenkonstruktor oder ähnliches verwenden. Bleiben Sie also auf dem Laufenden, eine Lösung für Ihr Problem könnte bald kommen! (Ich hoffe)

bstamour
quelle
Ich freue mich auf jeden Fall auf diese type classKonstrukte, die Sie festlegen. - Der Grund ist: Ich habe kein Problem, ich kann Translate2und Translate3d, aber ich möchte den Namespace lieber nicht verschmutzen.
A Sz
Ich bin kein GHC-Entwickler, also ist es nur zu hören. Ich hoffe es passiert auch.
Bstamour