【发布时间】:2014-02-03 05:04:41
【问题描述】:
我正在玩弄字符串,发现 Haskell(正确地)不允许高于 Unicode 代码点 0x10ffff 的字符(即,如果尝试使用超出此限制的内容,则会出现类似序列超出范围的错误)。出于好奇,我玩弄了 Unicode 代理一半(0xd800 到 0xdfff)——无效的 Unicode 代码点,并发现它们似乎是允许的。我很好奇为什么会这样。仅仅是因为作为有界项意味着只定义最大值和最小值吗?
【问题讨论】:
我正在玩弄字符串,发现 Haskell(正确地)不允许高于 Unicode 代码点 0x10ffff 的字符(即,如果尝试使用超出此限制的内容,则会出现类似序列超出范围的错误)。出于好奇,我玩弄了 Unicode 代理一半(0xd800 到 0xdfff)——无效的 Unicode 代码点,并发现它们似乎是允许的。我很好奇为什么会这样。仅仅是因为作为有界项意味着只定义最大值和最小值吗?
【问题讨论】:
禁止代理代码单元确实会使Char 成为更正确的Unicode 代码点类型。报告称 Char 是“其值代表 Unicode 字符的枚举”,因此这可能应该被视为 GHC 错误。
没有“有界项”的具体概念,但它需要在各个地方进行额外检查(例如,现在chr 只需要进行一次比较以检查其参数是否有效)并可能进行一些事情的表现更奇怪(如果人们间接期望代码点是连续的)。
不过,我不知道这样做有什么特别好的理由,或者最初甚至考虑过这种权衡。在 Haskell 1.4 中,Char 只是一个 16 位类型,因此很自然地将其扩展到 17*2^16 值而不添加额外检查。这个问题偶尔会被提出——我以前也提出过——但大多数人似乎并不十分担心。不过,提交一个关于它的 GHC 错误可能是合理的,以便进行适当的讨论。
请注意Data.Text(它使用 UTF-16 作为其内部表示)does disallow 是无效的代码单元(它必须这样做)。
【讨论】:
Bounded 和 Enum 都不要求它们的实例是连续的。
Bounded 而言,“连续”甚至没有确切的含义。只有当您转换为Ints 或从Ints 转换并在该表示中看到一个漏洞时,它才会出现。