Possible bug/omission in Numeric library?

Malcolm Wallace Malcolm.Wallace@cs.york.ac.uk
Wed, 28 Nov 2001 15:10:47 +0000


There is something strange about the Haskell'98 Numeric library,
which I think could be considered a bug of sorts.  There are functions

    readDec, readOct, readHex :: (Integral a) => ReadS a

which read an integer from a string in base 10, 8, or 16, but there
are no corresponding show functions to convert an integer to a string
using base 8 or 16.  The sole function given is

    showInt :: (Integral a) => a -> ShowS

which shows a number in base 10 only.  I think you'll agree that it
is odd that you can read a certain number format but cannot show it?

There are several obvious generalisations of showInt.  One might be:

    showInt :: (Integral a) => a -> a -> ShowS
    showInt base n r
      | n < 0   = error "Numeric.showInt: can't show negative numbers"
      | otherwise =
          let (n',d) = quotRem n base
              r'     = Char.intToDigit (fromIntegral d) : r
          in if n' == 0 then r' else showInt base n' r'

which shows a number in any base up to 16.  Another might be:

    showInt :: (Integral a) => a -> (Int->Char) -> a -> ShowS
    showInt base intToDig n r
      | n < 0   = error "Numeric.showInt: can't show negative numbers"
      | otherwise =
          let (n',d) = quotRem n base
              r'     = intToDig (fromIntegral d) : r
          in if n' == 0 then r' else showInt base intToDig n' r'

which more closely resembles the dual function readInt and could
be likewise accompanied by specific instances for the three most
common bases:

    showDec, showOct, showHex :: (Integral a) => a -> ShowS
    showDec = showInt 10 Char.intToDigit
    showOct = showInt 8  Char.intToDigit
    showHex = showInt 16 Char.intToDigit

However, I would guess that changing the type signature of the
current showInt function is unacceptable for Haskell'98.  Maybe we
should consider adding the more general version under a new name
like showIntBase, together with show{Dec,Oct,Hex}?  This would break
no existing code, and clear up the slight anomaly in the current
capability of the Haskell'98 library.

Regards,
    Malcolm