Исключение времени выполнения при попытке печати символа 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". Это не идеально, но для большинства персонажей вы должны видеть, что символы Юникода обрабатываются намного лучше.