Text oder Bytestring

78

Schönen Tag.

Das einzige, was ich jetzt an Haskell hasse, ist die Menge an Paketen für die Arbeit mit Strings.

Zuerst habe ich native Haskell- [Char]Strings verwendet, aber als ich versuchte, Hackage-Bibliotheken zu verwenden , ging ich in endlosen Konvertierungen völlig verloren. Jedes Paket scheint eine andere Zeichenfolgenimplementierung zu verwenden, einige übernehmen ihre eigene handgemachte Sache.

Als nächstes habe ich meinen Code mit Data.TextZeichenfolgen und OverloadedStringsErweiterungen umgeschrieben. Ich habe mich dafür entschieden, Textweil er einen größeren Funktionsumfang hat, aber es scheint, dass viele Projekte dies bevorzugen ByteString.
Jemand könnte kurz überlegen, warum man das eine oder andere benutzt?

PS: Übrigens, wie konvertiert man von Textnach ByteString?

Konnte nicht erwartet Typ entsprechen Data.ByteString.Lazy.Internal.ByteString gegen gefolgert Typ Text IO Data.ByteString.Lazy.Internal.ByteString Inferred Typ: IO Text Erwartete Typ

Ich habe versucht , encodeUtf8aus Data.Text.Encoding, aber kein Glück:

Der erwartete Typ Data.ByteString.Lazy.Internal.ByteString konnte nicht mit dem abgeleiteten Typ Data.ByteString.Internal.ByteString verglichen werden

UPD:

Vielen Dank für die Antworten, dass * Chunks Güte wie ein langer Weg aussieht, aber ich war etwas schockiert über das Ergebnis, meine ursprüngliche Funktion sah folgendermaßen aus:

htmlToItems :: Text -> [Item]
htmlToItems =
    getItems . parseTags . convertFuzzy Discard "CP1251" "UTF8"

Und jetzt wurde:

htmlToItems :: Text -> [Item]
htmlToItems =
    getItems . parseTags . fromLazyBS . convertFuzzy Discard "CP1251" "UTF8" . toLazyBS
    where
      toLazyBS t = fromChunks [encodeUtf8 t]
      fromLazyBS t = decodeUtf8 $ intercalate "" $ toChunks t

Und ja, diese Funktion funktioniert nicht, weil sie falsch ist. Wenn wir sie bereitstellen Text, sind wir zuversichtlich, dass dieser Text ordnungsgemäß codiert und einsatzbereit ist. Die Konvertierung ist dumm, aber eine solch ausführliche Konvertierung muss noch durchgeführt werden irgendwo draußen platzieren htmltoItems.

Dfr
quelle
41
Haskell Leute, bitte haben Sie eine einheitliche Zeichenfolge :)
Ankur
8
@Ankur: Textwird zur De-facto- Textimplementierung . String gibt es aus alten Gründen und aus einfachen Gründen immer noch, aber für ernsthafte Textmanipulationen sollten Sie Text verwenden.
ivanm
2
@ivanm: Wenn nur all diese alten bytestring-basierten Bibliotheken konvertieren würden!
John L
1
@ivanm In Wirklichkeit kommt es vor, dass Text nicht verwendbar ist. Ich verwende jetzt nur wenige Bibliotheken (Database.MongoDB, Text.Iconv) und keiner von ihnen respektiert Text, und all diese Konvertierungen von Hand durchzuführen, fühlt sich nicht vernünftig an.
Dfr
2
Wie und woher bekommen Sie den Text ursprünglich? Der Grund, warum Sie auf Probleme stoßen, ist, dass Sie niemals Text zwischen verschiedenen Codierungen konvertieren müssen. Sie sollten die Textdaten zuerst mit der richtigen Codierung dekodieren und dann einfach verwendenhtmlToItems = getItems . parseTags
shang

Antworten:

68

ByteStringssind hauptsächlich für Binärdaten nützlich, bieten aber auch eine effiziente Möglichkeit, Text zu verarbeiten, wenn Sie lediglich den ASCII-Zeichensatz benötigen. Wenn Sie Unicode-Zeichenfolgen verarbeiten müssen, müssen Sie verwenden Text. Ich muss jedoch betonen, dass keines der beiden ein Ersatz für das andere ist und im Allgemeinen für verschiedene Zwecke verwendet wird: Während es sich Textum reinen Unicode handelt, müssen Sie immer noch zu und von einer binären ByteStringDarstellung codieren, wenn Sie z. B. Text über einen Socket oder eine Datei transportieren .

Hier ist ein guter Artikel über die Grundlagen von Unicode, der die Beziehung zwischen Unicode-Codepunkten ( Text) und den codierten Binärbytes ( ByteString) anständig erklärt : Das absolute Minimum, das jeder Softwareentwickler unbedingt und positiv über Unicode und Zeichen wissen muss Sets

Sie können das Data.Text.Encoding- Modul verwenden, um zwischen den beiden Datentypen zu konvertieren, oder Data.Text.Lazy.Encoding, wenn Sie die Lazy-Varianten verwenden (wie Sie es anscheinend aufgrund Ihrer Fehlermeldungen tun).

shang
quelle
Hier ist die andere Seite getroffen, weil alle meine Zeichenfolgen bereits streng sind: Konnte nicht mit dem erwarteten Typ übereinstimmen. Text against inferred type Data.Text.Lazy.Internal.TextAlso fand ich fromChunks for Text, ok, aber das Endergebnis noch hässlich.
Dfr
5
Bitte verwenden Sie keine Bytestrings für "Text" -Daten, auch wenn Sie nur ASCII benötigen. Verwenden Sie Text für Textdaten und ByteString für gepackte Datenstrukturen. Wenn wir uns alle einig sind, welche Typen semantisch dargestellt werden sollen , werden wir viel weniger Verwirrung darüber haben, welcher Typ verwendet werden soll, und letztendlich weniger Konvertierungen zwischen Typen.
Nomen
1
"Sie müssen immer noch zu und von einer binären ByteString-Darstellung codieren, wenn Sie z. B. Text über einen Socket oder eine Datei transportieren." Das textPaket bietet tatsächlich Funktionen, um bereits mit Dateien zu arbeiten.
1
Ja, das Data.Text.IOModul verfügt über Funktionen zum Arbeiten mit Dateien, die jedoch fast nie Ihren Wünschen entsprechen. Sie werden intern Textvon der ByteStringVerwendung des Standardzeichensatzes Ihres Systemgebietsschemas dekodiert . Wenn die Datei zufällig eine andere Codierung aufweist, führt dies zu einem Laufzeitfehler oder einem Mülltext. Das explizite Codieren und Decodieren ist fast immer die richtige Option.
shang
26

Sie möchten auf jeden Fall Data.Text für Textdaten verwenden.

encodeUtf8ist der Weg zu gehen. Dieser Fehler:

Der erwartete Typ Data.ByteString.Lazy.Internal.ByteString konnte nicht mit dem abgeleiteten Typ Data.ByteString.Internal.ByteString verglichen werden

bedeutet, dass Sie dem Code einen strengen Bytestring bereitstellen, der einen faulen Bytestring erwartet . Die Konvertierung ist mit der fromChunksFunktion einfach :

Data.ByteString.Lazy.fromChunks :: [Data.ByteString.Internal.ByteString] -> ByteString

Alles, was Sie tun müssen, ist, die Funktion fromChunks [myStrictByteString]dort hinzuzufügen, wo der faule Bytestring erwartet wird.

Die Konvertierung in die andere Richtung kann mit der Doppelfunktion durchgeführt werden toChunks, die einen verzögerten Testtest durchführt und eine Liste strenger Blöcke enthält.

Möglicherweise möchten Sie die Betreuer einiger Pakete fragen, ob sie eine Textschnittstelle anstelle oder zusätzlich zu einer Bytestring-Schnittstelle bereitstellen können.

John L.
quelle
5

Verwenden Sie eine einzelne Funktion csaus dem Data.String.Conversions.

Es ermöglicht Ihnen , zwischen zu konvertieren String, ByteStringund Text(wie auch ByteString.Lazyund Text.Lazy), in Abhängigkeit von der Eingabe und der erwarteten Typen.

Sie müssen es immer noch anrufen, müssen sich aber nicht mehr um die jeweiligen Typen kümmern.

In dieser Antwort finden Sie ein Verwendungsbeispiel.

Titou
quelle