Unicode-Konsolen-E / A in Haskell unter Windows

Es scheint ziemlich schwierig zu sein, Konsolen-E / A für die Arbeit mit Unicode-Zeichen in Haskell unter Windows zu bekommen. Hier ist die Geschichte vom Weh:

(Vorläufig.) Bevor Sie überhaupt in Betracht ziehen, Unicode-E / A in der Konsole unter Windows auszuführen, müssen Sie sicherstellen, dass Sie eine Konsolenschrift verwenden, die die gewünschten Zeichen rendern kann. Die Raster-Schriftarten (die Standardeinstellung) haben eine unendlich schlechte Abdeckung (und erlauben kein Kopieren von Zeichen, die sie nicht darstellen können), und die von MS bereitgestellten TrueType-Optionen (Konsolen, Lucida-Konsole) haben keine sehr gute Abdeckung (obwohl diese dies ermöglichen werden) Kopieren / Einfügen von Zeichen, die sie nicht darstellen können). Sie können DejaVu Sans Mono installieren (folgen Sie den Anweisungen unten)Hier; Sie müssen möglicherweise neu starten, bevor es funktioniert). Solange dies nicht sortiert ist, können keine Apps viele Unicode-E / A-Vorgänge ausführen. nicht nur Haskell.Wenn Sie dies getan haben, werden Sie feststellen, dass einige Apps Konsolen-E / A unter Windows ausführen können. Aber es zum Laufen zu bringen, bleibt ziemlich kompliziert. Grundsätzlich gibt es zwei Möglichkeiten, unter Windows auf die Konsole zu schreiben. (Das Folgende gilt für jede Sprache, nicht nur für Haskell. Keine Sorge, Haskell wird gleich ins Bild kommen!) ...Option A besteht darin, die üblichen byte-basierten E / A-Funktionen im C-Library-Stil zu verwenden. Die Hoffnung ist, dass das Betriebssystem diese Bytes gemäß einer Codierung interpretiert, die alle seltsamen und wunderbaren Zeichen codieren kann, die Sie möchten. Unter Mac OS X, wo die Standard-Systemcodierung normalerweise UTF8 ist, funktioniert dies beispielsweise hervorragend. Wenn Sie eine utf8-Ausgabe senden, sehen Sie hübsche Symbole.Unter Windows funktioniert es weniger gut. Die von Windows erwartete Standardcodierung ist im Allgemeinen keine Codierung, die alle Unicode-Symbole abdeckt. Wenn Sie also auf diese oder jene Weise hübsche Symbole sehen möchten, müssen Sie dies tunVeränderung die Kodierung. Eine Möglichkeit wäre für Ihr Programm, die zu verwendenSetConsoleCP Befehl win32. (Dann müssen Sie sich an die Win32-Bibliothek binden.) Wenn Sie dies nicht möchten, können Sie erwarten, dass der Benutzer Ihres Programms die Codepage für Sie ändertchcp Befehl, bevor sie Ihr Programm ausführen).Option B ist die Verwendung der Unicode-fähigen Win32-Konsolen-API-Befehle wieWriteConsoleW. Hier senden Sie UTF16 direkt an Windows, was die Darstellung erleichtert: Es besteht keine Gefahr einer Kodierungsinkongruenz, da Windowsimmer erwartet mit diesen Funktionen UTF16.

Leider funktioniert keine dieser Optionen von Haskell aus sehr gut. Erstens gibt es keine Bibliotheken, von denen ich weiß, dass sie Option B verwenden. Das ist also nicht sehr einfach. Dadurch bleibt Option A erhalten. Wenn Sie die E / A-Bibliothek von Haskell verwenden (putStrLn und so weiter), so wird die Bibliothek vorgehen. In modernen Versionen von Haskell werden Fenster sorgfältig nach der aktuellen Codepage gefragt und die Zeichenfolgen in der richtigen Codierung ausgegeben. Bei diesem Ansatz gibt es zwei Probleme:

Man ist kein Showstopper, aber nervig. Wie oben erwähnt, codiert die Standardcodierung so gut wie nie die gewünschten Zeichen: Sie müssen als Benutzer zu einer Codierung wechseln, die dies tut. Also muss Ihr Benutzerchcp cp65001 bevor sie Ihr Programm ausführen (es kann Ihnen unangenehm sein, Ihre Benutzer dazu zu zwingen). Oder du musst dich binden anSetConsoleCP und mache das Äquivalent in deinem Programm (und benutze dannhSetEncoding Damit die Haskell-Bibliotheken die Ausgabe mit der neuen Codierung senden. Dies bedeutet, dass Sie den relevanten Teil der win32-Bibliotheken umbrechen müssen, um sie für Haskell sichtbar zu machen.Viel ernster gibt es eineFehler in Windows (Auflösung: wird nicht behoben), was zu a führtFehler in Haskell Dies bedeutet, dass, wenn Sie eine Codepage wie cp65001 ausgewählt haben, die den gesamten Unicode-Code abdeckt, die E / A-Routinen von Haskell fehlerhaft funktionieren und fehlschlagen. Also im Wesentlichenselbst wenn Sie (oder Ihr Benutzer) haben die Codierung korrekt auf eine Codierung eingestellt, die alle wunderbaren Unicode-Zeichen abdeckt, und dann haben Sie Haskell angewiesen, die Codierung für die Ausgabe zu verwenden.

Der oben aufgeführte Fehler ist immer noch ungelöst und wird als niedrig eingestuft. Die grundlegende Schlussfolgerung ist, dass Option A (in meiner obigen Klassifizierung) nicht durchführbar ist und man zu Option B wechseln muss, um verlässliche Ergebnisse zu erhalten. Es ist nicht klar, in welchem ​​Zeitrahmen dies gelöst werden soll, da dies nach erheblicher Arbeit aussieht.

Die Frage ist:Kann in der Zwischenzeit jemand eine Problemumgehung vorschlagen, um die Verwendung von Unicode-Konsolen-E / A in Haskell unter Windows zu ermöglichen?

Siehe auch dasPython-Bug-Tracker-Datenbankeintrag, Auseinandersetzung mit dem gleichen Problem in Python 3 (Fix vorgeschlagen, aber noch nicht in die Codebasis aufgenommen), undDiese Stackoverflow-AntwortGeben Sie eine Problemumgehung für dieses Problem in Python (basierend auf "Option B" in meiner Klassifizierung).

Antworten auf die Frage(1)

Ihre Antwort auf die Frage