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?

sastanin
  • 40,473
  • 13
  • 103
  • 130
  • is it different for other locales or always the same? I suppose it is different for some right? – yairchu Sep 07 '09 at 14:03
  • 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. – mrueg Sep 07 '09 at 21:50
  • 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. – sastanin Sep 08 '09 at 10:22
  • You could try to ask in the #haskell IRC channel. Usually, there is someone there who knows how to solve a problem.
    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 ( http://hackage.haskell.org/package/bindings-common ).
    – mrueg Sep 12 '09 at 15:25

1 Answers1

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
ADEpt
  • 5,504
  • 1
  • 25
  • 32