Es gibt mindestens drei beliebte Bibliotheken für den Zugriff auf und die Bearbeitung von Datensatzfeldern. Diejenigen, die ich kenne, sind: Datenzugriff, Fclabels und Objektive.
Persönlich habe ich mit Data Accessor angefangen und benutze sie jetzt. Vor kurzem gab es jedoch im Haskell-Café die Meinung, dass Fclabels überlegen seien.
Daher bin ich am Vergleich dieser drei (und vielleicht mehr) Bibliotheken interessiert.
data-structures
haskell
record
lenses
Teneriffa
quelle
quelle
lens
verfügt das Paket über die umfangreichsten Funktionen und Dokumentationen. Wenn Sie sich also nicht um die Komplexität und die Abhängigkeiten kümmern, ist dies der richtige Weg.Antworten:
Es gibt mindestens 4 Bibliotheken, von denen ich weiß, dass sie Objektive bereitstellen.
Die Vorstellung einer Linse ist, dass sie etwas Isomorphes liefert
Bereitstellung von zwei Funktionen: ein Getter und ein Setter
unterliegt drei Gesetzen:
Erstens, wenn Sie etwas setzen, können Sie es wieder herausholen
Zweitens ändert das Abrufen und anschließende Einstellen nichts an der Antwort
Und drittens ist das zweimalige Putten dasselbe wie das einmalige Putten oder vielmehr, dass der zweite Put gewinnt.
Beachten Sie, dass das Typsystem nicht ausreicht, um diese Gesetze für Sie zu überprüfen. Sie müssen sie daher selbst sicherstellen, unabhängig davon, welche Objektivimplementierung Sie verwenden.
Viele dieser Bibliotheken bieten darüber hinaus eine Reihe zusätzlicher Kombinatoren und normalerweise eine Form von Vorlagen-Haskell-Maschinen, um automatisch Linsen für die Felder einfacher Datensatztypen zu generieren.
In diesem Sinne können wir uns den verschiedenen Implementierungen zuwenden:
Implementierungen
fclabels
fclabels ist vielleicht die am einfachsten zu begründende Linsenbibliothek, da
a :-> b
es direkt in den obigen Typ übersetzt werden kann. Es bietet eine Kategorie- Instanz, für(:->)
die es nützlich ist, Objektive zusammenzustellen. Es bietet auch einen gesetzlosenPoint
Typ, der die Vorstellung einer hier verwendeten Linse verallgemeinert, und einige Leitungen für den Umgang mit Isomorphismen.Ein Hindernis für die Annahme von
fclabels
ist, dass das Hauptpaket die Schablonen-Haskell-Installation enthält, sodass das Paket nicht Haskell 98 ist und auch die (ziemlich unumstrittene)TypeOperators
Erweiterung erfordert .Datenzugriff
[Bearbeiten:
data-accessor
verwendet diese Darstellung nicht mehr, wurde jedoch in eine ähnliche Form wie die von verschobendata-lens
. Ich behalte diesen Kommentar jedoch.]Daten-Accessor ist etwas beliebter als
fclabels
, zum Teil , weil es ist Haskell 98. Allerdings ich in meinem Mund ein wenig erbrechen die Wahl der internen Repräsentation macht.Der Typ
T
, der zur Darstellung eines Objektivs verwendet wird, ist intern definiert alsFolglich müssen Sie für
get
den Wert eines Objektivs einen undefinierten Wert für das Argument 'a' angeben! Dies scheint mir eine unglaublich hässliche und Ad-hoc-Implementierung zu sein.Trotzdem hat Henning das Template-Haskell-Sanitär integriert, um die Accessoren automatisch für Sie in einem separaten ' Data-Accessor-Template' -Paket zu generieren .
Es hat den Vorteil einer anständig großen Anzahl von Paketen, die es bereits verwenden, nämlich Haskell 98, und die alles entscheidende
Category
Instanz bereitstellen. Wenn Sie also nicht darauf achten, wie die Wurst hergestellt wird, ist dieses Paket tatsächlich eine ziemlich vernünftige Wahl .Linsen
Als nächstes gibt es das Linsenpaket , das beobachtet, dass eine Linse einen Zustandsmonadenhomomorphismus zwischen zwei Zustandsmonaden bereitstellen kann, indem Linsen direkt als solche Monadenhomomorphismen definiert werden .
Wenn es sich tatsächlich die Mühe machen würde, einen Typ für seine Objektive bereitzustellen, hätten sie einen Typ vom Rang 2 wie:
Aus diesem Grund mag ich diesen Ansatz eher nicht, da er Sie unnötig aus Haskell 98 herauszieht (wenn Sie möchten, dass ein Typ Ihren Objektiven abstrakt zur Verfügung gestellt wird) und Ihnen die
Category
Instanz für Objektive entzieht , die Sie zulassen würden komponiere sie mit.
. Die Implementierung erfordert auch Typklassen mit mehreren Parametern.Beachten Sie, dass alle anderen hier erwähnten Objektivbibliotheken einen Kombinator bieten oder verwendet werden können, um denselben Zustandsfokalisierungseffekt zu erzielen. Sie können also nichts gewinnen, wenn Sie Ihr Objektiv direkt auf diese Weise codieren.
Darüber hinaus haben die zu Beginn angegebenen Nebenbedingungen in dieser Form keinen wirklich schönen Ausdruck. Wie bei 'fclabels' bietet dies eine Template-Haskell-Methode zum automatischen Generieren von Objektiven für einen Datensatztyp direkt im Hauptpaket.
Aufgrund der fehlenden
Category
Instanz, der Barockcodierung und der Anforderung von Template-Haskell im Hauptpaket ist dies meine am wenigsten bevorzugte Implementierung.Datenlinse
[Edit: Ab 1.8.0 sind diese vom Comonad-Transformers-Paket auf Data-Lens umgestiegen]
Mein
data-lens
Paket enthält Objektive im Sinne der Store Comonad.wo
Erweitert entspricht dies
Sie können dies als Ausklammern des allgemeinen Arguments aus dem Getter und dem Setter betrachten, um ein Paar zurückzugeben, das aus dem Ergebnis des Abrufens des Elements besteht, und einem Setter, um einen neuen Wert wieder einzugeben. Dies bietet den Rechenvorteil, den der 'Setter' bietet. Hier kann ein Teil der Arbeit recycelt werden, die verwendet wird, um den Wert herauszuholen, was zu einem effizienteren Änderungsvorgang führt als in der
fclabels
Definition, insbesondere wenn Accessoren verkettet sind.Es gibt auch eine gute theoretische Begründung für diese Darstellung, da die Teilmenge der 'Linsen'-Werte, die die drei zu Beginn dieser Antwort angegebenen Gesetze erfüllen, genau jene Linsen sind, für die die umhüllte Funktion eine' Comonad Coalgebra 'für die Store Comonad ist . Dies transformiert 3 haarige Gesetze für eine Linse
l
in 2 schön punktfreie Äquivalente:Dieser Ansatz wurde erstmals in Russell O'Connors "to
Functor
isLens
asApplicative
toBiplate
: Introducing Multiplate" erwähnt und beschrieben und wurde basierend auf einem Preprint von Jeremy Gibbons gebloggt.Es enthält auch eine Reihe von Kombinatoren für die strikte Arbeit mit Linsen und einige Standardlinsen für Behälter, wie z
Data.Map
.Die Linsen in
data-lens
Form aCategory
(im Gegensatz zumlenses
Paket) sind also Haskell 98 (im Gegensatz zufclabels
/lenses
) und sind vernünftig (im Gegensatz zum hinteren Ende von)data-accessor
data-lens-fd
Backend ) und bieten eine etwas effizientere Implementierung. Sie bieten die Funktionalität für die Arbeit mit MonadState für diejenigen, die bereit sind, nach draußen zu gehen von Haskell 98, und die Template-Haskell-Maschinerie ist jetzt über verfügbardata-lens-template
.Update 28.06.2012: Andere Implementierungsstrategien für Objektive
Isomorphismuslinsen
Es gibt zwei weitere erwägenswerte Objektivcodierungen. Die erste bietet eine schöne theoretische Möglichkeit, eine Linse als eine Möglichkeit zu betrachten, eine Struktur in den Wert des Feldes und "alles andere" zu zerlegen.
Gegeben ein Typ für Isomorphismen
so dass gültige Mitglieder erfüllen
hither . yon = id
, undyon . hither = id
Wir können eine Linse darstellen mit:
Diese sind in erster Linie nützlich, um über die Bedeutung von Objektiven nachzudenken, und wir können sie als Argumentationswerkzeug verwenden, um andere Objektive zu erklären.
van Laarhoven Linsen
Wir können Objektive so modellieren, dass sie mit
(.)
undid
auch ohneCategory
Instanz zusammengesetzt werden könnenals Typ für unsere Objektive.
Dann ist das Definieren eines Objektivs so einfach wie:
und Sie können selbst überprüfen, ob die Funktionszusammensetzung die Linsenzusammensetzung ist.
Ich habe kürzlich darüber geschrieben, wie Sie van Laarhoven-Objektive weiter verallgemeinern können , um Linsenfamilien zu erhalten, die die Feldtypen ändern können, indem Sie einfach diese Signatur auf verallgemeinern
Dies hat die unglückliche Konsequenz, dass der beste Weg, über Linsen zu sprechen, die Verwendung von Polymorphismus vom Rang 2 ist, aber Sie müssen diese Signatur nicht direkt verwenden, wenn Sie Linsen definieren.
Das, was
Lens
ich oben für definiert habe,_2
ist eigentlich einLensFamily
.Ich habe eine Bibliothek geschrieben, die Linsen, Linsenfamilien und andere Verallgemeinerungen enthält, einschließlich Getter, Setter, Falten und Durchquerungen. Es ist auf Hackage als
lens
Paket verfügbar .Ein großer Vorteil dieses Ansatzes besteht wiederum darin, dass Bibliotheksverwalter tatsächlich Objektive in diesem Stil in Ihren Bibliotheken erstellen können, ohne dass eine Abhängigkeit von der Objektivbibliothek entsteht, indem sie lediglich Funktionen mit Typ bereitstellen
Functor f => (b -> f b) -> a -> f a
für ihre jeweiligen Typen 'a' und 'b' bereitstellen. Dies senkt die Adoptionskosten erheblich.Da Sie das Paket nicht zum Definieren neuer Objektive verwenden müssen, entlastet dies meine früheren Bedenken hinsichtlich der Aufbewahrung der Bibliothek Haskell 98 erheblich.
quelle
:->
data-accessor
, und dann gab ich es an Henning weiter und hörte auf, darauf zu achten. Diea -> r -> (a,r)
Darstellung macht mich auch unbehaglich und meine ursprüngliche Implementierung war genau wie IhrLens
Typ. Heeennnninngg !!