Исключение времени выполнения при попытке печати символа Unicode
Char
- это тип символов Unicode в Haskell, а String
- просто [Char]
(т.е. список элементов Char
). Вот простой код:
main = putStrLn "©" -- Unicode string
Этот код компилируется отлично, но я получаю исключение во время выполнения, когда запускаю его в файле PowerShel.exe или cmd.exe:
app.exe:: commitBuffer: недопустимый аргумент (недопустимый символ)
Почему это происходит? Как ни странно, когда я делаю то же самое в С#, я не получаю исключения:
Console.WriteLine("©");
В .NET символы тоже Unicode. PowerShell или cmd печатает c
вместо ©
, но по крайней мере я получаю не исключение. Как я могу заставить исполняемый файл Haskell работать плавно?
Ответы
Ответ 1
Я думаю, что это должно считаться ошибкой в GHC, но есть обходной путь. Кодировка по умолчанию для всех дескрипторов в программе GHC (за исключением открытых в двоичном режиме) - это только кодировка, принятая консолью без обработки ошибок. К счастью, вы можете добавить обработку ошибок с чем-то вроде этого.
makeSafe h = do
ce' <- hGetEncoding h
case ce' of
Nothing -> return ()
Just ce -> mkTextEncoding ((takeWhile (/= '/') $ show ce) ++ "//TRANSLIT") >>=
hSetEncoding h
main = do
mapM_ makeSafe [stdout, stdin, stderr]
-- The rest of your main function.
Ответ 2
В Windows исправление заключается в том, чтобы сообщить оболочке использовать код страницы 65001 (инструкции здесь), который помещает Windows в режим "UTF-8". Это не идеально, но для большинства персонажей вы должны видеть, что символы Юникода обрабатываются намного лучше.