Ich sehe jetzt, dass Racket Typen hat. Auf den ersten Blick scheint es fast identisch mit der Haskell-Eingabe zu sein. Aber deckt Lisps CLOS einige der Bereiche ab, die Haskell-Typen abdecken? Das Erstellen eines sehr strengen Haskell-Typs und eines Objekts in einer beliebigen OO-Sprache scheint vage ähnlich zu sein. Es ist nur so, dass ich etwas von der Haskell-Kool-Hilfe getrunken habe und ich bin total paranoid, dass ich wegen dynamischer Eingabe geschraubt werde, wenn ich die Lisp-Straße entlang gehe.
quelle
Object
oder was auch immer die Wurzel des Typbaums ist. Dies ist weniger ausdrucksvoll , weil Sie beraubt die Möglichkeit zu sagen , dass bestimmte Variablen nur bestimmte Werte enthalten.Typed Racket unterscheidet sich stark von Haskell. Typsysteme in Lisp und Scheme und tatsächlich Typsysteme in traditionell untypisierten Sprachökosystemen im Allgemeinen haben ein grundlegendes Ziel, das andere Typsysteme nicht haben - sie arbeiten mit vorhandenem untypisiertem Code zusammen . Typed Racket führte beispielsweise ganz neue Typisierungsregeln ein, um verschiedene Racket-Redewendungen zu berücksichtigen. Betrachten Sie diese Funktion:
Bei nicht leeren Listen wird das erste Element zurückgegeben. Bei leeren Listen wird false zurückgegeben. Dies ist in untypisierten Sprachen üblich. Eine getippte Sprache würde einen Wrapper-Typ wie verwenden
Maybe
oder im leeren Fall einen Fehler auslösen. Wenn wir dieser Funktion einen Typ hinzufügen möchten, welcher Typ sollte verwendet werden? Es ist nicht[a] -> a
(in Haskell-Notation), weil es false zurückgeben kann. Dies ist auch nicht[a] -> Either a Boolean
der Fall, da (1) im leeren Fall immer false zurückgegeben wird, kein beliebiger Boolescher Wert, und (2) ein Typ vom Typ Elemente einschließtLeft
und falschRight
einfügt und Sie das "entweder auspacken" müssen, um zum eigentlichen Element zu gelangen. Stattdessen gibt der Wert eine echte Vereinigung zurück- Es gibt keine Wrapping-Konstruktoren, es wird in einigen Fällen einfach ein Typ und in anderen Fällen ein anderer Typ zurückgegeben. In Typed Racket wird dies mit dem Union-Typ-Konstruktor dargestellt:Der Typ
(U A #f)
gibt an, dass die Funktion entweder ein Element der Liste oder false ohne Umbruchinstanz zurückgeben kannEither
. Der Typprüfer kann daraus schließen, dasssome-list
es sich entweder um einen Typ(Pair A (Listof A))
oder um eine leere Liste handelt, und schließt daraus, dass in den beiden Zweigen der if-Anweisung bekannt ist, welche davon der Fall ist . Die Typprüfung weiß, dass(car some-list)
die Liste im Ausdruck den Typ haben muss ,(Pair A (Listof A))
da die if-Bedingung dies sicherstellt. Dies wird als Vorkommenstypisierung bezeichnet und soll den Übergang von nicht typisiertem Code zu typisiertem Code erleichtern.Das Problem ist die Migration. Es gibt eine Menge untypisierten Racket-Codes, und Typed Racket kann Sie nicht einfach dazu zwingen, alle Ihre bevorzugten untypisierten Bibliotheken aufzugeben und einen Monat damit zu verbringen, Ihrer Codebasis Typen hinzuzufügen, wenn Sie ihn verwenden möchten. Dieses Problem tritt immer dann auf, wenn Sie einer vorhandenen Codebasis schrittweise Typen hinzufügen. Eine JavaScript-Anwendung dieser Ideen finden Sie unter TypeScript und unter Beliebiger Typ.
Ein schrittweises Typsystem muss Werkzeuge für den Umgang mit gängigen untypisierten Redewendungen und die Interaktion mit vorhandenem untypisiertem Code bereitstellen. Andernfalls ist die Verwendung sehr schmerzhaft. Ein Beispiel für Clojure finden Sie unter "Warum wir Core.typed nicht mehr verwenden" .
quelle