Summentypen - Warum in Haskell `show (Int | Double)` anders ist als `(show Int) | (zeige Double) `

9

Warum sind diese nicht gleichwertig?

show $ if someCondition then someInt else some double

und

if someCondition then show someInt else show someDouble

Ich verstehe, dass Sie, wenn Sie den if ... elseTeil im ersten Beispiel für sich selbst auf einen Ausdruck isolieren, seinen Typ nicht mit einem anonymen Summentyp darstellen können Int | Double, wie Sie ihn in TypeScript leicht tun könnten (unter Erwähnung von TypeScript, weil es der ist Sprache, die ich oft verwendet habe und die Summentypen unterstützt), und müsste auf die Verwendung der EitherDaten zurückgreifen, die dann basierend darauf aufgerufen würden show.

Das Beispiel, das ich hier gegeben habe, ist trivial, aber für mich ist es sinnvoller zu denken, "Okay, wir werden etwas zeigen, und das hängt von etwas ab someCondition", anstatt "Okay, wenn eine Bedingung wahr ist, dann zeige someInt, sonst zeige someDouble" und erlaube es auch für weniger Code-Duplizierung (hier wird die Show zweimal wiederholt, es könnte sich aber auch um eine Langfunktionsanwendung handeln und anstelle einer if ... elsekönnte> 2 zu berücksichtigende Zweige vorhanden sein)

Meiner Meinung nach sollte es für den Compiler einfach sein, zu überprüfen, ob jeder der Typen, aus denen der Summentyp besteht (hier Int | Double), als showFunktionsparameter verwendet werden kann, und zu entscheiden, ob die Typen korrekt sind oder nicht. Noch besser ist, dass diese showFunktion immer a zurückgibtstring unabhängig von den Parametertypen , sodass der Compiler nicht alle möglichen "Zweige" (also alle möglichen Typen) mit sich führen muss.

Ist es freiwillig, dass eine solche Funktion nicht existiert? Oder ist die Implementierung schwieriger als ich denke?

Mehdi Saffar
quelle
2
Ein if ... then ... else ..., muss den gleichen Typ im thenund elseTeil haben. Sie können es in einigen Programmiersprachen als ternären Operator sehen.
Willem Van Onsem
1
Ich stimme dem zu making all conversions explicit. In meiner Frage möchte ich nicht, dass Haskell Intein Doubleoder umgekehrt wirft . Ich habe diese beiden Typen nur als Beispiel verwendet. Sie könnten jedes Intmit aund Doublemit bin meiner Frage ersetzen , wo beide Typen abgeleitet sind Show. Ich verstehe, dass es anonymous sum typesin Haskell keine gibt, aber ich würde gerne wissen, warum dies der Fall ist und was uns davon abhält, die Sprache dafür zu entwerfen.
Mehdi Saffar
4
Ich denke, solche Typen werden Unionstypen genannt . Ein Summentyp ist im Wesentlichen eine markierte Variante des Vereinigungstyps, wobei jeder Wert ein linkes / rechtes Tag über den Wert des inneren Typs hinaus tragen muss. Ich gehe davon aus, dass eine Typinferenz mit Unionstypen mit allen Funktionen auf Typebene von Haskell sehr schwer zu erreichen ist. Wenn x :: Int | Boolund wir kompilieren müssen show x, gibt es keine einfache Möglichkeit zu wissen, welcher Zeiger auf die Funktion zum Aufrufen showin einem auf Typlöschung basierenden RTS verwendet werden soll. Wir müssten wahrscheinlich zur Laufzeit einige Informationen auf Typebene aufbewahren.
Chi
1
Keine anonymen Summentypen zu haben, ist eine Entwurfsentscheidung der Haskell-Designer. Ich bin mir nicht ganz sicher, welchen Nutzen sie für den Tisch bringen würden, aber ich sehe, wo sie die Dinge komplizieren würden. Ich vermute also, dass sie weggelassen werden, weil das Kosten-Nutzen-Verhältnis nicht vorhanden ist. Um jedoch absolut sicher zu sein, müssen Sie die Original-Sprachdesigner und / oder die aktuellen Betreuer fragen. Ich denke nicht, dass dies eine großartige SO-Frage wäre, da beim Entwerfen einer Sprache viele persönliche Meinungen und Vorlieben eine Rolle spielen.
n. 'Pronomen' m.
4
(String, Int)ist nicht anonym. Es ist nur ein normaler Produkttyp mit lustiger Syntax. (String | Int)wäre ganz anders. Fragen Sie sich zunächst, ob und warum (Int|Int)identisch sein sollte Int.
n. 'Pronomen' m.

Antworten:

8

Alle Teile eines Ausdrucks müssen gut typisiert sein. Die Art von if someCondition then someInt else someDoublemüsste so etwas sein exists a. Show a => a, aber Haskell unterstützt diese Art der existenziellen Quantifizierung nicht.

Update: Wie Chi in einem Kommentar betont , wäre dies auch möglich, wenn Haskell Unterstützung für Vereinigungs- / Schnittpunkttypen hätte (die nicht mit Summen- / Produkttypen identisch sind), aber leider nicht.

Joseph Sible-Reinstate Monica
quelle
Könnten Sie bitte den Unterschied zwischen Vereinigungs- / Schnittpunkttypen und Summen- / Produkttypen erläutern? Ich habe immer gedacht, dass sie bis auf die Anonymität gleich sind?
Mehdi Saffar
1
@MehdiSaffar Anonym wie in nicht getaggt, nicht wie in einem unbenannten Konstruktor. Mit anderen Worten, wenn Sie eine haben Int ∪ Double, dann wissen Sie, dass Sie eine der beiden haben, könnten aber keine Musterübereinstimmung durchführen, um zu sehen, welche, sodass Sie nur Dinge tun können, die für beide Möglichkeiten gültig sind.
Joseph Sible-Reinstate Monica
2
Aus Gründen der Übersichtlichkeit stehen in TypeScript zur Laufzeit Typinformationen zur Verfügung, sodass ein typeofOperator vorhanden ist, der das Fehlen von Tags ausgleichen und feststellen kann, welcher Typ ohnehin verwendet wird. Haskell ist vollständig typgelöscht. Wenn es diese Funktion unterstützt, gibt es kein Äquivalent dazu.
Joseph Sible-Reinstate Monica
7

Es gibt Produkttypen mit leichter Syntax, die (,)in Haskell geschrieben wurden. Man könnte sagen, dass ein Summentyp mit einer leichten Syntax, so etwas wie (Int | String), eine großartige Idee wäre. Die Realität ist komplizierter. Mal sehen warum (ich nehme mir ein paar Freiheiten Num, sie sind nicht wichtig).

if someCondition then 42 else "helloWorld"

Wenn dies einen Wert vom Typ zurückgeben sollte (Int | String), was sollte dann der folgende zurückgeben?

if someCondition then 42 else 0

(Int | Int)Natürlich, aber wenn sich dies von der Ebene unterscheidet, sind Intwir in großen Schwierigkeiten. Sollte (Int | Int)also identisch mit plain sein Int.

Man kann sofort erkennen, dass dies nicht nur eine einfache Syntax für Summentypen ist, sondern eine völlig neue Sprachfunktion. Eine andere Art von Typsystem, wenn Sie so wollen. Sollen wir einen haben?

Schauen wir uns diese Funktion an.

mysteryType x a b = if x then a else b

Welchen Typ hat das mysteryTypenun? Offensichtlich

mysteryType :: Bool -> a -> b -> (a|b)

Recht? Was wäre wenna und bvom gleichen Typ sind?

let x = mysteryType True 42 0

Dies sollte klar sein, Intwie wir zuvor vereinbart haben. Geben Sie jetzt mysteryTypemanchmal einen anonymen Summentyp zurück, manchmal nicht, je nachdem, welche Argumente Sie übergeben. Wie würden Sie mit einem solchen Ausdruck übereinstimmen? Was um alles in der Welt kannst du damit machen? Außer trivialen Dingen wie "show" (oder anderen Methoden anderer Typklassen, für die es sich um eine Instanz handeln würde), nicht viel. Es sei denn, Sie fügen der Sprache Informationen zum Laufzeittyp hinzutypeof sind verfügbar - und das macht Haskell zu einer völlig anderen Sprache.

Also ja. Warum ist Haskell kein TypeScript? Weil wir kein anderes TypeScript brauchen. Wenn Sie TypeScript möchten, wissen Sie, wo es zu finden ist.

n. 'Pronomen' m.
quelle
1
@MichaWiedenmann Ehrlich gesagt weiß ich nicht, ob "relevant" das richtige Wort ist. Ich denke, es ist auf die eine oder andere Weise hilfreich. Ja, ich habe einen Moment angehalten und überlegt, ob ich es aufnehmen soll. Aber ich bin manchmal dafür bekannt, falsch zu liegen.
n. 'Pronomen' m.
Kein Problem, es ist dein Beitrag, du entscheidest.
Micha Wiedenmann
Also, was sind deine Pronomen?
Feuer