在Haskell中按区域设置对字符串进行排序和比较?

时间:2011-05-15 21:26:33

标签: string haskell localization locale

是否可以在Haskell(GHC)中使用国家字符对字符串进行正确排序?换句话说,按当前区域设置正确整理Chars?

我确实只找到了ICU模块,但它需要安装额外的库,因为它不是linux发行版的标准部分。我想基于POSIX的C(glibc like)库解决方案,因此处理额外的依赖关系不会有任何麻烦。

1 个答案:

答案 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ğöşü