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

Haskell 尝试打印Unicode字符时出现运行时异常,haskell,ghc,Haskell,Ghc,Char是Haskell中Unicode字符的类型,String只是[Char](即Char项的列表)。下面是一些简单的代码: main = putStrLn "©" -- Unicode string 此代码编译良好,但在PowerShell.exe或cmd.exe中运行时出现运行时异常: app.exe::commitBuffer:无效参数(无效字符) 为什么会发生这种情况?奇怪的是,当我在C#中做同样的事情时,我也不例外: Console.WriteLine("©"); 在.NET中,

Char
是Haskell中Unicode字符的类型,
String
只是
[Char]
(即
Char
项的列表)。下面是一些简单的代码:

main = putStrLn "©" -- Unicode string
此代码编译良好,但在PowerShell.exe或cmd.exe中运行时出现运行时异常:

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

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

Console.WriteLine("©");

在.NET中,字符也是Unicode。PowerShell或cmd打印的是
c
而不是
,但至少我没有得到例外。如何让Haskell可执行文件顺利运行?

在Windows上,修复方法是告诉shell使用(),这将Windows置于“UTF-8模式”。这并不完美,但对于大多数字符,您应该会看到unicode字符处理得更好。

我认为这应该算作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.
makeSafe h=do

“ce”可能是Haskell要求该程序在unicode shell中运行。My cmd shell打印的
“©很好,但在
上出现相同的错误ഠഃ അ ഠൃ ൩"。可能有用:我不是PowerShell或C#专家,但事实上出现了一些字符替换(“C”而不是“))当您运行C#程序时,可能表明PowerShell没有设置为使用UTF-8…@chi,Unicode字符串在Mac OS X上打印得很好;我通过终端使用bash,终端设置为使用UTF-8。@Jubobs确实,在linux上,终端也设置为UTF-8,我从来没有遇到过问题。@Bush如果您只想避免异常,您可以使用
chcp65001
在终端中--所有非ascii字符都将无法读取。@Bush您是否使用设置了代码页?问题的另一半是“为什么GHC二进制文件会崩溃,而不是像.NET二进制文件那样优雅地返回到非Unicode输出?”?“GHC可以;理论上,我们应该能够进行编码转换并避免崩溃。我想知道是否有人调查过。谢谢。我现在也不例外,但我仍然没有达到我的预期。我有
?First Second,2014
输出,而不是
©First Second,2014
。它添加了“?”,因为您的控制台使用的编码没有“)”字符,但我以前从未见过它添加“”,我不知道那里发生了什么。您还可以将此答案与@bheklillr的答案结合起来,将控制台的编码更改为具有所需字符的内容(代码页65001使用与utf-8相同的方法来记录字符大小,但不幸的是,如果您不关心实际显示的字符,则只能将其称为utf-8)当我将代码加载到ghci并手动运行
main
功能时,
存在。如果我把代码编译成exe文件,我就没有“文本”。非常感谢。