尝试打印Unicode字符时出现运行时异常

And*_*man 17 haskell ghc

Char是Haskell中Unicode字符的类型,String简单来说[Char](即Char项目列表).这是一些简单的代码:

main = putStrLn "©" -- Unicode string
Run Code Online (Sandbox Code Playgroud)

这段代码编译得很好,但是当我在PowerShel.execmd.exe中运行它时,我得到了运行时异常:

app.exe :: commitBuffer:无效参数(无效字符)

为什么会这样?奇怪的是,当我在C#中做同样的事情时,我也不例外:

Console.WriteLine("©");
Run Code Online (Sandbox Code Playgroud)

在.NET中,字符也是Unicode.相反,PowerShellcmd打印,但至少我不会例外.如何让Haskell可执行文件顺利运行?c©

bhe*_*ilr 9

在Windows上,修复是告诉shell使用代码页65001(此处的说明),这将Windows置于"UTF-8模式".它并不完美,但对于大多数角色,你应该看到unicode角色处理得更好.

  • 问题的另一半是"为什么GHC二进制崩溃而不是优雅地回退到像.NET二进制文件那样的非Unicode输出?" GHC可以[找出系统区域](http://hackage.haskell.org/package/base-4.7.0.2/docs/GHC-IO-Encoding.html#v:getLocaleEncoding); 理论上我们应该能够进行编码转换并避免崩溃.我想知道是否有人调查过. (5认同)

Jer*_*ist 5

我认为这应该算作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.
Run Code Online (Sandbox Code Playgroud)