如何在Haskell中根据语言环境格式化数字?

3
在Python中,我可以使用locale.format根据语言环境设置来美化打印数字:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
'en_US.UTF-8'
>>> locale.format("%.2f",1234567.89,grouping=True)
'1,234,567.89'

如何在Haskell中实现相同的功能?我发现有localeconv和setlocale绑定,但是否有一个支持Lconv的通用漂亮打印程序?

对于其他地区,它是不同的还是总是相同的?我想某些方面是不同的对吧? - yairchu
一个例子就是小数点分隔符。在美国,你写成5.3,在一些国家,比如德国,你会写成5,3。 - mrueg
是的,subw 是正确的。它取决于本地设置,格式因国家而异。它由 Lconv 结构定义。实际上,有三个重要参数:小数点、千位分隔符和每组的大小。对于货币值,还有其他参数。 - sastanin
你可以尝试在 #haskell IRC 频道中询问。通常情况下,那里会有人知道如何解决问题。 如果没有现成的解决方案,也许自己动手解决也不会太难,因为你可以通过 bindings-common 库(http://hackage.haskell.org/package/bindings-common)访问 Lconv 中的所有必要数据。 - mrueg
1个回答

1
我会说,如果所需的库缺失,你可以自己编写一个(显而易见的选择,但不容易),或者为所需函数编写绑定。例如,为sprintf编写限制绑定,仅允许sprintf双精度浮点数。

Double.hs:

{-# INCLUDE "double.h" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module Double (cPrintf) where

import Foreign
import Foreign.C.Types
import System.IO.Unsafe
import qualified Data.ByteString as B

foreign import ccall "double.h toString"
 c_toString :: CDouble -> (Ptr Word8) -> CInt -> IO CInt

buf = unsafePerformIO $ mallocBytes 64

cPrintf :: Double -> B.ByteString
cPrintf n = B.pack $ unsafePerformIO $ do
   len <- c_toString (realToFrac n) buf 64
   peekArray (fromIntegral len) buf

double.h:

int toString(double a, char *buffer, int bufferLen);

double.c:

#include <stdio.h>
#include "double.h"

int toString(double a, char *buffer, int bufferLen) {
 return snprintf(buffer, bufferLen, "%f", a);
}

构建为:

gcc -c double.c
ghc --make Main.hs double.o

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接