Ich bin wirklich daran interessiert herauszufinden, wo die Unterschiede liegen, und allgemeiner, kanonische Anwendungsfälle zu identifizieren, in denen HLists nicht verwendet werden können (oder vielmehr keine Vorteile gegenüber regulären Listen bieten).
(Mir ist bewusst, dass es TupleN
in Scala 22 (glaube ich) gibt , während man nur eine einzige HList benötigt, aber das ist nicht der konzeptionelle Unterschied, an dem ich interessiert bin.)
Ich habe im folgenden Text einige Fragen markiert. Es ist möglicherweise nicht notwendig, sie zu beantworten, sie sollen eher auf Dinge hinweisen, die mir unklar sind, und die Diskussion in bestimmte Richtungen leiten.
Motivation
Ich habe kürzlich einige Antworten auf SO gesehen, in denen Leute vorgeschlagen haben, HLists zu verwenden (zum Beispiel, wie von Shapeless bereitgestellt ), einschließlich einer gelöschten Antwort auf diese Frage . Es entstand diese Diskussion , die wiederum diese Frage auslöste.
Intro
Es scheint mir, dass Listen nur dann nützlich sind, wenn Sie die Anzahl der Elemente und ihre genauen Typen statisch kennen. Die Anzahl ist eigentlich nicht entscheidend, aber es ist unwahrscheinlich, dass Sie jemals eine Liste mit Elementen unterschiedlicher, aber statisch genau bekannter Typen erstellen müssen, aber dass Sie deren Anzahl statisch nicht kennen. Frage 1: Könnten Sie ein solches Beispiel überhaupt schreiben, z. B. in einer Schleife? Meine Intuition ist, dass eine statisch genaue Liste mit einer statisch unbekannten Anzahl beliebiger Elemente (willkürlich relativ zu einer bestimmten Klassenhierarchie) einfach nicht kompatibel ist.
HLists vs. Tuples
Wenn dies zutrifft, dh Sie kennen statisch Nummer und Typ - Frage 2: Warum nicht einfach ein n-Tupel verwenden? Sicher, Sie können eine HList typsicher zuordnen und falten (was Sie auch, aber nicht typsicher, mit Hilfe von über ein Tupel tun können productIterator
), aber da Anzahl und Typ der Elemente statisch bekannt sind, können Sie wahrscheinlich einfach auf die Tupelelemente zugreifen direkt und führen Sie die Operationen.
Auf der anderen Seite, wenn die Funktion, die f
Sie einer hlist zuordnen, so allgemein ist, dass sie alle Elemente akzeptiert - Frage 3: Warum nicht über verwenden productIterator.map
? Ok, ein interessanter Unterschied könnte sich aus dem Überladen von Methoden ergeben: Wenn wir mehrere überladene f
Methoden hätten, könnte der Compiler aufgrund der stärkeren Typinformationen, die von der hlist bereitgestellt werden (im Gegensatz zum productIterator), eine spezifischere auswählen f
. Ich bin mir jedoch nicht sicher, ob dies in Scala tatsächlich funktionieren würde, da Methoden und Funktionen nicht identisch sind.
HLists und Benutzereingaben
Aufbauend auf der gleichen Annahme, dass Sie Anzahl und Typ der Elemente statisch kennen müssen - Frage 4: Können Listen in Situationen verwendet werden, in denen die Elemente von irgendeiner Art von Benutzerinteraktion abhängen? Stellen Sie sich beispielsweise vor, Sie füllen eine hlist mit Elementen innerhalb einer Schleife. Die Elemente werden von irgendwoher gelesen (Benutzeroberfläche, Konfigurationsdatei, Interaktion mit dem Akteur, Netzwerk), bis eine bestimmte Bedingung erfüllt ist. Was wäre der Typ der hlist? Ähnliches gilt für eine Schnittstellenspezifikation getElements: HList [...], die mit Listen statisch unbekannter Länge arbeiten soll und die es Komponente A in einem System ermöglicht, eine solche Liste beliebiger Elemente von Komponente B abzurufen.
FunctionN
Merkmale nicht über Arity abstrahieren können: github.com/paulbutcher/ScalaMock/blob/develop/core/src/main/… github.com/paulbutcher/ScalaMock/blob / Develop / Core / Src / Main /… Leider ist mir keine Möglichkeit bewusst, wie ich Shapeless verwenden kann, um dies zu vermeiden, da ich mich mit "echten"FunctionN
s befassen mussUm ganz klar zu sein, eine HList ist im Wesentlichen nichts anderes als ein Stapel
Tuple2
mit etwas anderem Zucker.Bei Ihrer Frage geht es also im Wesentlichen um die Unterschiede zwischen der Verwendung verschachtelter Tupel und flachen Tupeln, aber die beiden sind isomorph, sodass es am Ende wirklich keinen Unterschied gibt, außer der Bequemlichkeit, welche Bibliotheksfunktionen verwendet werden können und welche Notation verwendet werden kann.
quelle
Es gibt viele Dinge, die man mit Tupeln nicht (gut) machen kann:
Sie können das alles natürlich mit Tupeln machen, aber im allgemeinen Fall nicht. Wenn Sie also HLists verwenden, wird Ihr Code trockener.
quelle
Ich kann das in super einfacher Sprache erklären:
Die Benennung von Tupel und Liste ist nicht signifikant. HLists könnten als HTuples bezeichnet werden. Der Unterschied besteht darin, dass Sie dies in Scala + Haskell mit einem Tupel (mithilfe der Scala-Syntax) tun können:
Um ein Eingabetupel mit genau zwei Elementen eines beliebigen Typs zu verwenden, fügen Sie ein drittes Element hinzu und geben Sie ein vollständig typisiertes Tupel mit genau drei Elementen zurück. Dies ist zwar völlig generisch gegenüber Typen, muss jedoch die Eingabe- / Ausgabelängen explizit angeben.
Mit einer HList im Haskell-Stil können Sie diese generische Überlänge festlegen, sodass Sie an jede Länge von Tupel / Liste anhängen und ein vollständig statisch typisiertes Tupel / eine vollständig statisch typisierte Liste zurückerhalten können. Dieser Vorteil gilt auch für homogen typisierte Sammlungen, bei denen Sie ein int an eine Liste mit genau n Ints anhängen und eine statisch typisierte Liste mit genau (n + 1) Ints zurückerhalten können, ohne n explizit anzugeben.
quelle