И компилятор и интрепретатор требуют, чтобы сторки в коде программы
были в utf8.
Например, код вида (в кодировке win-1251 или dos-866):
main = putStrLn "Привет мир!"
(ну или любой другой код, где есть кириллические строковые литералы)
вызывает ошибку:
Hello.hs:1:17:
lexical error in string/character literal (UTF-8 decoding error)
Понятное дело, что если код записать в utf8, то программа работает,
однако возникает проблема с отображением в виндовой консоли (где стоит
по умолчанию кодировка 866), ну или с родными для Windows текстовыми
файлами с кодировкой 1251.
Мне кажется, что в более ранних сборках GHC такого не было.
Что делать? Есть ли нормальный способ работь с локальными (не utf8)
кодировками: задавать их в программе в строковых литералах,
конвертировать и т.п.?
Проблема обостряется тем, что ни одного указанного в документации
пакета для работы с utf8 не установлено в GHC 6.10.3:
Codec.Binary.UTF8.Generic
Codec.Binary.UTF8.String
Data.ByteString.Lazy.UTF8
Data.ByteString.UTF8
System.IO.UTF8
(все имеет отношение к utf8-string-0.3.4)
planet.haskell.org читаешь? ;-)
2009/8/6 nsk.coder <nsk....@gmail.com>:
--
Best wishes,
Y
И компилятор и интрепретатор требуют, чтобы сторки в коде программы
были в utf8.
Например, код вида (в кодировке win-1251 или dos-866):
У меня (на работе) Windows XP.
2009/8/6 nsk.coder <nsk....@gmail.com>:
1. в будущем GHC 6.12 ее устранят
2. сейчас надо использовать пакет utf8-string
про который я как раз и сказал -- что в сборке 6.10.3 его нет!!
:-(
Yakov ZAYTSEV:
Т.е., если у меня под Linux локаль будет koi-8, то проблемы с GHC
6.10.3 не будет?? Что-то я не верю...
Однако, perl например, распознает и автоматически (можно и
принудительно) любую локаль . Да много разных механизмов "борьбы" уже
в разных платформах и языках придумали с этим злом, я просто не ожидал
что тут появятся проблемы...
Iliya Kuznetsov:
В данный момент, для указанной версии GHC (6.10.3) -- дела с
кодировками находятся в очевидном ауте, и способа как-то нормально
работать без танца с бубном -- нет.
Так, даже
import System.IO.UTF8 (readFile, writeFile)
мы сделать не можем за отутствием нужн библиотек, хотя вроде как они
должны быть там (наверно, поставить их несложно, однако, я не
попробовал)
Все остальное -- уже следствия . Хотя я не считаю, что программист
должен напрягаться и делать сам "костыли".
Платформа (и, возможно, язык) должна предоставлять механизмы работы с
разными кодировками и локалями. Это делает и perl, и Qt, и насколько я
представляю -- Java.
Меня очень напрягло требование оформлять строковые литералы в теле
программы только в UTF-8 (а почему тогда не в двубайтном Юникоде?).
Конечно, это можно обойти, но зачем такие сложности? Неужели нельзя
предоставить программисту самому определять кодировку в исходниках
(как например, это делается в указанных выше платформах типа Qt) в
проблемных случаях?
А примеры в приведенном блоге -- вообще юмор, не работает нигде -- ни
под Windows (с их проблемной консолью), ни под юниксовой UTF-8
консолью -- как у Вас и показано.
Надеюсь, исправят. А щас -- грустно.
Iliya Kuznetsov:
> Добрый день, nsk.coder,отвечаю сразу на два твоих письма. В 6.12 устранят
13 августа 2009 г. 20:53 пользователь Iliya Kuznetsov
(iliya.k...@gmail.com) написал:
Пара замечаний:
- BOM -- это козни микрософта, лучше без него;
14 августа 2009 г. 9:16 пользователь Iliya Kuznetsov
(iliya.k...@gmail.com) написал:
0. Задача: как побороть utf-зло в Haskell под windows-консолью (т.е.
как вернуться назад к ASCII или OEM однобайтовым кодировкам в вводе и
выводе и в строковых литералах).
1. Поставил для начала utf8-string (System.IO.UTF8 и т.п.).
Разумеется, под виндой это решения не дало.
2. Хаскелловская обертка над iconv (одноименный package)
устанавливаться не захотела -- хотя CYGWIN есть и все необходимые
библиотеки были установлены. Да и толку похоже от нее тоже было бы
мало -- так как на выходе-входе пришлось бы вручную сражаться с тойже
utf
3. попробовал как-то победить необходимость UTF-8 в строковых
литералах. Для GHC есть флаг -XOverloadedStrings который позволят
менять стандартные строковые литералы на свои. Своих у меня не
было :-), решил использовать Data.ByteString.Char8, однако, это
решения не дало.
Пишем в кодировке CP1251 текст:
import qualified Data.ByteString.Char8 as B
main = B.putStrLn "Привет мир!"
запускаем:
runghc -XOverloadedStrings test.hs
Опять таже ошибка: lexical error in string/character literal (UTF-8
decoding error)
Т.е. это зло пока победить не получилось :-(
Ладно, хотя бы ввод-вывод допилить!!
4. Для этого решил устанавливать package encoding 0.5.2 (щас уже есть
0.6) -- он умеет узнавать кодировку системы (оси??) и прозрачно менять
print, getContents, hPutStr, hPutStrLn, hGetContents, readFile,
writeFile и т.п.) -- это кроме тех же самых перекодировок туда-сюда,
что умеет делать iconv.
Пакет долго компилировался, но установился, однако, как раз под
Windows он не умеет узнавать "кодировку системы по умолчанию"!! Я
пытался разобраться с неявными параметрами (Implicit parameters)
типа :enc и внутренностями пакета encoding. Правда, ума не хватило...
Я написал автору пакета и он дал советы... В общем, заработало. Только
пакет пока(?) не поддерживает CP866 (консольную кодировку виндов в
России по умолчанию). Пришлось для эксперимента менять консольную
кодировку и шрифт консоли с растрового на ТруТайпный, после этого
такая вот прога заработала:
-----------------------------------------------
{-# LANGUAGE ImplicitParams #-}
import Prelude hiding (print)
import System.IO (stdout)
import System.IO.Encoding
import Data.Encoding.CP1251
s = "Русский язык"
main = do
let ?enc = CP1251
hPutStrLn (stdout) s
-----------------------------------------------
Ну вот вроде пока все.
{-# LANGUAGE ImplicitParams #-}
-- текст скрипта в кодировке UTF-8
import Prelude hiding (print)
import System.IO (stdout)
import System.IO.Encoding
import Data.Encoding.CP866
s = "Русский язык"
main = do
let ?enc = CP866
hPutStrLn (stdout) s
(Меня, правда, сильно удивил размер exe-файла в 9 мегабайт)
Автору пакета послал предложение включить поддержку в будущие версии
encoding'а.
Вот теперь бы кто обяснил, как исхитрится сделать не UTF-ные, т.е.
однобайтные строковые литералы.
Кому надо, попробую выложить здесь патченный исходник пакета с
поддержкой CP866
Однако, проблему с кривой реализацией кодировок в Haskell это не
решает, только что проверил.
Без импорта библиотек
import Prelude hiding (writeFile, readFile, print, putStrLn)
import System.IO.UTF8
не работает совсем, с ними -- работает ужасно и криво.
Так, скрипт
import Prelude hiding (print)
import System.IO.UTF8
main = print "Привет мир!"
выдает:
"\1055\1088\1080\1074\1077\1090 \1084\1080\1088!"
Скрипт
import Prelude hiding (putStrLn)
import System.IO.UTF8
main = putStrLn "Привет мир!"
выдает еще смешнее:
runghc Hello2.hs
Привет мир!
мир!
!
Пока, реальным и корректным решение проблемы с Haskell является лишь
использование пакета encoding (см. выше), и кстати, вышло обновление,
учитывающие посланные автору пожелания и все (вроде) русские кодировки
2009/10/13 nsk.coder <nsk....@gmail.com>: