Haskell 如何按 Unicode 字素簇应用 tail 和 tails?
数据阿明
结论
可以按 Unicode 字素簇(Grapheme Cluster)处理文本。不过,String、Data.Text 和 Data.Text.Lazy 的 tail、tails 都不会自动按字素簇切分。要让 ⚠️ 保持完整,需要先用支持字素边界的实现将文本切成字素簇,再根据这些簇生成后缀。
⚠️ 由 U+26A0 和 U+FE0F 两个码点组成。常规字符串操作按各自的元素边界处理,因此 tails 会生成完整序列,也会生成只含 U+FE0F 的后缀。
先切分,再生成后缀
可以使用 text-icu 这类支持字素边界切分的库。切分函数和参数应根据项目使用的 text-icu 版本 API 确定,并确保切分结果是按字素簇得到的 Text 列表。然后拼接每个后缀:
import Data.List (tails)
import qualified Data.Text as T
-- graphemeClusters 需由支持 Unicode 字素边界的库实现。
tailsByGrapheme :: [T.Text] -> [T.Text]
tailsByGrapheme = map T.concat . tails
先调用 graphemeClusters input,再把结果传给 tailsByGrapheme。对于只含 ⚠️ 的输入,按字素簇切分后会得到一个簇;生成的后缀是完整的 ⚠️ 和空字符串,不会多出只含 variation selector 的后缀。
注意事项
Data.Text和Data.Text.Lazy使用不同的存储方式,但都不会自动按字素簇处理文本。换用它们无法解决按用户感知字符切分的问题。- 字素簇边界由 Unicode 文本分段规则定义。“一个码点”不等于“一个用户感知的字符”。
- 如果处理结果需要在不同环境中保持一致,应确认所用库的分段规则及其 Unicode 数据版本符合项目要求。
备注:内容仅供参考。
