Possible bug/omission in Numeric library?
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
Hi! In fact, we might want to be slightly more general. Why don't go for a general base conversion, much like Malcolms idea but without converting every digit to a Char. Say something like toBase :: (Integral a) => a -> a -> [a] toBase base n | n < 0 = error "Numeric.toBase: can't convert negative numbers" | otherwise = theDigits n [] where theDigits n r = let (n',d) = quotRem n base r' = d : r in if n' == 0 then r' else theDigits n' r' Then the showInt function becomes showInt :: (Integral a) => a -> (Int->Char) -> a -> ShowS showInt base intToDig n r = foldr (\ i r -> intToDig (fromIntegral i) : r) r (toBase base n) but we can also use toBase by itself. We could also have an analogous fromBase, of course. Cheers, /kff
participants (2)
-
Karl-Filip Faxen -
Malcolm Wallace