In Elm, kann ich nicht herausfinden , wenn type
das entsprechende Schlüsselwort vs. ist type alias
. Die Dokumentation scheint keine Erklärung dafür zu haben, und ich kann auch keine in den Versionshinweisen finden. Ist das irgendwo dokumentiert?
Wie ich es mir vorstelle:
type
wird zum Definieren neuer Vereinigungstypen verwendet:
type Thing = Something | SomethingElse
Vor dieser Definition Something
und SomethingElse
bedeutete nichts. Jetzt sind beide vom Typ Thing
, den wir gerade definiert haben.
type alias
wird verwendet, um einem anderen bereits vorhandenen Typ einen Namen zu geben:
type alias Location = { lat:Int, long:Int }
{ lat = 5, long = 10 }
hat Typ { lat:Int, long:Int }
, der bereits ein gültiger Typ war. Jetzt können wir aber auch sagen, dass es einen Typ hat, Location
da dies ein Alias für denselben Typ ist.
Es ist erwähnenswert, dass das Folgende gut kompiliert und angezeigt wird "thing"
. Auch wenn wir angeben , thing
ist ein String
und aliasedStringIdentity
nimmt ein AliasedString
, wir werden nicht einen Fehler , dass es einen Typenkonflikt zwischen String
/ AliasedString
:
import Graphics.Element exposing (show)
type alias AliasedString = String
aliasedStringIdentity: AliasedString -> AliasedString
aliasedStringIdentity s = s
thing : String
thing = "thing"
main =
show <| aliasedStringIdentity thing
{}
Datensatzsyntax verwenden, definieren Sie einen neuen Typ?{ lat:Int, long:Int }
definiert keinen neuen Typ. Das ist schon ein gültiger Typ.type alias Location = { lat:Int, long:Int }
definiert auch keinen neuen Typ, sondern gibt einem bereits gültigen Typ nur einen anderen (möglicherweise aussagekräftigeren) Namen.type Location = Geo { lat:Int, long:Int }
würde einen neuen Typ definieren (Location
)Der Schlüssel ist das Wort
alias
. Wenn Sie im Verlauf der Programmierung Dinge gruppieren möchten, die zusammengehören, fügen Sie sie in einen Datensatz ein, wie im Fall eines Punktesoder eine Studentenakte.
Wenn Sie diese Datensätze weitergeben müssen, müssen Sie den gesamten Typ wie folgt buchstabieren:
Wenn Sie einen Punkt aliasen könnten, wäre die Signatur viel einfacher zu schreiben!
Ein Alias ist also eine Abkürzung für etwas anderes. Hier ist es eine Abkürzung für einen Datensatztyp. Sie können sich vorstellen, einem Datensatztyp, den Sie häufig verwenden, einen Namen zu geben. Aus diesem Grund wird es als Alias bezeichnet - es ist ein anderer Name für den nackten Datensatztyp, der durch dargestellt wird
{ x:Int, y:Int }
Löst
type
ein anderes Problem. Wenn Sie von OOP kommen, ist dies das Problem, das Sie mit Vererbung, Überladung von Operatoren usw. lösen. Manchmal möchten Sie die Daten als generische Sache behandeln, und manchmal möchten Sie sie wie eine bestimmte Sache behandeln.Ein alltäglicher Ort, an dem dies geschieht, ist das Weitergeben von Nachrichten - wie das Postsystem. Wenn Sie einen Brief senden, soll das Postsystem alle Nachrichten als gleich behandeln, sodass Sie das Postsystem nur einmal entwerfen müssen. Außerdem sollte die Weiterleitung der Nachricht unabhängig von der darin enthaltenen Nachricht sein. Erst wenn der Brief sein Ziel erreicht, interessiert es Sie, was die Nachricht ist.
Auf die gleiche Weise können wir a
type
als eine Vereinigung aller verschiedenen Arten von Nachrichten definieren, die auftreten können. Angenommen, wir implementieren ein Nachrichtensystem zwischen Studenten und ihren Eltern. Es gibt also nur zwei Nachrichten, die College-Kinder senden können: "Ich brauche Biergeld" und "Ich brauche Unterhosen".Wenn wir nun das Routing-System entwerfen, können die Typen für unsere Funktionen einfach weitergegeben werden
MessageHome
, anstatt sich über die verschiedenen Arten von Nachrichten Gedanken zu machen. Das Routing-System kümmert sich nicht darum. Es muss nur wissen, dass es ein istMessageHome
. Erst wenn die Nachricht ihr Ziel erreicht, das Zuhause der Eltern, müssen Sie herausfinden, was es ist.Wenn Sie die Elm-Architektur kennen, ist die Aktualisierungsfunktion eine riesige Fallanweisung, da dies das Ziel ist, an das die Nachricht weitergeleitet und somit verarbeitet wird. Und wir verwenden Union-Typen, um einen einzelnen Typ zu haben, mit dem wir uns beim Weitergeben der Nachricht befassen können, können dann aber eine case-Anweisung verwenden, um genau herauszufinden, um welche Nachricht es sich handelt, damit wir damit umgehen können.
quelle
Lassen Sie mich die vorherigen Antworten ergänzen, indem ich mich auf Anwendungsfälle konzentriere und einen kleinen Kontext zu Konstruktorfunktionen und -modulen gebe.
Verwendung von
type alias
Erstellen eines Alias und einer Konstruktorfunktion für einen Datensatz
Dies ist der häufigste Anwendungsfall: Sie können einen alternativen Namen und eine Konstruktorfunktion für eine bestimmte Art von Datensatzformat definieren.
Das Definieren des Typalias impliziert automatisch die folgende Konstruktorfunktion (Pseudocode):
Person : String -> Int -> { name : String, age : Int }
Dies kann nützlich sein, beispielsweise wenn Sie einen Json-Decoder schreiben möchten.
Geben
Sie die erforderlichen Felder an. Sie nennen es manchmal "erweiterbare Datensätze", was irreführend sein kann. Diese Syntax kann verwendet werden, um anzugeben, dass Sie einen Datensatz mit bestimmten vorhandenen Feldern erwarten. Sowie:
Dann können Sie die obige Funktion wie folgt verwenden (zum Beispiel aus Ihrer Sicht):
Richard Feldmans Vortrag auf ElmEurope 2017 könnte einen weiteren Einblick geben, wann sich dieser Stil lohnt.
Umbenennen von Inhalten
Sie können dies tun, da die neuen Namen später in Ihrem Code eine zusätzliche Bedeutung haben können, wie in diesem Beispiel
Vielleicht ist ein besseres Beispiel für diese Art der Verwendung im Kern
Time
.Erneutes Offenlegen eines Typs aus einem anderen Modul
Wenn Sie ein Paket (keine Anwendung) schreiben, müssen Sie möglicherweise einen Typ in einem Modul implementieren, möglicherweise in einem internen (nicht belichteten) Modul, aber Sie möchten den Typ aus einem anderen Modul verfügbar machen ein anderes (öffentliches) Modul. Alternativ können Sie Ihren Typ aus mehreren Modulen verfügbar machen.
Task
in core und Http.Request in Http sind Beispiele für das erste, während das Paar Json.Encode.Value und Json.Decode.Value ein Beispiel für das spätere ist.Sie können dies nur tun, wenn Sie den Typ ansonsten undurchsichtig halten möchten: Sie machen die Konstruktorfunktionen nicht verfügbar. Für Details siehe Verwendungen von
type
unten.Es ist anzumerken, dass in den obigen Beispielen nur # 1 eine Konstruktorfunktion bereitstellt. Wenn Sie Ihren Typalias in # 1 auf diese Weise verfügbar machen
module Data exposing (Person)
, werden sowohl der Typname als auch die Konstruktorfunktion verfügbar gemacht.Verwendung von
type
Definieren eines markierten Vereinigungstyps
Dies ist der häufigste Anwendungsfall. Ein gutes Beispiel dafür ist der
Maybe
Typ im Kern :Wenn Sie einen Typ definieren, definieren Sie auch seine Konstruktorfunktionen. Im Falle von Vielleicht sind dies (Pseudocode):
Was bedeutet, wenn Sie diesen Wert deklarieren:
Sie können es entweder erstellen
oder
Die Tags
Just
undNothing
dienen nicht nur als Konstruktorfunktionen, sondern auch als Destruktoren oder Muster in einemcase
Ausdruck. Was bedeutet, dass Sie mit diesen Mustern in einem sehen könnenMaybe
:Sie können dies tun, da das Vielleicht-Modul wie folgt definiert ist
Es könnte auch sagen
Die beiden sind in diesem Fall gleichwertig, aber explizit zu sein wird in Elm als Tugend angesehen, insbesondere wenn Sie ein Paket schreiben.
Ausblenden von Implementierungsdetails
Wie oben erwähnt, ist es eine bewusste Entscheidung, dass die Konstruktorfunktionen von
Maybe
für andere Module sichtbar sind.Es gibt jedoch auch andere Fälle, in denen der Autor beschließt, sie auszublenden. Ein Beispiel hierfür ist im Kern
Dict
. Als Konsument des Pakets sollten Sie nicht in der Lage sein, die Implementierungsdetails des Rot / Schwarz-Baum-Algorithmus dahinter zu sehenDict
und direkt mit den Knoten zu spielen. Durch das Ausblenden der Konstruktorfunktionen wird der Benutzer Ihres Moduls / Pakets gezwungen, nur Werte Ihres Typs über die von Ihnen bereitgestellten Funktionen zu erstellen (und diese Werte dann zu transformieren).Dies ist der Grund, warum manchmal solche Dinge im Code erscheinen
Im Gegensatz zur
type alias
Definition oben in diesem Beitrag erstellt diese Syntax einen neuen "Union" -Typ mit nur einer Konstruktorfunktion, diese Konstruktorfunktion kann jedoch vor anderen Modulen / Paketen verborgen werden.Wenn der Typ wie folgt belichtet wird:
Nur Code im
Data
Modul kann einen Personenwert erstellen, und nur dieser Code kann Musterübereinstimmungen erstellen.quelle
Der Hauptunterschied besteht meines Erachtens darin, ob die Typprüfung Sie anschreit, wenn Sie den Typ "synomisch" verwenden.
Erstellen Sie die folgende Datei, platzieren Sie sie irgendwo und führen Sie sie aus
elm-reactor
. Gehen Sie dann zuhttp://localhost:8000
, um den Unterschied zu sehen:Wenn Sie
2.
kommentieren und kommentieren, werden1.
Sie sehen:quelle
An
alias
ist nur ein kürzerer Name für einen anderen Typ, ähnlich wieclass
in OOP. Exp:Ein
type
(ohne Alias) können Sie Ihre eigene Art zu definieren, so dass Sie Typen wie definieren könnenInt
,String
... für Sie App. Zum Beispiel kann es im allgemeinen Fall zur Beschreibung eines App-Status verwendet werden:So können Sie es einfach in
view
Ulme handhaben :Ich denke du kennst den Unterschied zwischen
type
undtype alias
.Aber warum und wie man es benutzt
type
undtype alias
was mit derelm
App wichtig ist , ihr könnt den Artikel von Josh Clayton lesenquelle