diff --git a/src/Text/Printer/Fractional.hs b/src/Text/Printer/Fractional.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Printer/Fractional.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+
+-- | Print fractions.
+module Text.Printer.Fractional
+  (
+  -- * Positional numeral systems
+    PositionalSystem(..)
+  , BitSystem(..)
+  , Binary(..)
+  , Octal(..)
+  , Decimal(..)
+  , Hexadecimal(..)
+  , LowHex(..)
+  , UpHex(..)
+  -- * Optionality characteristic
+  , Optional(..)
+  , isOptional
+  , isRequired
+  -- * Fraction printers
+  , fraction'
+  , fraction
+  ) where
+
+import Data.Typeable (Typeable)
+import Data.Ix (Ix)
+import Data.Monoid (mempty)
+import Data.Ratio (numerator, denominator)
+import Text.Printer
+import Text.Printer.Integral
+
+-- | Optionality characteristic.
+data Optional = Optional
+              | Required
+              deriving (Typeable, Show, Read, Eq, Ord, Enum, Bounded, Ix)
+
+-- | True if the supplied value is 'Optional' and false otherwise.
+isOptional ∷ Optional → Bool
+isOptional Optional = True
+isOptional Required = False
+
+-- | True if the supplied value is 'Required' and false otherwise.
+isRequired ∷ Optional → Bool
+isRequired Optional = False
+isRequired Required = True
+
+-- | Print a fraction, writing the numerator and the denominator in
+--   the specified positional numeral system.
+fraction' ∷ (PositionalSystem s, Real α, Printer p)
+          ⇒ s
+          → p -- ^ Prefix for negative values
+          → p -- ^ Zero printer
+          → p -- ^ Prefix for positive values
+          → p -- ^ Numerator/denominator separator
+          → Optional -- ^ Whether to print invisible denominators
+          → α → p
+fraction' s neg z pos sep i a
+    | n == 0    = z
+    | d == 1    = case i of
+                    Optional → number' s neg z pos n
+                    Required →  number' s neg z pos n
+                             <> sep
+                             <> (printDigitIn s $! intToDigitIn s 1)
+    | otherwise = if n < 0
+                  then neg <> nonPositive s n <> sep <> nonNegative s d
+                  else pos <> nonNegative s n <> sep <> nonNegative s d
+  where r = toRational a
+        n = numerator r
+        d = denominator r
+
+-- | Print a fraction. The numerator and the denominator are written in the
+--   decimal numeral system and separated by a slash. Negative values
+--   are prefixed with a minus sign. Invisible denominators are omitted.
+fraction ∷ (Real α, Printer p) ⇒ α → p
+fraction = fraction' Decimal (char7 '-') (char7 '0')
+                     mempty (char7 '/') Optional
diff --git a/src/Text/Printer/Integral.hs b/src/Text/Printer/Integral.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Printer/Integral.hs
@@ -0,0 +1,865 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE BangPatterns #-}
+
+-- | Print integral numbers in common positional numeral systems. 
+module Text.Printer.Integral
+  (
+  -- * Positional systems
+    PositionalSystem(..)
+  , BitSystem(..)
+  , Binary(..)
+  , Octal(..)
+  , Decimal(..)
+  , Hexadecimal(..)
+  , LowHex(..)
+  , UpHex(..)
+  -- * Numeral printers
+  , nonNegative
+  , nnBinary
+  , nnOctal
+  , nnDecimal
+  , nnLowHex
+  , nnUpHex
+  , nnBits
+  , nnBinaryBits
+  , nnOctalBits
+  , nnLowHexBits
+  , nnUpHexBits
+  , nonPositive
+  , npBinary
+  , npOctal
+  , npDecimal
+  , npLowHex
+  , npUpHex
+  , npBits
+  , npBinaryBits
+  , npOctalBits
+  , npLowHexBits
+  , npUpHexBits
+  , number'
+  , number
+  , binary'
+  , binary
+  , octal'
+  , octal
+  , decimal'
+  , decimal
+  , lowHex'
+  , lowHex
+  , upHex'
+  , upHex
+  , bits'
+  , bits
+  , binaryBits'
+  , binaryBits
+  , octalBits'
+  , octalBits
+  , lowHexBits'
+  , lowHexBits
+  , upHexBits'
+  , upHexBits
+  ) where
+
+import Data.Typeable (Typeable)
+import Data.Char (chr, ord)
+import Data.Int
+import Data.Word
+import Data.Bits (Bits(..))
+import Data.Monoid (mempty)
+import qualified Text.Ascii as A
+import Text.Printer
+
+-- | Positional numeral system.
+class PositionalSystem s where
+  -- | The name of the system (e.g. \"binary\", \"decimal\").
+  systemName ∷ s → String
+  -- | The radix of the system.
+  radixIn ∷ Num α ⇒ s → α
+  -- | Test if a character is a digit.
+  isDigitIn ∷ s → Char → Bool
+  -- | Test if a character is a non-zero digit.
+  isNzDigitIn ∷ s → Char → Bool
+  -- | Map digits to the corresponding numbers. Return 'Nothing' on
+  --   other inputs.
+  fromDigitIn ∷ Num α ⇒ s → Char → Maybe α
+  -- | Map non-zero digits to the corresponding numbers. Return 'Nothing' on
+  --   other inputs.
+  fromNzDigitIn ∷ Num α ⇒ s → Char → Maybe α
+  -- | Map digits to the corresponding numbers. No checks are performed.
+  unsafeFromDigitIn ∷ Num α ⇒ s → Char → α
+  -- | Map 'Int' values to the corresponding digits. Inputs /must/ be
+  --   non-negative and less than the radix.
+  intToDigitIn ∷ s → Int → Char
+  -- | Print a digit.
+  printDigitIn ∷ Printer p ⇒ s → Char → p
+  printDigitIn _ = char7
+  {-# INLINE printDigitIn #-}
+  printZeroIn ∷ Printer p ⇒ s → p
+  printZeroIn s = printDigitIn s $! intToDigitIn s 0
+  {-# INLINE printZeroIn #-}
+
+-- | Positonal numeral system with a power of two radix.
+class PositionalSystem s ⇒ BitSystem s where
+  -- | Numer of bits occupied by a digit.
+  digitBitsIn ∷ s → Int
+  -- | The number that has 'digitBitsIn' least significant bits set to ones
+  --   and all the other bits set to zeroes.
+  digitMaskIn ∷ Num α ⇒ s → α
+  -- | Map the last digit of a number to the corresponding 'Int' value.
+  lastDigitIn ∷ Bits α ⇒ s → α → Int
+
+-- | The binary numeral system.
+data Binary = Binary deriving (Typeable, Eq, Ord, Show, Read)
+
+instance PositionalSystem Binary where
+  systemName _ = "binary"
+  {-# INLINE systemName #-}
+  radixIn _ = 2
+  {-# INLINE radixIn #-}
+  isDigitIn _ = A.isBinDigit
+  {-# INLINE isDigitIn #-}
+  isNzDigitIn _ = A.isNzBinDigit
+  {-# INLINE isNzDigitIn #-}
+  fromDigitIn _ = A.fromBinDigit
+  {-# INLINE fromDigitIn #-}
+  fromNzDigitIn _ = A.fromNzBinDigit
+  {-# INLINE fromNzDigitIn #-}
+  unsafeFromDigitIn _ = A.unsafeFromBinDigit
+  {-# INLINE unsafeFromDigitIn #-}
+  intToDigitIn _ i = chr $! ord '0' + i
+  {-# INLINE intToDigitIn #-}
+  printZeroIn _ = char7 '0'
+  {-# INLINE printZeroIn #-}
+
+instance BitSystem Binary where
+  digitBitsIn _ = 1
+  {-# INLINE digitBitsIn #-}
+  digitMaskIn _ = 1
+  {-# INLINE digitMaskIn #-}
+  lastDigitIn _ n = if testBit n 0 then 1 else 0
+  {-# INLINE lastDigitIn #-}
+
+-- | The octal numeral system.
+data Octal = Octal deriving (Typeable, Eq, Ord, Show, Read)
+
+instance PositionalSystem Octal where
+  systemName _ = "octal"
+  {-# INLINE systemName #-}
+  radixIn _ = 8
+  {-# INLINE radixIn #-}
+  isDigitIn _ = A.isOctDigit
+  {-# INLINE isDigitIn #-}
+  isNzDigitIn _ = A.isNzOctDigit
+  {-# INLINE isNzDigitIn #-}
+  fromDigitIn _ = A.fromOctDigit
+  {-# INLINE fromDigitIn #-}
+  fromNzDigitIn _ = A.fromNzOctDigit
+  {-# INLINE fromNzDigitIn #-}
+  unsafeFromDigitIn _ = A.unsafeFromOctDigit
+  {-# INLINE unsafeFromDigitIn #-}
+  intToDigitIn _ i = chr $! ord '0' + i
+  {-# INLINE intToDigitIn #-}
+  printZeroIn _ = char7 '0'
+  {-# INLINE printZeroIn #-}
+
+instance BitSystem Octal where
+  digitBitsIn _ = 3
+  {-# INLINE digitBitsIn #-}
+  digitMaskIn _ = 7
+  {-# INLINE digitMaskIn #-}
+  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
+                  + (if testBit n 1 then 2 else 0)
+                  + (if testBit n 2 then 4 else 0)
+  {-# INLINE lastDigitIn #-}
+
+-- | The decimal numeral system.
+data Decimal = Decimal deriving (Typeable, Eq, Ord, Show, Read)
+
+instance PositionalSystem Decimal where
+  systemName _ = "decimal"
+  {-# INLINE systemName #-}
+  radixIn _ = 10
+  {-# INLINE radixIn #-}
+  isDigitIn _ = A.isDecDigit
+  {-# INLINE isDigitIn #-}
+  isNzDigitIn _ = A.isNzDecDigit
+  {-# INLINE isNzDigitIn #-}
+  fromDigitIn _ = A.fromDecDigit
+  {-# INLINE fromDigitIn #-}
+  fromNzDigitIn _ = A.fromNzDecDigit
+  {-# INLINE fromNzDigitIn #-}
+  unsafeFromDigitIn _ = A.unsafeFromDecDigit
+  {-# INLINE unsafeFromDigitIn #-}
+  intToDigitIn _ i = chr $! ord '0' + i
+  {-# INLINE intToDigitIn #-}
+  printZeroIn _ = char7 '0'
+  {-# INLINE printZeroIn #-}
+
+-- | The hexadecimal numeral system.
+data Hexadecimal = Hexadecimal
+
+instance PositionalSystem Hexadecimal where
+  systemName _ = "hexadecimal"
+  {-# INLINE systemName #-}
+  radixIn _ = 16
+  {-# INLINE radixIn #-}
+  isDigitIn _ = A.isHexDigit
+  {-# INLINE isDigitIn #-}
+  isNzDigitIn _ = A.isNzHexDigit
+  {-# INLINE isNzDigitIn #-}
+  fromDigitIn _ = A.fromHexDigit
+  {-# INLINE fromDigitIn #-}
+  fromNzDigitIn _ = A.fromNzHexDigit
+  {-# INLINE fromNzDigitIn #-}
+  unsafeFromDigitIn _ = A.unsafeFromHexDigit
+  {-# INLINE unsafeFromDigitIn #-}
+  intToDigitIn _ i | i < 10    = chr $! ord '0' + i
+                   | otherwise = chr $! ord 'A' + (i - 10) 
+  {-# INLINE intToDigitIn #-}
+  printZeroIn _ = char7 '0'
+  {-# INLINE printZeroIn #-}
+
+instance BitSystem Hexadecimal where
+  digitBitsIn _ = 4
+  {-# INLINE digitBitsIn #-}
+  digitMaskIn _ = 15
+  {-# INLINE digitMaskIn #-}
+  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
+                  + (if testBit n 1 then 2 else 0)
+                  + (if testBit n 2 then 4 else 0)
+                  + (if testBit n 3 then 8 else 0)
+  {-# INLINABLE lastDigitIn #-}
+
+-- | The hexadecimal numeral system, using lower case digits.
+data LowHex = LowHex
+
+instance PositionalSystem LowHex where
+  systemName _ = "lower case hexadecimal"
+  {-# INLINE systemName #-}
+  radixIn _ = 16
+  {-# INLINE radixIn #-}
+  isDigitIn _ = A.isLowHexDigit
+  {-# INLINE isDigitIn #-}
+  isNzDigitIn _ = A.isNzLowHexDigit
+  {-# INLINE isNzDigitIn #-}
+  fromDigitIn _ = A.fromLowHexDigit
+  {-# INLINE fromDigitIn #-}
+  fromNzDigitIn _ = A.fromNzLowHexDigit
+  {-# INLINE fromNzDigitIn #-}
+  unsafeFromDigitIn _ = A.unsafeFromLowHexDigit
+  {-# INLINE unsafeFromDigitIn #-}
+  intToDigitIn _ i | i < 10    = chr $! ord '0' + i
+                   | otherwise = chr $! ord 'a' + (i - 10) 
+  {-# INLINE intToDigitIn #-}
+  printZeroIn _ = char7 '0'
+  {-# INLINE printZeroIn #-}
+
+instance BitSystem LowHex where
+  digitBitsIn _ = 4
+  {-# INLINE digitBitsIn #-}
+  digitMaskIn _ = 15
+  {-# INLINE digitMaskIn #-}
+  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
+                  + (if testBit n 1 then 2 else 0)
+                  + (if testBit n 2 then 4 else 0)
+                  + (if testBit n 3 then 8 else 0)
+  {-# INLINABLE lastDigitIn #-}
+
+-- | The hexadecimal numeral system, using upper case digits.
+data UpHex = UpHex
+
+instance PositionalSystem UpHex where
+  systemName _ = "upper case hexadecimal"
+  {-# INLINE systemName #-}
+  radixIn _ = 16
+  {-# INLINE radixIn #-}
+  isDigitIn _ = A.isUpHexDigit
+  {-# INLINE isDigitIn #-}
+  isNzDigitIn _ = A.isNzUpHexDigit
+  {-# INLINE isNzDigitIn #-}
+  fromDigitIn _ = A.fromUpHexDigit
+  {-# INLINE fromDigitIn #-}
+  fromNzDigitIn _ = A.fromNzUpHexDigit
+  {-# INLINE fromNzDigitIn #-}
+  unsafeFromDigitIn _ = A.unsafeFromUpHexDigit
+  {-# INLINE unsafeFromDigitIn #-}
+  intToDigitIn _ i | i < 10    = chr $! ord '0' + i
+                   | otherwise = chr $! ord 'A' + (i - 10) 
+  {-# INLINE intToDigitIn #-}
+  printZeroIn _ = char7 '0'
+  {-# INLINE printZeroIn #-}
+
+instance BitSystem UpHex where
+  digitBitsIn _ = 4
+  {-# INLINE digitBitsIn #-}
+  digitMaskIn _ = 15
+  {-# INLINE digitMaskIn #-}
+  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
+                  + (if testBit n 1 then 2 else 0)
+                  + (if testBit n 2 then 4 else 0)
+                  + (if testBit n 3 then 8 else 0)
+  {-# INLINABLE lastDigitIn #-}
+
+-- | Print a non-negative number in the specified positional numeral system.
+nonNegative ∷ (PositionalSystem s, Integral α, Printer p) ⇒ s → α → p
+nonNegative s = go (printDigitIn s $! intToDigitIn s 0)
+  where go p 0 = p
+        go _ m = go mempty q <> printDigitIn s d
+          where (q, r) = quotRem m radix
+                !d     = intToDigitIn s $ fromIntegral r
+        radix = radixIn s
+{-# INLINABLE nonNegative #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int8 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int16 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int32 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int64 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word8 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word16 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word32 → p #-}
+{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word64 → p #-}
+{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ Binary → α → p #-}
+{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ Octal → α → p #-}
+{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ Decimal → α → p #-}
+{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ LowHex → α → p #-}
+{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ UpHex → α → p #-}
+
+-- | Print a non-negative number in the binary numeral system.
+nnBinary ∷ (Integral α, Printer p) ⇒ α → p
+nnBinary = nonNegative Binary
+{-# INLINE nnBinary #-}
+
+-- | Print a non-negative number in the octal numeral system.
+nnOctal ∷ (Integral α, Printer p) ⇒ α → p
+nnOctal = nonNegative Octal
+{-# INLINE nnOctal #-}
+
+-- | Print a non-negative number in the decimal numeral system.
+nnDecimal ∷ (Integral α, Printer p) ⇒ α → p
+nnDecimal = nonNegative Decimal
+{-# INLINE nnDecimal #-}
+
+-- | Print a non-negative number in the hexadecimal numeral system
+--   using lower case digits.
+nnLowHex ∷ (Integral α, Printer p) ⇒ α → p
+nnLowHex = nonNegative LowHex
+{-# INLINE nnLowHex #-}
+
+-- | Print a non-negative number in the hexadecimal numeral system
+--   using upper case digits.
+nnUpHex ∷ (Integral α, Printer p) ⇒ α → p
+nnUpHex = nonNegative UpHex
+{-# INLINE nnUpHex #-}
+
+-- | Print a non-negative binary number in the specified positional numeral
+--   system.
+nnBits ∷ (BitSystem s, Num α, Bits α, Printer p) ⇒ s → α → p
+nnBits s = go (printDigitIn s $! intToDigitIn s 0)
+  where go p 0 = p
+        go _ m = go mempty (shiftR m digitBits) <> printDigitIn s d
+          where !d = intToDigitIn s $ lastDigitIn s m
+        digitBits = digitBitsIn s
+{-# INLINABLE nnBits #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int64 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word8 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word16 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word32 → p #-}
+{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word64 → p #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ Binary → α → p #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ Octal → α → p #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ Hexadecimal → α → p #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ LowHex → α → p #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ UpHex → α → p #-}
+
+-- | Print a non-negative binary number in the binary numeral system.
+nnBinaryBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
+nnBinaryBits = nnBits Binary
+{-# INLINE nnBinaryBits #-}
+
+-- | Print a non-negative binary number in the octal numeral system.
+nnOctalBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
+nnOctalBits = nnBits Octal
+{-# INLINE nnOctalBits #-}
+
+-- | Print a non-negative binary number in the hexadecimal numeral system
+--   using lower case digits.
+nnLowHexBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
+nnLowHexBits = nnBits LowHex
+{-# INLINE nnLowHexBits #-}
+
+-- | Print a non-negative binary number in the hexadecimal numeral system
+--   using upper case digits.
+nnUpHexBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
+nnUpHexBits = nnBits UpHex
+{-# INLINE nnUpHexBits #-}
+
+-- | Print a non-positive number in the specified positional numeral system.
+--   For example, @'nonPositive' 'Decimal' (-/123/)@ would print \"123\".
+nonPositive ∷ (PositionalSystem s, Integral α, Printer p) ⇒ s → α → p
+nonPositive s = go (printDigitIn s $! intToDigitIn s 0)
+  where go p 0 = p
+        go _ m = go mempty q <> printDigitIn s d
+          where (q, r) = quotRem m radix
+                !d     = intToDigitIn s $ negate $ fromIntegral r
+        radix = radixIn s
+{-# INLINABLE nonPositive #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int8 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int16 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int32 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int64 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word8 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word16 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word32 → p #-}
+{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word64 → p #-}
+{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ Binary → α → p #-}
+{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ Octal → α → p #-}
+{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ Decimal → α → p #-}
+{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ LowHex → α → p #-}
+{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ UpHex → α → p #-}
+
+-- | Print a non-positive number in the binary numeral system.
+npBinary ∷ (Integral α, Printer p) ⇒ α → p
+npBinary = nonPositive Binary
+{-# INLINE npBinary #-}
+
+-- | Print a non-positive number in the octal numeral system.
+npOctal ∷ (Integral α, Printer p) ⇒ α → p
+npOctal = nonPositive Octal
+{-# INLINE npOctal #-}
+
+-- | Print a non-positive number in the decimal numeral system.
+npDecimal ∷ (Integral α, Printer p) ⇒ α → p
+npDecimal = nonPositive Decimal
+{-# INLINE npDecimal #-}
+
+-- | Print a non-positive number in the hexadecimal numeral system
+--   using lower case digits.
+npLowHex ∷ (Integral α, Printer p) ⇒ α → p
+npLowHex = nonPositive LowHex
+{-# INLINE npLowHex #-}
+
+-- | Print a non-positive number in the hexadecimal numeral system
+--   using upper case digits.
+npUpHex ∷ (Integral α, Printer p) ⇒ α → p
+npUpHex = nonPositive UpHex
+{-# INLINE npUpHex #-}
+
+-- | Print a non-positive two-compliment binary number in the specified
+--   positional numeral system. For example, @'npBits' 'UpHex' (-/0xABC/)@
+--   would print \"ABC\".
+npBits ∷ (BitSystem s, Ord α, Num α, Bits α, Printer p) ⇒ s → α → p
+npBits s n = case testBit n 0 of
+    True → go mempty (shiftR (negate n) digitBits) <> printDigitIn s d
+      where !d = intToDigitIn s $ radix - lastDigitIn s n
+    False → case n > negRadix of
+        True → printDigitIn s d'
+        False → go mempty m <> printDigitIn s d'
+          where m | d == 0    = negate $ shiftR n digitBits
+                  | otherwise = complement $ shiftR n digitBits
+      where !d  = lastDigitIn s n
+            !d' = intToDigitIn s $ (radix - d) .&. digitMask
+  where go p 0 = p
+        go p m = go p (shiftR m digitBits) <> printDigitIn s d
+          where !d = intToDigitIn s $ lastDigitIn s m
+        radix     = radixIn s
+        digitMask = digitMaskIn s
+        digitBits = digitBitsIn s
+        negRadix  = complement $ digitMaskIn s
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int64 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word8 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word16 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word32 → p #-}
+{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word64 → p #-}
+{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Binary → α → p #-}
+{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Octal → α → p #-}
+{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Hexadecimal → α → p #-}
+{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ LowHex → α → p #-}
+{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ UpHex → α → p #-}
+
+-- | Print a non-positive binary number in the binary numeral system.
+npBinaryBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+npBinaryBits = npBits Binary
+{-# INLINE npBinaryBits #-}
+
+-- | Print a non-positive binary number in the octal numeral system.
+npOctalBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+npOctalBits = npBits Octal
+{-# INLINE npOctalBits #-}
+
+-- | Print a non-positive binary number in the hexadecimal numeral system
+--   using lower case digits.
+npLowHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+npLowHexBits = npBits LowHex
+{-# INLINE npLowHexBits #-}
+
+-- | Print a non-positive binary number in the hexadecimal numeral system
+--   using upper case digits.
+npUpHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+npUpHexBits = npBits UpHex
+{-# INLINE npUpHexBits #-}
+
+-- | Print a number in the specified positional numeral system.
+number' ∷ (PositionalSystem s, Ord α, Integral α, Printer p)
+        ⇒ s
+        → p -- ^ Prefix for negative values
+        → p -- ^ Zero printer
+        → p -- ^ Prefix for positive values
+        → α → p
+number' s neg z pos n = case compare n 0 of
+    LT → go neg q <> printDigitIn s d
+      where (q, r) = quotRem n (negate radix)
+            !d     = intToDigitIn s $ negate $ fromIntegral r
+    EQ → z
+    GT → go pos q <> printDigitIn s d
+      where (q, r) = quotRem n radix
+            !d     = intToDigitIn s $ fromIntegral r
+  where go p 0 = p
+        go p m = go p q <> printDigitIn s d
+          where (q, r) = quotRem m radix
+                !d     = intToDigitIn s $ fromIntegral r
+        radix = radixIn s
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int8 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int16 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int32 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int64 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word8 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word16 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word32 → p #-}
+{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word64 → p #-}
+{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Binary → p → p → p → α → p #-}
+{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Decimal → p → p → p → α → p #-}
+{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Octal → p → p → p → α → p #-}
+{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Hexadecimal → p → p → p → α → p #-}
+{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ LowHex → p → p → p → α → p #-}
+{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ UpHex → p → p → p → α → p #-}
+
+-- | Print a number in the specified positional numeral system. Negative
+--   values are prefixed with a minus sign.
+number ∷ (PositionalSystem s, Ord α, Integral α, Printer p) ⇒ s → α → p
+number s = number' s (char7 '-') (printZeroIn s) mempty
+{-# INLINE number #-}
+
+-- | Print a number in the binary numeral system.
+binary' ∷ (Ord α, Integral α, Printer p)
+        ⇒ p -- ^ Prefix for negative values
+        → p -- ^ Zero printer
+        → p -- ^ Prefix for positive values
+        → α → p
+binary' = number' Binary
+{-# INLINE binary' #-}
+
+-- | Print a number in the binary numeral system. Negative values
+--   are prefixed with a minus sign.
+binary ∷ (Ord α, Integral α, Printer p) ⇒ α → p
+binary = number Binary
+{-# INLINE binary #-}
+
+-- | Print a number in the octal numeral system.
+octal' ∷ (Ord α, Integral α, Printer p)
+       ⇒ p -- ^ Prefix for negative values
+       → p -- ^ Zero printer
+       → p -- ^ Prefix for positive values
+       → α → p
+octal' = number' Octal
+{-# INLINE octal' #-}
+
+-- | Print a number in the octal numeral system. Negative values
+--   are prefixed with a minus sign.
+octal ∷ (Ord α, Integral α, Printer p) ⇒ α → p
+octal = number Octal
+{-# INLINE octal #-}
+
+-- | Print a number in the decimal numeral system.
+decimal' ∷ (Ord α, Integral α, Printer p)
+         ⇒ p -- ^ Prefix for negative values
+         → p -- ^ Zero printer
+         → p -- ^ Prefix for positive values
+         → α → p
+decimal' = number' Decimal
+{-# INLINE decimal' #-}
+
+-- | Print a number in the decimal numeral system. Negative values
+--   are prefixed with a minus sign.
+decimal ∷ (Ord α, Integral α, Printer p) ⇒ α → p
+decimal = number Decimal
+{-# INLINE decimal #-}
+
+-- | Print a number in the hexadecimal numeral system using lower case
+--   digits.
+lowHex' ∷ (Ord α, Integral α, Printer p)
+        ⇒ p -- ^ Prefix for negative values
+        → p -- ^ Zero printer
+        → p -- ^ Prefix for positive values
+        → α → p
+lowHex' = number' LowHex
+{-# INLINE lowHex' #-}
+
+-- | Print a number in the hexadecimal numeral system using lower case
+--   digits. Negative values are prefixed with a minus sign.
+lowHex ∷ (Ord α, Integral α, Printer p) ⇒ α → p
+lowHex = number LowHex
+{-# INLINE lowHex #-}
+
+-- | Print a number in the hexadecimal numeral system using upper case
+--   digits.
+upHex' ∷ (Ord α, Integral α, Printer p)
+       ⇒ p -- ^ Prefix for negative values
+       → p -- ^ Zero printer
+       → p -- ^ Prefix for positive values
+       → α → p
+upHex' = number' UpHex
+{-# INLINE upHex' #-}
+
+-- | Print a number in the hexadecimal numeral system using upper case
+--   digits. Negative values are prefixed with a minus sign.
+upHex ∷ (Ord α, Integral α, Printer p) ⇒ α → p
+upHex = number UpHex
+{-# INLINE upHex #-}
+
+-- | Print a binary number in the specified positional numeral system.
+bits' ∷ (BitSystem s, Ord α, Num α, Bits α, Printer p)
+      ⇒ s
+      → p -- ^ Prefix for negative values
+      → p -- ^ Zero printer
+      → p -- ^ Prefix for positive values
+      → α → p
+bits' s neg z pos n = case compare n 0 of
+    LT → case testBit n 0 of
+           True → go neg (shiftR (negate n) digitBits) <> printDigitIn s d
+             where !d = intToDigitIn s $ radix - lastDigitIn s n
+           False → case n > negRadix of
+               True → neg <> printDigitIn s d'
+               False → go neg m <> printDigitIn s d'
+                 where m | d == 0    = negate $ shiftR n digitBits
+                         | otherwise = complement $ shiftR n digitBits
+             where !d  = lastDigitIn s n
+                   !d' = intToDigitIn s $ (radix - d) .&. digitMask
+    EQ → z
+    GT → go pos (shiftR n digitBits) <> printDigitIn s d
+      where !d = intToDigitIn s $ lastDigitIn s n
+  where go p 0 = p
+        go p m = go p (shiftR m digitBits) <> printDigitIn s d
+          where !d = intToDigitIn s $ lastDigitIn s m
+        radix     = radixIn s
+        digitMask = digitMaskIn s
+        digitBits = digitBitsIn s
+        negRadix  = complement $ digitMaskIn s
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int64 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word8 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word16 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word32 → p #-}
+{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word64 → p #-}
+{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Binary → p → p → p → α → p #-}
+{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Octal → p → p → p → α → p #-}
+{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Hexadecimal → p → p → p → α → p #-}
+{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ LowHex → p → p → p → α → p #-}
+{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ UpHex → p → p → p → α → p #-}
+
+-- | Print a binary number in the specified positional numeral system.
+--   Negative values are prefixed with a minus sign.
+bits ∷ (BitSystem s, Ord α, Num α, Bits α, Printer p) ⇒ s → α → p
+bits s = bits' s (char7 '-') (printZeroIn s) mempty
+{-# INLINE bits #-}
+
+-- | Print a binary number in the binary numeral system.
+binaryBits' ∷ (Ord α, Num α, Bits α, Printer p)
+            ⇒ p -- ^ Prefix for negative values
+            → p -- ^ Zero printer
+            → p -- ^ Prefix for positive values
+            → α → p
+binaryBits' = bits' Binary
+{-# INLINE binaryBits' #-}
+
+-- | Print a binary number in the binary numeral system. Negative values
+--   are prefixed with a minus sign.
+binaryBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+binaryBits = bits Binary
+{-# INLINE binaryBits #-}
+
+-- | Print a binary number in the octal numeral system.
+octalBits' ∷ (Ord α, Num α, Bits α, Printer p)
+           ⇒ p -- ^ Prefix for negative values
+           → p -- ^ Zero printer
+           → p -- ^ Prefix for positive values
+           → α → p
+octalBits' = bits' Octal
+{-# INLINE octalBits' #-}
+
+-- | Print a binary number in the octal numeral system. Negative values
+--   are prefixed with a minus sign.
+octalBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+octalBits = bits Octal
+{-# INLINE octalBits #-}
+
+-- | Print a binary number in the hexadecimal numeral system using lower
+--   case digits.
+lowHexBits' ∷ (Ord α, Num α, Bits α, Printer p)
+            ⇒ p -- ^ Prefix for negative values
+            → p -- ^ Zero printer
+            → p -- ^ Prefix for positive values
+            → α → p
+lowHexBits' = bits' LowHex
+{-# INLINE lowHexBits' #-}
+
+-- | Print a binary number in the hexadecimal numeral system using lower
+--   case digits. Negative values are prefixed with a minus sign.
+lowHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+lowHexBits = bits LowHex
+{-# INLINE lowHexBits #-}
+
+-- | Print a binary number in the hexadecimal numeral system using upper
+--   case digits.
+upHexBits' ∷ (Ord α, Num α, Bits α, Printer p)
+           ⇒ p -- ^ Prefix for negative values
+           → p -- ^ Zero printer
+           → p -- ^ Prefix for positive values
+           → α → p
+upHexBits' = bits' UpHex
+{-# INLINE upHexBits' #-}
+
+-- | Print a binary number in the hexadecimal numeral system using upper
+--   case digits. Negative values are prefixed with a minus sign.
+upHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
+upHexBits = bits UpHex
+{-# INLINE upHexBits #-}
diff --git a/src/Text/Printer/Numerals.hs b/src/Text/Printer/Numerals.hs
deleted file mode 100644
--- a/src/Text/Printer/Numerals.hs
+++ /dev/null
@@ -1,852 +0,0 @@
-{-# LANGUAGE UnicodeSyntax #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE BangPatterns #-}
-
--- | Print numbers in common positional numeral systems. 
-module Text.Printer.Numerals
-  (
-  -- * Positional systems.
-    PositionalSystem(..)
-  , BitSystem(..)
-  , Binary(..)
-  , Octal(..)
-  , Decimal(..)
-  , Hexadecimal(..)
-  , LowHex(..)
-  , UpHex(..)
-  -- * Numeral printers
-  , nonNegative
-  , nnBinary
-  , nnOctal
-  , nnDecimal
-  , nnLowHex
-  , nnUpHex
-  , nnBits
-  , nnBinaryBits
-  , nnOctalBits
-  , nnLowHexBits
-  , nnUpHexBits
-  , nonPositive
-  , npBinary
-  , npOctal
-  , npDecimal
-  , npLowHex
-  , npUpHex
-  , npBits
-  , npBinaryBits
-  , npOctalBits
-  , npLowHexBits
-  , npUpHexBits
-  , number'
-  , number
-  , binary'
-  , binary
-  , octal'
-  , octal
-  , decimal'
-  , decimal
-  , lowHex'
-  , lowHex
-  , upHex'
-  , upHex
-  , bits'
-  , bits
-  , binaryBits'
-  , binaryBits
-  , octalBits'
-  , octalBits
-  , lowHexBits'
-  , lowHexBits
-  , upHexBits'
-  , upHexBits
-  ) where
-
-import Data.Typeable (Typeable)
-import Data.Char (chr, ord)
-import Data.Int
-import Data.Word
-import Data.Bits (Bits(..))
-import Data.Monoid (mempty)
-import qualified Text.Ascii as A
-import Text.Printer
-
--- | Positional numeral system.
-class PositionalSystem s where
-  -- | The name of the system (e.g. \"binary\", \"decimal\").
-  systemName ∷ s → String
-  -- | The radix of the system.
-  radixIn ∷ Num α ⇒ s → α
-  -- | Test if a character is a digit.
-  isDigitIn ∷ s → Char → Bool
-  -- | Test if a character is a non-zero digit.
-  isNzDigitIn ∷ s → Char → Bool
-  -- | Map digits to the corresponding numbers. Return 'Nothing' on
-  --   other inputs.
-  fromDigitIn ∷ Num α ⇒ s → Char → Maybe α
-  -- | Map non-zero digits to the corresponding numbers. Return 'Nothing' on
-  --   other inputs.
-  fromNzDigitIn ∷ Num α ⇒ s → Char → Maybe α
-  -- | Map digits to the corresponding numbers. No checks are performed.
-  unsafeFromDigitIn ∷ Num α ⇒ s → Char → α
-  -- | Map 'Int' values to the corresponding digits. Inputs /must/ be
-  --   non-negative and less than the radix.
-  intToDigitIn ∷ s → Int → Char
-  -- | Print a digit.
-  printDigitIn ∷ Printer p ⇒ s → Char → p
-  printDigitIn _ = char7
-  {-# INLINE printDigitIn #-}
-
--- | Positonal numeral system with a power of two radix.
-class PositionalSystem s ⇒ BitSystem s where
-  -- | Numer of bits occupied by a digit.
-  digitBitsIn ∷ s → Int
-  -- | The number that has 'digitBitsIn' least significant bits set to ones
-  --   and all the other bits set to zeroes.
-  digitMaskIn ∷ Num α ⇒ s → α
-  -- | Map the last digit of a number to the corresponding 'Int' value.
-  lastDigitIn ∷ Bits α ⇒ s → α → Int
-
--- | The binary numeral system.
-data Binary = Binary deriving (Typeable, Eq, Ord, Show, Read)
-
-instance PositionalSystem Binary where
-  systemName _ = "binary"
-  {-# INLINE systemName #-}
-  radixIn _ = 2
-  {-# INLINE radixIn #-}
-  isDigitIn _ = A.isBinDigit
-  {-# INLINE isDigitIn #-}
-  isNzDigitIn _ = A.isNzBinDigit
-  {-# INLINE isNzDigitIn #-}
-  fromDigitIn _ = A.fromBinDigit
-  {-# INLINE fromDigitIn #-}
-  fromNzDigitIn _ = A.fromNzBinDigit
-  {-# INLINE fromNzDigitIn #-}
-  unsafeFromDigitIn _ = A.unsafeFromBinDigit
-  {-# INLINE unsafeFromDigitIn #-}
-  intToDigitIn _ i = chr $! ord '0' + i
-  {-# INLINE intToDigitIn #-}
-
-instance BitSystem Binary where
-  digitBitsIn _ = 1
-  {-# INLINE digitBitsIn #-}
-  digitMaskIn _ = 1
-  {-# INLINE digitMaskIn #-}
-  lastDigitIn _ n = if testBit n 0 then 1 else 0
-  {-# INLINE lastDigitIn #-}
-
--- | The octal numeral system.
-data Octal = Octal deriving (Typeable, Eq, Ord, Show, Read)
-
-instance PositionalSystem Octal where
-  systemName _ = "octal"
-  {-# INLINE systemName #-}
-  radixIn _ = 8
-  {-# INLINE radixIn #-}
-  isDigitIn _ = A.isOctDigit
-  {-# INLINE isDigitIn #-}
-  isNzDigitIn _ = A.isNzOctDigit
-  {-# INLINE isNzDigitIn #-}
-  fromDigitIn _ = A.fromOctDigit
-  {-# INLINE fromDigitIn #-}
-  fromNzDigitIn _ = A.fromNzOctDigit
-  {-# INLINE fromNzDigitIn #-}
-  unsafeFromDigitIn _ = A.unsafeFromOctDigit
-  {-# INLINE unsafeFromDigitIn #-}
-  intToDigitIn _ i = chr $! ord '0' + i
-  {-# INLINE intToDigitIn #-}
-
-instance BitSystem Octal where
-  digitBitsIn _ = 3
-  {-# INLINE digitBitsIn #-}
-  digitMaskIn _ = 7
-  {-# INLINE digitMaskIn #-}
-  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
-                  + (if testBit n 1 then 2 else 0)
-                  + (if testBit n 2 then 4 else 0)
-  {-# INLINE lastDigitIn #-}
-
--- | The decimal numeral system.
-data Decimal = Decimal deriving (Typeable, Eq, Ord, Show, Read)
-
-instance PositionalSystem Decimal where
-  systemName _ = "decimal"
-  {-# INLINE systemName #-}
-  radixIn _ = 10
-  {-# INLINE radixIn #-}
-  isDigitIn _ = A.isDecDigit
-  {-# INLINE isDigitIn #-}
-  isNzDigitIn _ = A.isNzDecDigit
-  {-# INLINE isNzDigitIn #-}
-  fromDigitIn _ = A.fromDecDigit
-  {-# INLINE fromDigitIn #-}
-  fromNzDigitIn _ = A.fromNzDecDigit
-  {-# INLINE fromNzDigitIn #-}
-  unsafeFromDigitIn _ = A.unsafeFromDecDigit
-  {-# INLINE unsafeFromDigitIn #-}
-  intToDigitIn _ i = chr $! ord '0' + i
-  {-# INLINE intToDigitIn #-}
-
--- | The hexadecimal numeral system.
-data Hexadecimal = Hexadecimal
-
-instance PositionalSystem Hexadecimal where
-  systemName _ = "hexadecimal"
-  {-# INLINE systemName #-}
-  radixIn _ = 16
-  {-# INLINE radixIn #-}
-  isDigitIn _ = A.isHexDigit
-  {-# INLINE isDigitIn #-}
-  isNzDigitIn _ = A.isNzHexDigit
-  {-# INLINE isNzDigitIn #-}
-  fromDigitIn _ = A.fromHexDigit
-  {-# INLINE fromDigitIn #-}
-  fromNzDigitIn _ = A.fromNzHexDigit
-  {-# INLINE fromNzDigitIn #-}
-  unsafeFromDigitIn _ = A.unsafeFromHexDigit
-  {-# INLINE unsafeFromDigitIn #-}
-  intToDigitIn _ i | i < 10    = chr $! ord '0' + i
-                   | otherwise = chr $! ord 'A' + (i - 10) 
-  {-# INLINE intToDigitIn #-}
-
-instance BitSystem Hexadecimal where
-  digitBitsIn _ = 4
-  {-# INLINE digitBitsIn #-}
-  digitMaskIn _ = 15
-  {-# INLINE digitMaskIn #-}
-  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
-                  + (if testBit n 1 then 2 else 0)
-                  + (if testBit n 2 then 4 else 0)
-                  + (if testBit n 3 then 8 else 0)
-  {-# INLINABLE lastDigitIn #-}
-
--- | The hexadecimal numeral system, using lower case digits.
-data LowHex = LowHex
-
-instance PositionalSystem LowHex where
-  systemName _ = "lower case hexadecimal"
-  {-# INLINE systemName #-}
-  radixIn _ = 16
-  {-# INLINE radixIn #-}
-  isDigitIn _ = A.isLowHexDigit
-  {-# INLINE isDigitIn #-}
-  isNzDigitIn _ = A.isNzLowHexDigit
-  {-# INLINE isNzDigitIn #-}
-  fromDigitIn _ = A.fromLowHexDigit
-  {-# INLINE fromDigitIn #-}
-  fromNzDigitIn _ = A.fromNzLowHexDigit
-  {-# INLINE fromNzDigitIn #-}
-  unsafeFromDigitIn _ = A.unsafeFromLowHexDigit
-  {-# INLINE unsafeFromDigitIn #-}
-  intToDigitIn _ i | i < 10    = chr $! ord '0' + i
-                   | otherwise = chr $! ord 'a' + (i - 10) 
-  {-# INLINE intToDigitIn #-}
-
-instance BitSystem LowHex where
-  digitBitsIn _ = 4
-  {-# INLINE digitBitsIn #-}
-  digitMaskIn _ = 15
-  {-# INLINE digitMaskIn #-}
-  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
-                  + (if testBit n 1 then 2 else 0)
-                  + (if testBit n 2 then 4 else 0)
-                  + (if testBit n 3 then 8 else 0)
-  {-# INLINABLE lastDigitIn #-}
-
--- | The hexadecimal numeral system, using upper case digits.
-data UpHex = UpHex
-
-instance PositionalSystem UpHex where
-  systemName _ = "upper case hexadecimal"
-  {-# INLINE systemName #-}
-  radixIn _ = 16
-  {-# INLINE radixIn #-}
-  isDigitIn _ = A.isUpHexDigit
-  {-# INLINE isDigitIn #-}
-  isNzDigitIn _ = A.isNzUpHexDigit
-  {-# INLINE isNzDigitIn #-}
-  fromDigitIn _ = A.fromUpHexDigit
-  {-# INLINE fromDigitIn #-}
-  fromNzDigitIn _ = A.fromNzUpHexDigit
-  {-# INLINE fromNzDigitIn #-}
-  unsafeFromDigitIn _ = A.unsafeFromUpHexDigit
-  {-# INLINE unsafeFromDigitIn #-}
-  intToDigitIn _ i | i < 10    = chr $! ord '0' + i
-                   | otherwise = chr $! ord 'A' + (i - 10) 
-  {-# INLINE intToDigitIn #-}
-
-instance BitSystem UpHex where
-  digitBitsIn _ = 4
-  {-# INLINE digitBitsIn #-}
-  digitMaskIn _ = 15
-  {-# INLINE digitMaskIn #-}
-  lastDigitIn _ n = (if testBit n 0 then 1 else 0)
-                  + (if testBit n 1 then 2 else 0)
-                  + (if testBit n 2 then 4 else 0)
-                  + (if testBit n 3 then 8 else 0)
-  {-# INLINABLE lastDigitIn #-}
-
--- | Print a non-negative number in the specified positional numeral system.
-nonNegative ∷ (PositionalSystem s, Integral α, Printer p) ⇒ s → α → p
-nonNegative s = go (printDigitIn s $! intToDigitIn s 0)
-  where go p 0 = p
-        go _ m = go mempty q <> printDigitIn s d
-          where (q, r) = quotRem m radix
-                !d     = intToDigitIn s $ fromIntegral r
-        radix = radixIn s
-{-# INLINABLE nonNegative #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int8 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int16 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int32 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Int64 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word8 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word16 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word32 → p #-}
-{-# SPECIALIZE nonNegative ∷ Printer p ⇒ Decimal → Word64 → p #-}
-{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ Binary → α → p #-}
-{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ Octal → α → p #-}
-{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ Decimal → α → p #-}
-{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ LowHex → α → p #-}
-{-# SPECIALIZE nonNegative ∷ (Integral α, Printer p) ⇒ UpHex → α → p #-}
-
--- | Print a non-negative number in the binary numeral system.
-nnBinary ∷ (Integral α, Printer p) ⇒ α → p
-nnBinary = nonNegative Binary
-{-# INLINE nnBinary #-}
-
--- | Print a non-negative number in the octal numeral system.
-nnOctal ∷ (Integral α, Printer p) ⇒ α → p
-nnOctal = nonNegative Octal
-{-# INLINE nnOctal #-}
-
--- | Print a non-negative number in the decimal numeral system.
-nnDecimal ∷ (Integral α, Printer p) ⇒ α → p
-nnDecimal = nonNegative Decimal
-{-# INLINE nnDecimal #-}
-
--- | Print a non-negative number in the hexadecimal numeral system
---   using lower case digits.
-nnLowHex ∷ (Integral α, Printer p) ⇒ α → p
-nnLowHex = nonNegative LowHex
-{-# INLINE nnLowHex #-}
-
--- | Print a non-negative number in the hexadecimal numeral system
---   using upper case digits.
-nnUpHex ∷ (Integral α, Printer p) ⇒ α → p
-nnUpHex = nonNegative UpHex
-{-# INLINE nnUpHex #-}
-
--- | Print a non-negative binary number in the specified positional numeral
---   system.
-nnBits ∷ (BitSystem s, Num α, Bits α, Printer p) ⇒ s → α → p
-nnBits s = go (printDigitIn s $! intToDigitIn s 0)
-  where go p 0 = p
-        go _ m = go mempty (shiftR m digitBits) <> printDigitIn s d
-          where !d = intToDigitIn s $ lastDigitIn s m
-        digitBits = digitBitsIn s
-{-# INLINABLE nnBits #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Int64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Binary → Word64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Int64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Octal → Word64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Int64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ Hexadecimal → Word64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Int64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ LowHex → Word64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Int64 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word8 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word16 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word32 → p #-}
-{-# SPECIALIZE nnBits ∷ Printer p ⇒ UpHex → Word64 → p #-}
-{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ Binary → α → p #-}
-{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ Octal → α → p #-}
-{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ Hexadecimal → α → p #-}
-{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ LowHex → α → p #-}
-{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Printer p) ⇒ UpHex → α → p #-}
-
--- | Print a non-negative binary number in the binary numeral system.
-nnBinaryBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
-nnBinaryBits = nnBits Binary
-{-# INLINE nnBinaryBits #-}
-
--- | Print a non-negative binary number in the octal numeral system.
-nnOctalBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
-nnOctalBits = nnBits Octal
-{-# INLINE nnOctalBits #-}
-
--- | Print a non-negative binary number in the hexadecimal numeral system
---   using lower case digits.
-nnLowHexBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
-nnLowHexBits = nnBits LowHex
-{-# INLINE nnLowHexBits #-}
-
--- | Print a non-negative binary number in the hexadecimal numeral system
---   using upper case digits.
-nnUpHexBits ∷ (Num α, Bits α, Printer p) ⇒ α → p
-nnUpHexBits = nnBits UpHex
-{-# INLINE nnUpHexBits #-}
-
--- | Print a non-positive number in the specified positional numeral system.
---   For example, @'nonPositive' 'Decimal' (-/123/)@ would print \"123\".
-nonPositive ∷ (PositionalSystem s, Integral α, Printer p) ⇒ s → α → p
-nonPositive s = go (printDigitIn s $! intToDigitIn s 0)
-  where go p 0 = p
-        go _ m = go mempty q <> printDigitIn s d
-          where (q, r) = quotRem m radix
-                !d     = intToDigitIn s $ negate $ fromIntegral r
-        radix = radixIn s
-{-# INLINABLE nonPositive #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int8 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int16 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int32 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Int64 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word8 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word16 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word32 → p #-}
-{-# SPECIALIZE nonPositive ∷ Printer p ⇒ Decimal → Word64 → p #-}
-{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ Binary → α → p #-}
-{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ Octal → α → p #-}
-{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ Decimal → α → p #-}
-{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ LowHex → α → p #-}
-{-# SPECIALIZE nonPositive ∷ (Integral α, Printer p) ⇒ UpHex → α → p #-}
-
--- | Print a non-positive number in the binary numeral system.
-npBinary ∷ (Integral α, Printer p) ⇒ α → p
-npBinary = nonPositive Binary
-{-# INLINE npBinary #-}
-
--- | Print a non-positive number in the octal numeral system.
-npOctal ∷ (Integral α, Printer p) ⇒ α → p
-npOctal = nonPositive Octal
-{-# INLINE npOctal #-}
-
--- | Print a non-positive number in the decimal numeral system.
-npDecimal ∷ (Integral α, Printer p) ⇒ α → p
-npDecimal = nonPositive Decimal
-{-# INLINE npDecimal #-}
-
--- | Print a non-positive number in the hexadecimal numeral system
---   using lower case digits.
-npLowHex ∷ (Integral α, Printer p) ⇒ α → p
-npLowHex = nonPositive LowHex
-{-# INLINE npLowHex #-}
-
--- | Print a non-positive number in the hexadecimal numeral system
---   using upper case digits.
-npUpHex ∷ (Integral α, Printer p) ⇒ α → p
-npUpHex = nonPositive UpHex
-{-# INLINE npUpHex #-}
-
--- | Print a non-positive two-compliment binary number in the specified
---   positional numeral system. For example, @'npBits' 'UpHex' (-/0xABC/)@
---   would print \"ABC\".
-npBits ∷ (BitSystem s, Ord α, Num α, Bits α, Printer p) ⇒ s → α → p
-npBits s n = case testBit n 0 of
-    True → go mempty (shiftR (negate n) digitBits) <> printDigitIn s d
-      where !d = intToDigitIn s $ radix - lastDigitIn s n
-    False → case n > negRadix of
-        True → printDigitIn s d'
-        False → go mempty m <> printDigitIn s d'
-          where m | d == 0    = negate $ shiftR n digitBits
-                  | otherwise = complement $ shiftR n digitBits
-      where !d  = lastDigitIn s n
-            !d' = intToDigitIn s $ (radix - d) .&. digitMask
-  where go p 0 = p
-        go p m = go p (shiftR m digitBits) <> printDigitIn s d
-          where !d = intToDigitIn s $ lastDigitIn s m
-        radix     = radixIn s
-        digitMask = digitMaskIn s
-        digitBits = digitBitsIn s
-        negRadix  = complement $ digitMaskIn s
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Int64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Binary → Word64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Int64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Octal → Word64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Int64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ Hexadecimal → Word64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Int64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ LowHex → Word64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Int64 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word8 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word16 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word32 → p #-}
-{-# SPECIALIZE npBits ∷ Printer p ⇒ UpHex → Word64 → p #-}
-{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Binary → α → p #-}
-{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Octal → α → p #-}
-{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Hexadecimal → α → p #-}
-{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ LowHex → α → p #-}
-{-# SPECIALIZE npBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ UpHex → α → p #-}
-
--- | Print a non-positive binary number in the binary numeral system.
-npBinaryBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-npBinaryBits = npBits Binary
-{-# INLINE npBinaryBits #-}
-
--- | Print a non-positive binary number in the octal numeral system.
-npOctalBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-npOctalBits = npBits Octal
-{-# INLINE npOctalBits #-}
-
--- | Print a non-positive binary number in the hexadecimal numeral system
---   using lower case digits.
-npLowHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-npLowHexBits = npBits LowHex
-{-# INLINE npLowHexBits #-}
-
--- | Print a non-positive binary number in the hexadecimal numeral system
---   using upper case digits.
-npUpHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-npUpHexBits = npBits UpHex
-{-# INLINE npUpHexBits #-}
-
--- | Print a number in the specified positional numeral system.
-number' ∷ (PositionalSystem s, Ord α, Integral α, Printer p)
-        ⇒ s
-        → p -- ^ Prefix for negative values
-        → p -- ^ Prefix for the zero
-        → p -- ^ Prefix for positive values
-        → α → p
-number' s neg z pos n = case compare n 0 of
-    LT → go neg q <> printDigitIn s d
-      where (q, r) = quotRem n (negate radix)
-            !d     = intToDigitIn s $ negate $ fromIntegral r
-    EQ → z <> (printDigitIn s $! intToDigitIn s 0)
-    GT → go pos q <> printDigitIn s d
-      where (q, r) = quotRem n radix
-            !d     = intToDigitIn s $ fromIntegral r
-  where go p 0 = p
-        go p m = go p q <> printDigitIn s d
-          where (q, r) = quotRem m radix
-                !d     = intToDigitIn s $ fromIntegral r
-        radix = radixIn s
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int8 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int16 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int32 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Int64 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word8 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word16 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word32 → p #-}
-{-# SPECIALIZE number' ∷ Printer p ⇒ Decimal → p → p → p → Word64 → p #-}
-{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Binary → p → p → p → α → p #-}
-{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Decimal → p → p → p → α → p #-}
-{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Octal → p → p → p → α → p #-}
-{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ Hexadecimal → p → p → p → α → p #-}
-{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ LowHex → p → p → p → α → p #-}
-{-# SPECIALIZE number' ∷ (Ord α, Integral α, Printer p) ⇒ UpHex → p → p → p → α → p #-}
-
--- | Print a number in the specified positional numeral system. Negative
---   values are prefixed with a minus sign.
-number ∷ (PositionalSystem s, Ord α, Integral α, Printer p) ⇒ s → α → p
-number s = number' s (char7 '-') mempty mempty
-{-# INLINE number #-}
-
--- | Print a number in the binary numeral system.
-binary' ∷ (Ord α, Integral α, Printer p)
-        ⇒ p -- ^ Prefix for negative values
-        → p -- ^ Prefix for the zero
-        → p -- ^ Prefix for positive values
-        → α → p
-binary' = number' Binary
-{-# INLINE binary' #-}
-
--- | Print a number in the binary numeral system. Negative values
---   are prefixed with a minus sign.
-binary ∷ (Ord α, Integral α, Printer p) ⇒ α → p
-binary = number Binary
-{-# INLINE binary #-}
-
--- | Print a number in the octal numeral system.
-octal' ∷ (Ord α, Integral α, Printer p)
-       ⇒ p -- ^ Prefix for negative values
-       → p -- ^ Prefix for the zero
-       → p -- ^ Prefix for positive values
-       → α → p
-octal' = number' Octal
-{-# INLINE octal' #-}
-
--- | Print a number in the octal numeral system. Negative values
---   are prefixed with a minus sign.
-octal ∷ (Ord α, Integral α, Printer p) ⇒ α → p
-octal = number Octal
-{-# INLINE octal #-}
-
--- | Print a number in the decimal numeral system.
-decimal' ∷ (Ord α, Integral α, Printer p)
-         ⇒ p -- ^ Prefix for negative values
-         → p -- ^ Prefix for the zero
-         → p -- ^ Prefix for positive values
-         → α → p
-decimal' = number' Decimal
-{-# INLINE decimal' #-}
-
--- | Print a number in the decimal numeral system. Negative values
---   are prefixed with a minus sign.
-decimal ∷ (Ord α, Integral α, Printer p) ⇒ α → p
-decimal = number Decimal
-{-# INLINE decimal #-}
-
--- | Print a number in the hexadecimal numeral system using lower case
---   digits.
-lowHex' ∷ (Ord α, Integral α, Printer p)
-        ⇒ p -- ^ Prefix for negative values
-        → p -- ^ Prefix for the zero
-        → p -- ^ Prefix for positive values
-        → α → p
-lowHex' = number' LowHex
-{-# INLINE lowHex' #-}
-
--- | Print a number in the hexadecimal numeral system using lower case
---   digits. Negative values are prefixed with a minus sign.
-lowHex ∷ (Ord α, Integral α, Printer p) ⇒ α → p
-lowHex = number LowHex
-{-# INLINE lowHex #-}
-
--- | Print a number in the hexadecimal numeral system using upper case
---   digits.
-upHex' ∷ (Ord α, Integral α, Printer p)
-       ⇒ p -- ^ Prefix for negative values
-       → p -- ^ Prefix for the zero
-       → p -- ^ Prefix for positive values
-       → α → p
-upHex' = number' UpHex
-{-# INLINE upHex' #-}
-
--- | Print a number in the hexadecimal numeral system using upper case
---   digits. Negative values are prefixed with a minus sign.
-upHex ∷ (Ord α, Integral α, Printer p) ⇒ α → p
-upHex = number UpHex
-{-# INLINE upHex #-}
-
--- | Print a binary number in the specified positional numeral system.
-bits' ∷ (BitSystem s, Ord α, Num α, Bits α, Printer p)
-      ⇒ s
-      → p -- ^ Prefix for negative values
-      → p -- ^ Prefix for the zero
-      → p -- ^ Prefix for positive values
-      → α → p
-bits' s neg z pos n = case compare n 0 of
-    LT → case testBit n 0 of
-           True → go neg (shiftR (negate n) digitBits) <> printDigitIn s d
-             where !d = intToDigitIn s $ radix - lastDigitIn s n
-           False → case n > negRadix of
-               True → neg <> printDigitIn s d'
-               False → go neg m <> printDigitIn s d'
-                 where m | d == 0    = negate $ shiftR n digitBits
-                         | otherwise = complement $ shiftR n digitBits
-             where !d  = lastDigitIn s n
-                   !d' = intToDigitIn s $ (radix - d) .&. digitMask
-    EQ → z <> (printDigitIn s $! intToDigitIn s 0)
-    GT → go pos (shiftR n digitBits) <> printDigitIn s d
-      where !d = intToDigitIn s $ lastDigitIn s n
-  where go p 0 = p
-        go p m = go p (shiftR m digitBits) <> printDigitIn s d
-          where !d = intToDigitIn s $ lastDigitIn s m
-        radix     = radixIn s
-        digitMask = digitMaskIn s
-        digitBits = digitBitsIn s
-        negRadix  = complement $ digitMaskIn s
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Int64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Binary → p → p → p → Word64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Int64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Octal → p → p → p → Word64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Int64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ Hexadecimal → p → p → p → Word64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Int64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ LowHex → p → p → p → Word64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Int64 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word8 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word16 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word32 → p #-}
-{-# SPECIALIZE bits' ∷ Printer p ⇒ UpHex → p → p → p → Word64 → p #-}
-{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Binary → p → p → p → α → p #-}
-{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Octal → p → p → p → α → p #-}
-{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ Hexadecimal → p → p → p → α → p #-}
-{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ LowHex → p → p → p → α → p #-}
-{-# SPECIALIZE bits' ∷ (Ord α, Num α, Bits α, Printer p) ⇒ UpHex → p → p → p → α → p #-}
-
--- | Print a binary number in the specified positional numeral system.
---   Negative values are prefixed with a minus sign.
-bits ∷ (BitSystem s, Ord α, Num α, Bits α, Printer p) ⇒ s → α → p
-bits s = bits' s (char7 '-') mempty mempty
-{-# INLINE bits #-}
-
--- | Print a binary number in the binary numeral system.
-binaryBits' ∷ (Ord α, Num α, Bits α, Printer p)
-            ⇒ p -- ^ Prefix for negative values
-            → p -- ^ Prefix for the zero
-            → p -- ^ Prefix for positive values
-            → α → p
-binaryBits' = bits' Binary
-{-# INLINE binaryBits' #-}
-
--- | Print a binary number in the binary numeral system. Negative values
---   are prefixed with a minus sign.
-binaryBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-binaryBits = bits Binary
-{-# INLINE binaryBits #-}
-
--- | Print a binary number in the octal numeral system.
-octalBits' ∷ (Ord α, Num α, Bits α, Printer p)
-           ⇒ p -- ^ Prefix for negative values
-           → p -- ^ Prefix for the zero
-           → p -- ^ Prefix for positive values
-           → α → p
-octalBits' = bits' Octal
-{-# INLINE octalBits' #-}
-
--- | Print a binary number in the octal numeral system. Negative values
---   are prefixed with a minus sign.
-octalBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-octalBits = bits Octal
-{-# INLINE octalBits #-}
-
--- | Print a binary number in the hexadecimal numeral system using lower
---   case digits.
-lowHexBits' ∷ (Ord α, Num α, Bits α, Printer p)
-            ⇒ p -- ^ Prefix for negative values
-            → p -- ^ Prefix for the zero
-            → p -- ^ Prefix for positive values
-            → α → p
-lowHexBits' = bits' LowHex
-{-# INLINE lowHexBits' #-}
-
--- | Print a binary number in the hexadecimal numeral system using lower
---   case digits. Negative values are prefixed with a minus sign.
-lowHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-lowHexBits = bits LowHex
-{-# INLINE lowHexBits #-}
-
--- | Print a binary number in the hexadecimal numeral system using upper
---   case digits.
-upHexBits' ∷ (Ord α, Num α, Bits α, Printer p)
-           ⇒ p -- ^ Prefix for negative values
-           → p -- ^ Prefix for the zero
-           → p -- ^ Prefix for positive values
-           → α → p
-upHexBits' = bits' UpHex
-{-# INLINE upHexBits' #-}
-
--- | Print a binary number in the hexadecimal numeral system using upper
---   case digits. Negative values are prefixed with a minus sign.
-upHexBits ∷ (Ord α, Num α, Bits α, Printer p) ⇒ α → p
-upHexBits = bits UpHex
-{-# INLINE upHexBits #-}
-
-
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -7,9 +7,11 @@
 
 import Data.Word (Word)
 import Data.Char (intToDigit)
+import Data.Ratio (numerator, denominator)
 import Numeric (showIntAtBase)
 import Text.Printf (printf)
-import Text.Printer.Numerals
+import Text.Printer.Integral
+import Text.Printer.Fractional
 
 main = defaultMain
   [ testProperty "nnBinary" $ \w →
@@ -105,6 +107,13 @@
       else if i < 0
            then upHexBits i == (printf "-%X" (negate $ toInteger i) ∷ String)
            else upHexBits i == (printf "%X" i ∷ String)
+  , testProperty "fraction" $ \r →
+      if r == (0 ∷ Rational)
+      then fraction r == "0"
+      else let n = numerator r
+               d = denominator r in
+             fraction r == if d == 1 then show n
+                                     else show n ++ "/" ++ show d
   ]
 
 showBinary i = showIntAtBase 2 intToDigit i ""
diff --git a/text-printer.cabal b/text-printer.cabal
--- a/text-printer.cabal
+++ b/text-printer.cabal
@@ -1,5 +1,5 @@
 Name: text-printer
-Version: 0.3
+Version: 0.4
 Category: Text
 Stability: experimental
 Synopsis: Abstract interface for text builders/printers.
@@ -30,13 +30,14 @@
     bytestring >= 0.10,
     text,
     pretty,
-    text-latin1 >= 0.2,
+    text-latin1 >= 0.3,
     semigroups >= 0.8
   Hs-Source-Dirs: src
   GHC-Options: -Wall
   Exposed-Modules:
     Text.Printer
-    Text.Printer.Numerals
+    Text.Printer.Integral
+    Text.Printer.Fractional
 
 Test-Suite tests
   Default-Language: Haskell2010
