Data.Text vs String

79

Während die allgemeine Meinung der Haskell-Community zu sein scheint, dass es immer besser ist, Textstatt zu verwenden String, Stringverwirrt mich die Tatsache, dass die APIs der meisten gepflegten Bibliotheken immer noch orientiert sind, zum Teufel. Auf der anderen Seite gibt es bemerkenswerte Projekte , die Stringinsgesamt als Fehler betrachtet werden und Preludebei denen alle Instanzen von String-orientierten Funktionen durch ihre TextGegenstücke ersetzt werden.

Gibt es also Gründe für Leute, weiterhin Stringschreiborientierte APIs zu schreiben, außer Abwärts- und Standard-Prelude-Kompatibilität und die "Switch-Making-Intertia"? Gibt es möglicherweise andere Nachteile Textim Vergleich zu String?

Das interessiert mich besonders, weil ich eine Bibliothek entwerfe und versuche zu entscheiden, welcher Typ zum Ausdrücken von Fehlermeldungen verwendet werden soll.

Nikita Volkov
quelle
Wie schwer wird es sein, beide zu unterstützen?
Daniel Wagner
6
@Vektorweg würde ich streiten. Da Stringes sich nur um einen Alias ​​für eine Liste von Chars handelt, weist es natürlich andere Leistungsmerkmale auf als monolithische Daten Text. Beide Typen sind für den Compiler überhaupt nicht von Belang, da sie nicht primitiv sind und in Bibliotheken definiert sind.
Nikita Volkov
1
@ DanielWagner Wäre es nicht eine nicht sehr motivierte Komplikation? Auf jeden Fall handelt es sich um einen allgemeinen Ansatz, wenn es ein gemeinsames Muster für die Unterstützung beider Typen in Bibliotheken gäbe, das beträchtlich wäre.
Nikita Volkov
3
@Vektorweg Es gibt einen guten Blog-Beitrag über den ausreichend intelligenten Compiler . (Ich habe gerade festgestellt, dass es auch GHC erwähnt.)
kqr
1
Gehen Sie für Text! Zukünftige Generationen könnten eines Tages von einer Welt ohne Zeichenfolgen profitieren, wenn wir das Hinzufügen von Zeichenfolgen-abhängigem Code einstellen.
Titou

Antworten:

30

Meine uneingeschränkte Vermutung ist, dass die meisten Bibliotheksautoren nicht mehr Abhängigkeiten als nötig hinzufügen möchten. Da Zeichenfolgen buchstäblich Teil jeder Haskell-Distribution sind (sie sind Teil des Sprachstandards!), Ist es viel einfacher, sie zu übernehmen, wenn Sie Zeichenfolgen verwenden und Ihre Benutzer nicht verlangen, Textverteilungen nach Hackage zu sortieren.

Es ist einer dieser "Designfehler", mit denen man nur leben muss, wenn man den größten Teil der Community nicht davon überzeugen kann, über Nacht zu wechseln. Schauen Sie sich an, wie lange es gedauert hat, bis Applicative zu einer Superklasse von Monad wurde - eine relativ kleine, aber begehrte Änderung - und stellen Sie sich vor, wie lange es dauern würde, alle String-Dinge durch Text zu ersetzen.


Um Ihre spezifischere Frage zu beantworten: Ich würde mich für String entscheiden, es sei denn, Sie erhalten durch die Verwendung von Text spürbare Leistungsvorteile. Fehlermeldungen sind normalerweise eher kleine einmalige Dinge, daher sollte es kein großes Problem sein, String zu verwenden.

Auf der anderen Seite, wenn Sie ein ideologischer Purist sind, der Pragmatismus für Idealismus meidet, dann entscheiden Sie sich für Text.


* Ich habe Designfehler in Angstzitate gesetzt, weil Zeichenfolgen als Zeichenliste eine nette Eigenschaft sind, mit der sie leicht über andere vorhandene Listenoperationsfunktionen nachgedacht und in diese integriert werden können.

kqr
quelle
4
Es geht nicht so sehr um eine Art fanatische Reinheit, sondern nur darum, dass ich lieber zu einem Wechsel zum Besseren beitrage (wenn es wirklich einer ist), als zu einer Stagnation suboptimaler Ansätze. Okay, Sie bestätigen also, dass die Verwendung von Text im Wesentlichen keine Nachteile hat?
Nikita Volkov
4
@NikitaVolkov Wenn Sie zu einem Wechsel beitragen möchten, können Sie meiner Meinung nach eine größere Änderung vornehmen, indem Sie sich an der Aktualisierung des Standards und der Lobbyarbeit / Konvertierung vorhandener Bibliotheken beteiligen. Praktisch keine anderen Nachteile als die, an die Sie denken können, wie die Adoptionsrate und Personen, die Musterübereinstimmungen für den ersten Buchstaben vornehmen oder eine Karte aus Data.List verwenden möchten und so weiter.
kqr
6
Das ist vielleicht nicht mehr so ​​wichtig, da Data.Text heutzutage eine Selbstverständlichkeit ist und mit GHC ausgeliefert wird (von dem ich annehme, dass die meisten Leute es heutzutage verwenden).
Profpatsch
23

Wenn Ihre API auf die Verarbeitung großer Mengen zeichenorientierter Daten und / oder verschiedener Codierungen abzielt, sollte Ihre API Text verwenden .

Wenn Ihr API ist in erster Linie mit kleinen Einmal Saiten für den Umgang, dann den eingebauten in mit String - Typ sollte in Ordnung sein.

Wenn Sie String für große Textmengen verwenden, verbrauchen Anwendungen, die Ihre API verwenden, erheblich mehr Speicher. Die Verwendung mit fremden Codierungen kann die Verwendung je nach Funktionsweise Ihrer API erheblich erschweren.

String ist ziemlich teuer (mindestens 5N Wörter, wobei N die Anzahl der Zeichen im String ist). Ein Wort entspricht der Anzahl der Bits wie die Prozessorarchitektur (z. B. 32 Bit oder 64 Bit): http://blog.johantibell.com/2011/06/memory-footprints-of-some-common-data.html

Alain O'Dea
quelle
11
Ich glaube nicht, dass ASCII etwas damit zu tun hat: Sowohl String als auch Text unterstützen Unicode gleichermaßen und verschieben die eigentliche Codierung unter Ihre Abstraktionsebene. In beiden Fällen müssten Sie sich nur an den Grenzen Ihres Programms darum kümmern. Die Unicode-Unterstützung ist kein gutes Kriterium für die Auswahl.
Tikhon Jelvis
4
Sie haben sich Stringmit ByteStringdem ASCII verwechselt.
Nikita Volkov
1
@TikhonJelvis gibt es nicht das Problem, dass einer Charin der Zeichenfolge nur Teil eines Unicode-Zeichens und nicht eines einzelnen Unicode-Zeichens sein kann? Wird das nicht Verwirrung stiften? Löst Data.Text das?
João Portela
3
@ João Portela: Haskells Charsind nicht wie Java oder C # char. Sie sind vollständige Unicode-Codepunkte (32 Bit).
Tobias Brandt
1
Sie sind 32bit? Ich habe immer angenommen, dass sie 16 Bit sind. Danke, dass du das geklärt hast.
João Portela
9

Es gibt mindestens drei Gründe, [Char] in kleinen Projekten zu verwenden.

  1. [Char] stützt sich nicht auf arkane Mitarbeiter wie Fremdzeiger, Rohspeicher, Roh-Arrays usw., die auf verschiedenen Plattformen unterschiedlich funktionieren oder sogar gar nicht verfügbar sind

  2. [Char]ist die Verkehrssprache in Haskell. Es gibt mindestens drei ‚effizient‘ Wege Unicode - Daten in Haskell zu behandeln: utf8-bytestring, Data.Text.Textund Data.Vector.Unboxed.Vector Charjede erfordert den Umgang mit Zusatzpaket.

  3. Durch die Verwendung von [Char]one erhalten Sie Zugriff auf alle []Funktionen der Monade, einschließlich vieler spezifischer Funktionen (alternative Zeichenfolgenpakete versuchen, dabei zu helfen, aber immer noch).

Persönlich halte ich utf16 -basierte Data.Texteiner der fragwürdigen desicions der Haskell - Gemeinschaft, da utf16 Mähdreschern Mängel sowohl utf8 und UTF32 kodieren , während keines ihrer Vorteile haben.

Permeakra
quelle
1
Können Sie weitere Informationen darüber geben, warum Sie utf16 für minderwertig halten? Nicht unbedingt als Teil dieser Antwort, aber vielleicht zu einem Artikel, der Ihre Haltung beschreibt.
Wizek
2
@Wizek - es ist eine ziemlich verbreitete Meinung. Siehe programmers.stackexchange.com/questions/102205/… .
Jules
5

Ich frage mich, ob Data.Text immer effizienter ist als Data.String ???

"Nachteile" ist beispielsweise O (1) für Zeichenfolgen und O (n) für Text. Anhängen ist O (n) für Zeichenfolgen und O (n + m) für strenge Texte. Gleichfalls,

    let foo = "foo" ++ bigchunk
        bar = "bar" ++ bigchunk

ist für Strings platzsparender als für strenge Texte.

Ein weiteres Problem, das nicht mit der Effizienz zusammenhängt, ist der Mustervergleich (übersichtlicher Code) und die Faulheit (vorhersehbar pro Zeichen in Strings, irgendwie abhängig von der Implementierung in Lazy Text).

Texte eignen sich offensichtlich gut für statische Zeichenfolgen und für direkte Änderungen. Für andere Formen der strukturellen Bearbeitung kann Data.String Vorteile haben.

Vorbeigehen
quelle
1
Leistung und Effizienz sind mehr als nur ein großes Problem. Die String-Implementierung ist eine verknüpfte Liste mit einem Knoten für jedes einzelne Zeichen. Das ist viel zusätzlicher Speicher, Cache und Fragmentierung für eine einfache Zeichenfolge.
Justin Meiners
4

Ich glaube nicht, dass es einen einzigen technischen Grund gibt, warum String bleiben soll. Und ich kann mehrere sehen, damit es geht.

Insgesamt würde ich zunächst argumentieren, dass es im Fall Text / String nur eine beste Lösung gibt:

  • Streicherleistungen sind schlecht, da sind sich alle einig

  • Text ist nicht schwer zu verwenden. Alle Funktionen, die üblicherweise für Zeichenfolgen verwendet werden, sind für Text verfügbar, sowie einige nützliche Funktionen im Zusammenhang mit Zeichenfolgen (Ersetzen, Auffüllen, Codieren).

  • Zwei Lösungen zu haben, schafft unnötige Komplexität, wenn nicht alle Basisfunktionen polymorph gemacht werden. Beweis: Es gibt SO Fragen zum Thema automatische Konvertierungen . Das ist also ein Problem.

Eine Lösung ist also weniger komplex als zwei, und die Mängel von String lassen sie schließlich verschwinden. Je früher desto besser !

Titou
quelle
1
So einfach ist das nicht, nein. Es gibt einiges an nicht trivialem Code für die Verarbeitung von Zeichenfolgen, der darauf ausgelegt ist Stringund überhaupt nicht gut funktioniert Text.
Feuer
@dfeuer Ich würde mich sehr für Hinweise interessieren - mir fehlen schmerzliche Erfahrungen aus erster Hand in diesen Fällen.
Titou