Кажется довольно сложно получить консольный ввод/вывод для работы с символами Unicode в Haskell под окнами. Вот сказка о горе:
- (Предварительно). Прежде чем рассматривать возможность ввода Unicode ввода/вывода в консоли под окнами, вы должны убедиться, что используете консольный шрифт, который может отображать нужные вам символы. Растровые шрифты (по умолчанию) имеют бесконечно низкое покрытие (и не позволяют копировать вставку символов, которые они не могут представлять), а варианты передачи TrueType MS (consolas, консоль lucida) не имеют большого охвата (хотя это позволит копирование/вставка символов, которые они не могут представлять). Возможно, вы захотите установить DejaVu Sans Mono (следуйте инструкциям внизу здесь, вам, возможно, придется перезагрузиться, прежде чем это сработает). Пока это не будет отсортировано, никакие приложения не смогут делать много Unicode I/O; а не только Haskell.
- Сделав это, вы заметите, что некоторые приложения смогут выполнять консольные операции ввода-вывода под окнами. Но заставить его работать остается довольно сложным. Существует два способа записи на консоль под окнами. (Что следует за любым языком, а не только с Haskell, не волнуйтесь, Haskell немного войдет в изображение!)...
- Вариант A - использовать обычные функции ввода-вывода на основе байтов в библиотеке c-library; надежда состоит в том, что ОС будет интерпретировать эти байты в соответствии с некоторой кодировкой, которая может кодировать все странные и замечательные персонажи, которые вы хотите. Например, используя эквивалентную технику в Mac OS X, где стандартная системная кодировка обычно UTF8, это отлично работает; вы отправляете выход utf8, вы видите симпатичные символы.
- В окнах это работает не так хорошо. Кодировка по умолчанию, которую ожидают окна, обычно не будет кодировкой, охватывающей все символы Юникода. Поэтому, если вы хотите увидеть симпатичные символы таким образом, так или иначе, вам нужно изменить кодировку. Одна из возможностей программы - использовать команду
SetConsoleCP
win32. (Итак, вам нужно привязать к библиотеке Win32.) Или, если вы этого не сделаете, вы можете ожидать, что пользователь вашей программы изменит вам кодовую страницу (тогда они должны были бы вызвать командуchcp
до они запускают вашу программу). - Вариант B - использовать команды API консоли Win32, поддерживающие Unicode, такие как
WriteConsoleW
. Здесь вы отправляете UTF16 прямо в окна, что делает его счастливым: нет опасности несоответствия кодировки, потому что окна всегда ожидают UTF16 с этими функциями.
К сожалению, ни один из этих вариантов не очень хорошо работает с Haskell. Во-первых, нет библиотек, которые, как я знаю, используют вариант B, так что это не очень просто. Это оставляет опцию A. Если вы используете библиотеку ввода/вывода Haskell (putStrLn
и т.д.), Это то, что сделает библиотека. В современных версиях Haskell он будет внимательно просить окна, какова текущая кодовая страница, и выводит ваши строки в правильной кодировке. С этим подходом существуют две проблемы:
- Один из них не демонстратор, но раздражает. Как уже упоминалось выше, кодировка по умолчанию почти никогда не кодирует нужные символы: пользователю необходимо изменить кодировку. Таким образом, ваш пользователь должен
chcp cp65001
перед запуском вашей программы (вам может показаться отвратительным заставить ваших пользователей сделать это). Или вам нужно привязать кSetConsoleCP
и выполнить эквивалент внутри вашей программы (а затем использоватьhSetEncoding
, чтобы библиотеки Haskell отправляли выходные данные с использованием новой кодировки), что означает, что вам нужно обернуть соответствующую часть библиотек win32 чтобы сделать их видимыми Haskell. - Гораздо серьезнее, есть ошибка в окнах (разрешение: не будет исправлено), что приводит к ошибка в Haskell, что означает, что если вы выбрали любую кодовую страницу, такую как cp65001, которая может охватывать все Unicode, процедуры ввода/вывода Haskell будут работать неправильно и сбой. Таким образом, даже если вы (или ваш пользователь) правильно установите кодировку на некоторую кодировку, которая охватывает все замечательные символы Юникода, а затем "сделайте все в порядке", говоря Haskell, чтобы выводить данные с использованием этой кодировки, вы все равно теряете.
Ошибка, указанная выше, все еще не решена и указана как низкий приоритет; основной вывод заключается в том, что Вариант A (в моей классификации выше) неработоспособный, и нужно переключиться на вариант B, чтобы получить надежные результаты. Неясно, какими будут сроки для этого решения, поскольку это выглядит как значительная работа.
Вопрос: тем временем, может ли кто-нибудь предложить обходной путь, позволяющий использовать консоли ввода-вывода Unicode в Haskell под окнами.
См. также запись базы данных об ошибках python, схватив ту же проблему в Python 3 (исправление предлагается, но еще не принято в codebase) и qaru.site/info/11792/..., дающий обходной путь для этой проблемы в Python (на основе "опции B" в моей классификации).