Как форматировать числа в соответствии с локалью в Haskell?

В 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?


person sastanin    schedule 07.09.2009    source источник
comment
отличается ли он для других локалей или всегда одинаков? Я полагаю, это отличается для некоторых прав?   -  person yairchu    schedule 07.09.2009
comment
Примером этого может быть десятичный разделитель. В США вы пишете 5.3, в некоторых странах, например. Германия, вы бы написали 5,3.   -  person mrueg    schedule 08.09.2009
comment
Да, subw прав. Это зависит от местных настроек, и формат зависит от страны. Он разработан структурой Lconv. На самом деле есть три важных параметра: десятичная точка, разделитель тысяч и размер каждой группы. Существуют дополнительные параметры для денежных значений.   -  person sastanin    schedule 08.09.2009
comment
Вы можете попробовать задать вопрос на IRC-канале #haskell. Обычно там есть кто-то, кто знает, как решить проблему. ‹br› Если решения еще нет, возможно, не составит труда создать собственное, так как вы можете получить доступ ко всем необходимым данным из Lconv с помощью библиотеки bindings-common ( hackage.haskell.org/package/bindings-common).   -  person mrueg    schedule 12.09.2009


Ответы (1)


Я бы сказал, что если рассматриваемая библиотека отсутствует, то вы можете либо написать ее сами (очевидный вариант, непростой), либо написать привязку для нужной функции. Например, ограниченная привязка для sprintf, позволяющая использовать sprintf только удваивается:

Двойной.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

двойной.ч:

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

двойной.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
person ADEpt    schedule 12.11.2009
comment
Ну, выглядит менее сложным, чем я ожидал. Спасибо. - person sastanin; 13.11.2009