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 ... else
Teil 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 Either
Daten 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 ... else
kö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 show
Funktionsparameter verwendet werden kann, und zu entscheiden, ob die Typen korrekt sind oder nicht. Noch besser ist, dass diese show
Funktion 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?
quelle
if ... then ... else ...
, muss den gleichen Typ imthen
undelse
Teil haben. Sie können es in einigen Programmiersprachen als ternären Operator sehen.making all conversions explicit
. In meiner Frage möchte ich nicht, dass HaskellInt
einDouble
oder umgekehrt wirft . Ich habe diese beiden Typen nur als Beispiel verwendet. Sie könnten jedesInt
mita
undDouble
mitb
in meiner Frage ersetzen , wo beide Typen abgeleitet sindShow
. Ich verstehe, dass esanonymous sum types
in 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.x :: Int | Bool
und wir kompilieren müssenshow x
, gibt es keine einfache Möglichkeit zu wissen, welcher Zeiger auf die Funktion zum Aufrufenshow
in einem auf Typlöschung basierenden RTS verwendet werden soll. Wir müssten wahrscheinlich zur Laufzeit einige Informationen auf Typebene aufbewahren.(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 sollteInt
.Antworten:
Alle Teile eines Ausdrucks müssen gut typisiert sein. Die Art von
if someCondition then someInt else someDouble
müsste so etwas seinexists 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.
quelle
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.typeof
Operator 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.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 FreiheitenNum
, sie sind nicht wichtig).Wenn dies einen Wert vom Typ zurückgeben sollte
(Int | String)
, was sollte dann der folgende zurückgeben?(Int | Int)
Natürlich, aber wenn sich dies von der Ebene unterscheidet, sindInt
wir in großen Schwierigkeiten. Sollte(Int | Int)
also identisch mit plain seinInt
.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.
Welchen Typ hat das
mysteryType
nun? OffensichtlichRecht? Was wäre wenn
a
undb
vom gleichen Typ sind?Dies sollte klar sein,
Int
wie wir zuvor vereinbart haben. Geben Sie jetztmysteryType
manchmal 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.
quelle