Console de E / S de Unicode no Haskell no Windows

Parece bastante difícil obter o I / O do console para trabalhar com caracteres Unicode no Haskell em Windows. Aqui está o conto da desgraça:

(Preliminar.) Antes mesmo de considerar a realização de E / S em Unicode no console no Windows, é necessário verificar se você está usando uma fonte do console que pode renderizar os caracteres desejados. As fontes de varredura (o padrão) têm uma cobertura infinitamente fraca (e não permitem a cópia de caracteres que não podem representar), e as opções de truetype fornecidas pela MS (consolas, console lucida) não têm uma cobertura excelente (embora isso permita copiar / colar de caracteres que eles não podem representar). Você pode considerar a instalação do DejaVu Sans Mono (siga as instruções na parte inferiorAqui; você pode ter que reiniciar antes de funcionar). Até que isso seja classificado, nenhum aplicativo poderá fazer muita E / S de Unicode; não apenas Haskell.Tendo feito isso, você notará que alguns aplicativos poderão fazer E / S de console nas janelas. Mas fazê-lo funcionar é bem complicado. Existem basicamente duas maneiras de escrever no console no Windows. (O que se segue é verdadeiro para qualquer idioma, não apenas Haskell; não se preocupe, Haskell vai entrar na foto daqui a pouco!) ...A opção A é usar as funções usuais de E / S baseadas em bytes da biblioteca C; a esperança é que o sistema operacional interprete esses bytes de acordo com alguma codificação que possa codificar todos os caracteres estranhos e maravilhosos que você deseja. Por exemplo, usando a técnica equivalente no Mac OS X, onde a codificação padrão do sistema é geralmente UTF8, isso funciona muito bem; você manda saída utf8, você vê belos símbolos.No Windows, funciona menos bem. A codificação padrão que o Windows espera geralmente não será uma codificação cobrindo todos os símbolos Unicode. Então, se você quiser ver símbolos bonitos dessa maneira, de um jeito ou de outro, você precisamudança a codificação. Uma possibilidade seria o seu programa usar oSetConsoleCP comando win32. (Então, você precisa se ligar à biblioteca Win32.) Ou, se preferir não fazer isso, você pode esperar que o usuário do seu programa altere a página de código para você (eles teriam que chamar ochcp comando antes de executar o programa).A opção B é usar os comandos da API do console win32 compatíveis com Unicode, comoWriteConsoleW. Aqui você envia UTF16 direto para o Windows, o que o torna feliz: não há perigo de uma incompatibilidade de codificação porque o Windowssempre espera o UTF16 com essas funções.

Infelizmente, nenhuma dessas opções funciona muito bem com o Haskell. Primeiro, não há bibliotecas que eu saiba que usam a Opção B, então isso não é muito fácil. Isso deixa a opção A. Se você usa a biblioteca de E / S do Haskell (putStrLn e assim por diante), isso é o que a biblioteca fará. Nas versões modernas do Haskell, ele perguntará cuidadosamente ao Windows qual é a página de código atual e exibirá suas strings na codificação correta. Há dois problemas com esta abordagem:

Um não é um showstopper, mas é chato. Como mencionado acima, a codificação padrão quase nunca codifica os caracteres que você deseja: você é o usuário que precisa mudar para uma codificação que o faça. Assim, seu usuário precisachcp cp65001 antes de executar seu programa (você pode achar desagradável forçar seus usuários a fazer isso). Ou você precisa se ligarSetConsoleCP e fazer o equivalente dentro do seu programa (e depois usarhSetEncoding para que as bibliotecas Haskell enviem a saída usando a nova codificação), o que significa que você precisa envolver a parte relevante das bibliotecas do win32 para torná-las visíveis para Haskell.Muito mais a sério, existe umbug no windows (resolução: não corrige) o que leva a umbug em Haskell o que significa que, se você selecionou qualquer página de código como cp65001, que pode abranger todo o Unicode, as rotinas de E / S do Haskell não funcionarão e falharão. Então, essencialmente,mesmo se você (ou seu usuário) definiu a codificação adequadamente para alguma codificação que cobre todos os maravilhosos caracteres Unicode e, em seguida, "faça tudo certo" ao dizer a Haskell para produzir as coisas usando essa codificação, você ainda perde.

O bug listado acima ainda não foi resolvido e listado como baixa prioridade; A conclusão básica é que a Opção A (na minha classificação acima) é impraticável e é preciso mudar para a Opção B para obter resultados confiáveis. Não está claro qual será o prazo para que isso seja resolvido, já que parece um trabalho considerável.

A questão é:Enquanto isso, alguém pode sugerir uma solução alternativa para permitir o uso de E / S de console Unicode no Haskell no Windows.

Veja também esteentrada do banco de dados do rastreador de bugs python, lutando com o mesmo problema no Python 3 (correção proposta, mas ainda não aceito no codebase), eesta resposta stackoverflow, dando uma solução para este problema no Python (baseado na 'opção B' na minha classificação).

questionAnswers(1)

yourAnswerToTheQuestion