是否可以在Haskell(GHC)中使用国家字符对字符串进行正确排序?换句话说,按当前区域设置正确整理Chars?
我确实只找到了ICU模块,但它需要安装额外的库,因为它不是linux发行版的标准部分。我想基于POSIX的C(glibc like)库解决方案,因此处理额外的依赖关系不会有任何麻烦。
答案 0 :(得分:13)
推荐方式:text-icu
如您所见,以区域设置敏感方式强健处理字符串的推荐方法是通过 text 和 text-icu 。 text库在标准库集Haskell Platform中提供。
一个例子,排序土耳其语字符串:
{-# LANGUAGE OverloadedStrings #-}
import Data.Text.IO as T
import Data.Text.ICU as T
import Data.List (sortBy)
main = do
let trLocale = T.Locale "tr-TR"
str = "ÇIİĞÖŞÜ"
strs = take 10 (cycle $ T.toLower trLocale str : str : [])
mapM_ T.putStrLn (sortBy (T.compare [T.FoldCaseExcludeSpecialI]) strs)
在正确缩小土耳其语字符串后,似乎根据区域设置按lexicographic ordering正确排序:
*Main> main
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
çıiğöşü
çıiğöşü
çıiğöşü
çıiğöşü
çıiğöşü
未使用text-icu软件包
您已在问题中询问避免使用其他库的解决方案,而不是Posix提供的解决方案。虽然text-icu可以从Hackage(cabal install text-icu
)轻松安装,但它确实依赖于ICU C库,而这在任何地方都不可用。此外,没有Posix替代方案具有强大或全面性。最后,text-icu
是唯一正确对多字符字符进行转换的包。
鉴于此,Haskell中内置的Char和String类型提供Data.Char,其值表示Unicode,并且函数will do Unicode case conversion以区域设置不敏感的方式使用{{3由Open Group定义。此外,我们可以以(文本)区域设置敏感的方式对句柄执行IO。
import System.IO
import Data.Char
import Data.List (sort)
main = do
t <- mkTextEncoding "UTF-8"
hSetEncoding stdout t
let str = "ÇIİĞÖŞÜ"
strs = take 10 (cycle $ map toLower str : str : [])
mapM_ putStrLn (sort strs)
实际上,GHC默认会将您的文本区域设置用于IO(例如UTF8)。对于许多问题,这可能会给出正确的答案。您必须意识到在许多情况下它也会出错,因为如果没有批量处理文本,以及丰富的转换和比较支持,它是不可能正确的。
*Main> main
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
çiiğöşü
çiiğöşü
çiiğöşü
çiiğöşü
çiiğöşü