Gibt es eine Alternative zu Datensätzen in Haskell?

8

Ich suche nach einer besseren Alternative zu den Standardsätzen, die nur automatisch generierte Accessor-Funktionen über Tupel sind. Das Problem ist die Benennung Probleme, bei denen Datensätze mit den gleichen Namen ihrer Felder die gleichen Accessor-Funktionen erhalten.

    
Aleksey Bykov 03.01.2014, 20:32
quelle

6 Antworten

6

Ich verwende das Objektiv mit der Funktion makeFields TH. So kann ich etwas tun:

%Vor%

Was hier passiert, ist, dass die makeFields-Funktion Typklassen HasName und HasEmail mit einem einzelnen Member (Name oder E-Mail) erstellt. Es erstellt auch Instanzen für diese Typen. MultiParamTypeClasses und funktionale Abhängigkeiten ermöglichen es, diese Elemente für verschiedene Datentypen "zu überladen".

makeFields per Konvention wird dies für jeden Datensatzkonstruktor tun, der mit einem Unterstrich beginnt, und der Name, den er für das Feld wählt, ist der Saldo des Konstruktornamens, der mit dem ersten Großbuchstaben beginnt. Also macht _corpEmail ein "email" -Feld.

Nun sind diese "Felder" Linsen und es gibt eine Menge Funktionen , die Sie mit ihnen anwenden können. Um einfach den Wert aus einem Datensatz zu erhalten, können Sie die Funktion "Ansicht" verwenden, z. B .:

view email myGuy

Es gibt eine Umkehrung dieser Funktion namens (^.), die eine Aufzeichnung als ersten Parameter und die Linse als zweite nimmt. Ich persönlich bevorzuge diesen Stil in vielen Fällen, aber ich benutze immer noch manchmal Ansicht, besonders in einem Punkt-freien Stil.

Lens ist viel größer als nur diese Funktion - ich persönlich finde diese Funktion überzeugend, aber das Wichtigste, was es für Sie tut, ist, Ihnen zu ermöglichen, diese Objektive zu komponieren, um tief in die Datenstrukturen zu kommen. Komposition ist einfach mit dem Operator (.) Wie jede andere Funktion; Wenn wir uns also vorstellen, dass mein Beispiel ein _corpPresident :: Person -Feld hat, könnte ich das tun:

%Vor%

Oder - um diesen verschachtelten Wert zu ändern:

%Vor%

Oder die gleiche Sache (mit mehr Operator-Wahnsinn):

%Vor%

Es gibt noch viel mehr und ich habe kaum selbst an der Oberfläche gekratzt. Die hackage docs sind gut, aber ich denke, der beste Weg, um anzufangen, ist mit dem Feldführer, der in der Readme des Github Repository .

    
Jeremy 05.01.2014 19:57
quelle
5

Meine Richtlinie für Namespace-Konflikte besteht darin, widersprüchliche Typen in separaten Modulen zu platzieren. Dann können Sie die Namespacing-Tools von Haskell verwenden, um Konflikte zu lösen. Ich wünschte jedoch, Haskell hätte mehrere Namespaces in einem einzigen Modul definieren können.

    
Gabriel Gonzalez 03.01.2014 21:22
quelle
4

Aus dem Haskel 98-Bericht

  

Operationen mit Feldbezeichnungen sind in Abschnitt 3.15 beschrieben. Eine Datendeklaration kann die gleiche Feldbezeichnung in mehreren Konstruktoren verwenden, solange die Typisierung des Feldes in allen Fällen nach der Typ-Synonym-Erweiterung gleich ist. Ein Label darf nicht von mehr als einem Typ im Bereich geteilt werden. Feldnamen teilen den Namespace der obersten Ebene mit gewöhnlichen Variablen und Klassenmethoden und dürfen nicht mit anderen Namen auf oberster Ebene im Geltungsbereich kollidieren.

Also nein, es gibt keinen Weg darum.

Normalerweise mache ich etwas wie

%Vor%

Aber um ehrlich zu sein, brauche ich selten eine Typklasse wie diese. Es zeigt, wie Sie denselben "Accessor" für verschiedene Datensatztypen verwenden können.

    
bheklilr 03.01.2014 20:37
quelle
1

Eine Vinyl Bibliothek führt eine Lösung ein. Um die Autoren zu zitieren:

  

Vinyl ist eine allgemeine Lösung für das Plattenproblem in Haskell mit Strings auf Typenebene und anderen modernen GHC-Features, die statische Strukturtypisierung (mit einer Subtyping-Beziehung) und automatische reihenpolymorphe Linsen aufweisen. All dies ist ohne Vorlage Haskell möglich.

Wenn jedoch der Speicherabdruck für Sie von Interesse ist, würde ich vorschlagen, mit Gabriels Vorschlag zu gehen, da Vinyl-Schallplatten schwerer sind.

Im Allgemeinen ist das Records-Problem ein berüchtigtes Problem und seit den späten 90ern werden großartige Lösungen vorgeschlagen (können Sie sich das vorstellen?). Aber seit es schwierig war, sie umzusetzen, ist niemand dazu gekommen. Kürzlich initiierte ich eine entsprechende Diskussion auf Reddit , dort können Sie interessante Informationen bekommen. Es stellt sich heraus, dass zumindest in Bezug auf das Namespacing-Problem einige Arbeiten durchgeführt werden und dass die Ergebnisse bald die Welt sehen werden.

    
Nikita Volkov 04.01.2014 00:46
quelle
1

Am einfachsten ist es, die Erweiterung DisambiguateRecordFields zu aktivieren. Das ändert nicht viel, es verwendet im Wesentlichen Haskell98-Datendeklarationen, erlaubt Ihnen aber, Feldnamen wiederzuverwenden. Ich habe festgestellt, dass es ziemlich gut funktioniert, besonders wenn Sie einen Schritt weiter gehen zu RecordWildCards .

    
leftaroundabout 04.01.2014 00:52
quelle
0

NamedFieldPuns mit DisambiguateRecordFields, aber das ist auf Funktion beschränkt und lässt Bindings, nicht beliebige Ausdrücke: Ссылка

    
misterbee 04.01.2014 17:32
quelle

Tags und Links