Haskell源代码编码

8

《Haskell 2010语言报告》指出:

Haskell使用Unicode [2]字符集。然而,源程序目前偏向于早期版本Haskell所使用的ASCII字符集。

这是否意味着UTF-8?

在ghc-7.0.4/compiler/parser/Lexer.x.source中:

$unispace    = \x05 -- Trick Alex into handling Unicode. See alexGetChar.
$whitechar   = [\ \n\r\f\v $unispace]
$white_no_nl = $whitechar # \n
$tab         = \t

$ascdigit  = 0-9
$unidigit  = \x03 -- Trick Alex into handling Unicode. See alexGetChar.
$decdigit  = $ascdigit -- for now, should really be $digit (ToDo)
$digit     = [$ascdigit $unidigit]

$special   = [\(\)\,\;\[\]\`\{\}]
$ascsymbol = [\!\#\$\%\&\*\+\.\/\<\=\>\?\@\\\^\|\-\~]
$unisymbol = \x04 -- Trick Alex into handling Unicode. See alexGetChar.
$symbol    = [$ascsymbol $unisymbol] # [$special \_\:\"\']

$unilarge  = \x01 -- Trick Alex into handling Unicode. See alexGetChar.
$asclarge  = [A-Z]
$large     = [$asclarge $unilarge]

$unismall  = \x02 -- Trick Alex into handling Unicode. See alexGetChar.
$ascsmall  = [a-z]
$small     = [$ascsmall $unismall \_]

$unigraphic = \x06 -- Trick Alex into handling Unicode. See alexGetChar.
$graphic   = [$small $large $symbol $digit $special $unigraphic \:\"\']

我不确定如何处理这个问题。alexGetChar并没有提供太多帮助。

4个回答

7
Unicode是一个字符集。UTF-8、UTF-16等是Unicode代码点的具体物理编码方式。可以在这里阅读详细解释。here
引用报告部分仅说明Haskell源代码使用Unicode字符集,但并未说明应该使用哪种编码方式。换句话说,它只是说明了源代码中可能出现的字符,而并没有说明这些字符如何以纯字节的形式写入。

2
撰写任何类型的解析器都需要了解特定文件的编码方式。Unicode字符集有许多可接受的编码方式,包括UTF-8、UTF-16、UTF-32等。您的解析器应该能够处理所有这些编码方式。在实践中,由于您将字节转换为字符的过程局限于读取器函数中,所以这不是问题。 - Ray Toal
1
为了确定具体的编码,您可以使用字节顺序标记或使用一些启发式方法(至少UTF-8可以很容易地与UTF-16和UTF-32区分开来,并且UTF-16 BE可以与UTF-16 LE区分开来)。至少只要您知道大多数字符都在ASCII字符集中。 - Ivan Danilov

7

一份提议建议将UTF-8作为Haskell源文件的标准编码,但我不确定它是否已被接受。

实际上,GHC假设所有输入文件都是UTF-8编码,但它会忽略注释中的格式错误字节序列。


1
虽然 Haskell 标准仅表示 Unicode 是可能字符的集合(而不是例如 ASCII 或 Latin-1),但它并没有指定要使用哪种不同的编码方式(UTF8、UTF16、UTF32、字节顺序)。
Haskell 平台自带的词法分析器 Alex 要求其输入为 UTF8 编码 *,这就是你看到的所提到的代码的原因。实际上,我认为 Haskell 的所有主要实现都要求源代码采用 UTF8 编码。
* - 这实际上是一个真正的问题,因为 GHC 将字符串和更重要的 Data.Text 内部存储为 UTF16。 直接对其进行词法分析而不是来回转换将会很好。

0

数据类型(即您可以使用的“抽象”数据)与其表示形式(即它在计算机内存或磁盘上的存储方式)之间存在重要区别。

Haskell报告中有两件事与Unicode相关:

  1. Haskell中的Char数据类型表示Unicode字符(也称为代码点)。您应该将其视为提供某些接口的抽象数据类型(例如,您可以在其上调用isDigittoLower),但不允许您知道它在内部的确切表示方式。 Haskell的特定实现(例如GHC)可以自由地以任何希望的方式在内存中表示它,这完全无关紧要,因为您无法访问底层原始位。

  2. Haskell程序是文本,由(抽象)Unicode代码点组成,即基本上是一个String。然后它继续解释如何解析此String。再次强调,重要的是它根据抽象Unicode代码点序列定义了Haskell的语法。

现在,关于Haskell源代码的问题。 Haskell报告没有指定当Unicode文本存储在文件中时如何将其编码为零和一。

事实上,Haskell报告根本没有指定如何存储Haskell程序!它没有提到Haskell源代码存储在文件中,文件必须以模块命名,并且目录结构应遵循模块名称的结构 - 所有这些都被认为是编译器实现细节,而想法是这允许每个编译器在任何地方以任何方式存储Haskell程序:在文件中,在数据库表中,作为黑板上用粉笔写出的程序的jpeg照片。因此,它也没有指定编码(对于在黑板上书写的程序指定编码是没有意义的)。

然而,GHC,事实上的标准Haskell编译器,假定Haskell程序存储在以UTF-8编码的文件中,按层次结构组织,并以模块名称命名。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接