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

String 在Haskell中按区域设置对字符串进行排序和比较?,string,haskell,localization,locale,String,Haskell,Localization,Locale,是否可以在Haskell(GHC)中正确地对带有国家字符的字符串进行排序?换句话说,按当前区域设置正确排序字符 我确实只找到了ICU模块,但它需要安装额外的库,因为它不是linux发行版的标准部分。我希望解决方案基于POSIX的C(类似glibc的)库,这样就不会有处理额外依赖项的麻烦。推荐方式:text icu 如您所见,建议通过和以区域设置敏感的方式稳健地处理字符串。该库在标准库集中提供,即 例如,排序土耳其字符串: {-# LANGUAGE OverloadedStrings #-} i

是否可以在Haskell(GHC)中正确地对带有国家字符的字符串进行排序?换句话说,按当前区域设置正确排序字符


我确实只找到了ICU模块,但它需要安装额外的库,因为它不是linux发行版的标准部分。我希望解决方案基于POSIX的C(类似glibc的)库,这样就不会有处理额外依赖项的麻烦。

推荐方式:text icu

如您所见,建议通过以区域设置敏感的方式稳健地处理字符串。该库在标准库集中提供,即

例如,排序土耳其字符串:

{-# 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)
在正确下套管土耳其管柱后,根据区域设置正确排序:

*Main> main
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
çıiğöşü
çıiğöşü
çıiğöşü
çıiğöşü
çıiğöşü
不使用文本icu包

您在问题中要求避免使用Posix提供的库以外的其他库的解决方案。虽然文本icu很容易从Hackage安装(
cabal install text icu
),但它确实依赖于icu C库,而icu C库并非无处不在。此外,没有比Posix更健壮、更全面的替代方案。最后,
text-icu
是唯一能够正确转换多字符的软件包

尽管如此,Haskell中内置的Char和String类型提供了一些函数,这些函数的值表示Unicode,并且以不区分区域设置的方式使用OpenGroup定义的函数。此外,我们可以以(文本)区域设置敏感的方式对句柄执行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)


您可以将FFI绑定到
wcscoll
,但使用
文本icu
则更好,而且可能更正确。问得好,回答得好。Human stuff从来都不是一个纯函数。请注意,
i
在字符解决方案中是不同的。使用特定于区域设置的排序规则不是更正确吗?还要注意,
Char
上的toUpper仅基于
LC\u CTYPE
区域设置进行宽字符转换。因此,它只是部分地区感知。如前所述,多字符转换失败。@hammar是的,我认为您可能应该使用经批准的排序方法。
*Main> main
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
ÇIİĞÖŞÜ
çiiğöşü
çiiğöşü
çiiğöşü
çiiğöşü
çiiğöşü