How to format numbers according to locale in Haskell?
Asked Answered
S

1

3

In Python I can use locale.format to pretty-print numbers according to locale setting:

>>> 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'

How can I do the same in Haskell? I see that there are localeconv and setlocale bindings, but is there a generic pretty printer which respects Lconv?

Shirtwaist answered 7/9, 2009 at 8:31 Comment(4)
is it different for other locales or always the same? I suppose it is different for some right?Myriammyriameter
An example of this would be the decimal separator. In the US, you write 5.3, in some countries, e.g. Germany, you would write 5,3.Hernandez
Yes, subw is right. It depends on local settings and the format varies between countries. It is devined by Lconv structure. In fact, there are three important parameters: decimal point, thousand separator and size of each group. There are additional parameters for monetary values.Shirtwaist
You could try to ask in the #haskell IRC channel. Usually, there is someone there who knows how to solve a problem. <br> If there is no solution already, it probably won't be too hard to roll you own, since you can access all the necessary data from Lconv with the bindings-common library ( hackage.haskell.org/package/bindings-common ).Hernandez
F
1

I would say that if the library in question is missing then you could either write yourself one (obvious option, not easy) or write a binding for the needed function. For example, restricted binding for sprintf which allows to sprintf only doubles:

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);
}

Build as:

gcc -c double.c
ghc --make Main.hs double.o
Foretell answered 12/11, 2009 at 19:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.