【问题标题】:Haskell: quoteFile fails on text file with "invalid byte sequence" on unicode charactersHaskell:quoteFile 在 unicode 字符上带有“无效字节序列”的文本文件上失败
【发布时间】:2026-02-05 14:40:01
【问题描述】:

我在虚拟环境中遇到了quoteFile 的问题(安装了 GHC 7.8.4 的 Debian Wheezy)。我已经从Text.Shakespeare.Text 描述了st quasi quoter 的面向文件的版本:

import Language.Haskell.TH.Quote    (QuasiQuoter, quoteFile)
import Text.Shakespeare.Text        (st)

sfFile :: QuasiQuoter
stFile = quoteFile st

这在我的主机上运行良好,但是在我的虚拟环境(Docker 映像)上失败并出现以下错误:

尝试运行编译时代码时出现异常: test-file.md: hGetContents: 无效参数(无效字节序列)

代码:Language.Haskell.TH.Quote.quoteExp stFile "test-file.md"

我对 REPL 的调查显示,文本文件中的第一个 unicode 字符发生错误,在我目前的情况下,这是 '«' 左指针双角引号:

import System.IO (IOMode(..), hGetContents, openFile, openBinaryFile, utf8)

main =
  do h <- openBinaryFile "test-file.md" ReadMode
     hGetContentContents h
     -- Binary read works fine out-of-box.

     h' <- openFile "test-file.md" ReadMode
     hSetEncoding h' utf8
     hGetContentContents h'
     -- This works only if encoding is explicitly set, otherwise 
     -- it gives "invalid byte sequence" error at run-time

在我看来,我需要配置一点我的虚拟环境,或者可能重建 GHC 本身。

我尝试将语言环境设置为en.UTF-8 UTF-8,但没有帮助(最初我根本没有进行语言环境配置)。

更新:目标文件有UTF-8编码:

$ file -bi test-file.md
text/x-c++; charset=utf-8

【问题讨论】:

  • @Arnon 问题是我无法访问stFile 引用者的句柄,因为读取操作是内部的。也许有一种方法可以为所有句柄设置默认编码?
  • 据我所知,没有在整个操作系统的环境中设置它,你声称你已经尝试过了.....
  • @Arnon 我已经从那个环境中的源代码构建了 GHC,所以也许我现在需要用新的语言环境重建 GHC?
  • 我认为这不会有很大的不同

标签: linux haskell unicode encoding utf-8


【解决方案1】:

最后,我发现我的虚拟语言环境设置不正确,例如locale 命令显示所有LANG 变量都设置为POSIX

LANG 变量导出到命令是最快的解决方法(bash 示例):

export LANG=en_US.UTF8 cabal build

但是,您可能需要安装 en_US 语言环境,Debian 手动配置是:

  1. 编辑文件/etc/locale.gen,添加新行en_US.UTF-8 UTF-8
  2. 调用locale-gen 生成语言环境。
  3. 导出LANG变量。

Debian 语言环境维基1

附:我的默认 Debian Wheezy 安装在默认语言环境列表中有 C.UTF-8,所以我相信出于极简主义的目的,是否可以使用它而不是安装额外的英语语言环境,但我没有自己测试它。

【讨论】:

    最近更新 更多