diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013 Mikhail Vorozhtsov
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, 
+  this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright 
+  notice, this list of conditions and the following disclaimer in the 
+  documentation and/or other materials provided with the distribution.
+- Neither the names of the copyright owners nor the names of the 
+  contributors may be used to endorse or promote products derived 
+  from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/data-textual.cabal b/data-textual.cabal
new file mode 100644
--- /dev/null
+++ b/data-textual.cabal
@@ -0,0 +1,57 @@
+Name: data-textual
+Version: 0.1
+Category: Data, Text
+Stability: experimental
+Synopsis: Human-friendly textual representations.
+Description:
+  This package provides an interface for converting between data and its
+  (human-friendly) textual representation.
+
+Homepage: https://github.com/mvv/data-textual
+Bug-Reports: https://github.com/mvv/data-textual/issues
+
+Author: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+Maintainer: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+Copyright: 2013 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+License: BSD3
+License-File: LICENSE
+
+Cabal-Version: >= 1.10.0
+Build-Type: Simple
+
+Source-Repository head
+  Type: git
+  Location: https://github.com/mvv/data-textual.git
+
+Library
+  Default-Language: Haskell2010
+  Build-Depends:
+    base >= 4 && < 5,
+    bytestring >= 0.10,
+    text,
+    tagged >= 0.2,
+    text-latin1 >= 0.2,
+    text-printer >= 0.3,
+    parsers >= 0.5
+  Hs-Source-Dirs: src
+  GHC-Options: -Wall
+  Exposed-Modules:
+    Data.Textual
+    Data.Textual.Numerals
+
+Test-Suite tests
+  Default-Language: Haskell2010
+  Type: exitcode-stdio-1.0
+  Build-Depends:
+    base                       >= 4 && < 5,
+    test-framework             >= 0.5,
+    test-framework-quickcheck2 >= 0.2,
+    QuickCheck                 >= 2.4,
+    text-printer,
+    tagged,
+    parsers,
+    data-textual
+  Hs-Source-Dirs: tests
+  GHC-Options: -Wall
+  Main-Is: Tests.hs
+
diff --git a/src/Data/Textual.hs b/src/Data/Textual.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Textual.hs
@@ -0,0 +1,649 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- | Working with human-friendly (as opposed to the compiler-friendly
+--   'Show' and 'Read') textual representations.
+module Data.Textual
+  (
+  -- * Printing
+    Printable(..)
+  , maybePrint
+  , toString
+  , toText
+  , toLazyText
+  , toAscii
+  , toLazyAscii
+  , toUtf8
+  , toLazyUtf8
+  -- * Parsing
+  , Textual(..)
+  -- ** Standard types proxies
+  , hintType
+  , hintType1
+  , hintTypeArg
+  , aUnit
+  , aChar
+  , anInteger
+  , anInt
+  , anInt8
+  , anInt16
+  , anInt32
+  , anInt64
+  , aWord
+  , aWord8
+  , aWord16
+  , aWord32
+  , aWord64
+  , aFloat
+  , aDouble
+  , aMaybe
+  , aMaybeOf
+  , aList
+  , aListOf
+  -- ** Built-in parser
+  , Parsed(..)
+  , isParsed
+  , isMalformed
+  , maybeParsed
+  , builtInParser
+  , parseString
+  , parseStringAs
+  , parseText
+  , parseTextAs
+  , parseLazyText
+  , parseLazyTextAs
+  , parseAscii
+  , parseAsciiAs
+  , parseLazyAscii
+  , parseLazyAsciiAs
+  , parseUtf8
+  , parseUtf8As
+  , parseLazyUtf8
+  , parseLazyUtf8As
+  , fromString
+  , fromStringAs
+  , fromText
+  , fromTextAs
+  , fromLazyText
+  , fromLazyTextAs
+  , fromAscii
+  , fromAsciiAs
+  , fromLazyAscii
+  , fromLazyAsciiAs
+  , fromUtf8
+  , fromUtf8As
+  , fromLazyUtf8
+  , fromLazyUtf8As
+  ) where
+
+import Prelude hiding (print)
+import Data.Typeable (Typeable)
+import Data.Proxy (Proxy(..))
+import Data.Foldable (Foldable)
+import Data.Traversable (Traversable)
+import Data.Monoid (mempty)
+import Data.Int
+import Data.Word
+import Data.List (stripPrefix)
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Char8 as BS8
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.ByteString.Lazy.Char8 as BL8
+import qualified Data.Text as TS
+import qualified Data.Text.Lazy as TL
+import Data.Text.Lazy.Encoding (decodeUtf8)
+import Data.Textual.Numerals
+import Control.Applicative
+import qualified Text.Printer as TP
+import qualified Text.Printer.Numerals as TP
+import Text.Parser.Combinators (Parsing, (<?>))
+import qualified Text.Parser.Combinators as PC
+import Text.Parser.Char (CharParsing)
+import qualified Text.Parser.Char as PC
+
+-- | The default printer for values of a type.
+class Printable α where
+  print ∷ TP.Printer p ⇒ α → p
+
+instance Printable Char where
+  print = TP.char
+  {-# INLINE print #-}
+
+instance Printable String where
+  print = TP.string
+  {-# INLINE print #-}
+
+instance Printable TS.Text where
+  print = TP.text
+  {-# INLINE print #-}
+
+instance Printable TL.Text where
+  print = TP.lazyText
+  {-# INLINE print #-}
+
+instance Printable Integer where
+  print = TP.decimal
+  {-# INLINE print #-}
+
+instance Printable Int where
+  print = TP.decimal
+  {-# INLINE print #-}
+
+instance Printable Int8 where
+  print = TP.decimal
+  {-# INLINE print #-}
+
+instance Printable Int16 where
+  print = TP.decimal
+  {-# INLINE print #-}
+
+instance Printable Int32 where
+  print = TP.decimal
+  {-# INLINE print #-}
+
+instance Printable Int64 where
+  print = TP.decimal
+  {-# INLINE print #-}
+
+instance Printable Word where
+  print = TP.nnDecimal
+  {-# INLINE print #-}
+
+instance Printable Word8 where
+  print = TP.nnDecimal
+  {-# INLINE print #-}
+
+instance Printable Word16 where
+  print = TP.nnDecimal
+  {-# INLINE print #-}
+
+instance Printable Word32 where
+  print = TP.nnDecimal
+  {-# INLINE print #-}
+
+instance Printable Word64 where
+  print = TP.nnDecimal
+  {-# INLINE print #-}
+
+instance Printable Float where
+  print = TP.string7 . show
+  {-# INLINE print #-}
+
+instance Printable Double where
+  print = TP.string7 . show
+  {-# INLINE print #-}
+
+-- | A shorthand for @'maybe' 'mempty' 'print'@.
+maybePrint ∷ (TP.Printer p, Printable α) ⇒ Maybe α → p
+maybePrint = maybe mempty print
+{-# INLINE maybePrint #-}
+
+-- | A shorthand for @'TP.buildString' . 'print'@.
+toString ∷ Printable α ⇒ α → String
+toString = TP.buildString . print
+{-# INLINE toString #-}
+
+-- | A shorthand for @'TP.buildText' . 'print'@.
+toText ∷ Printable α ⇒ α → TS.Text
+toText = TP.buildText . print
+{-# INLINE toText #-}
+
+-- | A shorthand for @'TP.buildLazyText' . 'print'@.
+toLazyText ∷ Printable α ⇒ α → TL.Text
+toLazyText = TP.buildLazyText . print
+{-# INLINE toLazyText #-}
+
+-- | A shorthand for @'TP.buildAscii' . 'print'@.
+toAscii ∷ Printable α ⇒ α → BS.ByteString
+toAscii = TP.buildAscii . print
+{-# INLINE toAscii #-}
+
+-- | A shorthand for @'TP.buildLazyAscii' . 'print'@.
+toLazyAscii ∷ Printable α ⇒ α → BL.ByteString
+toLazyAscii = TP.buildLazyAscii . print
+{-# INLINE toLazyAscii #-}
+
+-- | A shorthand for @'TP.buildUtf8' . 'print'@.
+toUtf8 ∷ Printable α ⇒ α → BS.ByteString
+toUtf8 = TP.buildUtf8 . print
+{-# INLINE toUtf8 #-}
+
+-- | A shorthand for @'TP.buildLazyUtf8' . 'print'@.
+toLazyUtf8 ∷ Printable α ⇒ α → BL.ByteString
+toLazyUtf8 = TP.buildLazyUtf8 . print
+{-# INLINE toLazyUtf8 #-}
+
+-- | The default parser for values of a type, must satisfy
+--   @
+--     'fromString' ('toString' /x/) = 'Just' /x/
+--   @
+class Printable α ⇒ Textual α where
+  textual ∷ (Monad μ, CharParsing μ) ⇒ μ α
+
+instance Textual Char where
+  textual = PC.anyChar
+  {-# INLINE textual #-}
+
+instance Textual Integer where
+  textual = number Decimal
+  {-# INLINE textual #-}
+
+instance Textual Int where
+  textual = bounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Int8 where
+  textual = bounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Int16 where
+  textual = bounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Int32 where
+  textual = bounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Int64 where
+  textual = bounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Word where
+  textual = nnBounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Word8 where
+  textual = nnBounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Word16 where
+  textual = nnBounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Word32 where
+  textual = nnBounded Decimal
+  {-# INLINE textual #-}
+
+instance Textual Word64 where
+  textual = nnBounded Decimal
+  {-# INLINE textual #-}
+
+-- | Hint the type system about the type of the first argument.
+hintType ∷ α → Proxy α → α
+hintType a _ = a
+{-# INLINE hintType #-}
+
+-- | Hint the type system about the type constructor.
+hintType1 ∷ f α → Proxy f → f α
+hintType1 f _ = f
+{-# INLINE hintType1 #-}
+
+-- | Hint the type system about the type argument. 
+hintTypeArg ∷ f α → Proxy α → f α
+hintTypeArg f _ = f
+{-# INLINE hintTypeArg #-}
+
+infixl 1 `hintType`, `hintType1`, `hintTypeArg`
+
+-- | /()/ proxy value.
+aUnit ∷ Proxy ()
+aUnit = Proxy
+
+-- | 'Char' proxy value.
+aChar ∷ Proxy Char
+aChar = Proxy
+
+-- | 'Integer' proxy value.
+anInteger ∷ Proxy Integer
+anInteger = Proxy
+
+-- | 'Int' proxy value.
+anInt ∷ Proxy Int
+anInt = Proxy
+
+-- | 'Int8' proxy value.
+anInt8 ∷ Proxy Int8
+anInt8 = Proxy
+
+-- | 'Int16' proxy value.
+anInt16 ∷ Proxy Int16
+anInt16 = Proxy
+
+-- | 'Int32' proxy value.
+anInt32 ∷ Proxy Int32
+anInt32 = Proxy
+
+-- | 'Int64' proxy value.
+anInt64 ∷ Proxy Int64
+anInt64 = Proxy
+
+-- | 'Word' proxy value.
+aWord ∷ Proxy Word
+aWord = Proxy
+
+-- | 'Word8' proxy value.
+aWord8 ∷ Proxy Word8
+aWord8 = Proxy
+
+-- | 'Word16' proxy value.
+aWord16 ∷ Proxy Word16
+aWord16 = Proxy
+
+-- | 'Word32' proxy value.
+aWord32 ∷ Proxy Word32
+aWord32 = Proxy
+
+-- | 'Word64' proxy value.
+aWord64 ∷ Proxy Word64
+aWord64 = Proxy
+
+-- | 'Float' proxy value.
+aFloat ∷ Proxy Float
+aFloat = Proxy
+
+-- | 'Double' proxy value.
+aDouble ∷ Proxy Double
+aDouble = Proxy
+
+-- | 'Maybe' proxy value.
+aMaybe ∷ Proxy Maybe
+aMaybe = Proxy
+
+-- | 'Maybe' /α/ proxy value.
+aMaybeOf ∷ Proxy α → Proxy (Maybe α)
+aMaybeOf _ = Proxy
+
+-- | List proxy value.
+aList ∷ Proxy []
+aList = Proxy
+
+-- | List of /α/ proxy value.
+aListOf ∷ Proxy α → Proxy ([α])
+aListOf _ = Proxy
+
+-- | Parsing result.
+data Parsed α = Parsed α
+              | Malformed [String] String
+              deriving (Typeable, Functor, Foldable, Traversable, Eq, Show)
+
+instance Applicative Parsed where
+  pure = Parsed
+  {-# INLINE pure #-}
+  Parsed f       <*> Parsed a       = Parsed (f a)
+  Malformed ls e <*> _              = Malformed ls e
+  _              <*> Malformed ls e = Malformed ls e
+  {-# INLINABLE (<*>) #-}
+
+instance Alternative Parsed where
+  empty = Malformed [] "Alternative.empty"
+  {-# INLINE empty #-}
+  p@(Parsed _) <|> _ = p
+  _            <|> p = p
+  {-# INLINABLE (<|>) #-}
+
+-- | Map 'Parsed' to 'True' and 'Malformed' to 'False'.
+isParsed ∷ Parsed α → Bool
+isParsed (Parsed _) = True
+isParsed _          = False
+
+-- | Map 'Parsed' to 'False' and 'Malformed' to 'True'.
+isMalformed ∷ Parsed α → Bool
+isMalformed (Malformed _ _) = True
+isMalformed _               = False
+
+-- | Map 'Parsed' values to 'Just' and 'Malformed' to 'Nothing'.
+maybeParsed ∷ Parsed α → Maybe α
+maybeParsed (Parsed a) = Just a
+maybeParsed _          = Nothing
+{-# INLINABLE maybeParsed #-}
+
+data Parser α =
+  Parser { runParser ∷ ∀ r
+                     . [String] → Word → String
+                     → ([String] → Word → String → α → Parsed r)
+                     → ([String] → Word → String → String → Parsed r)
+                     → Parsed r }
+
+instance Functor Parser where
+  fmap f p = Parser $ \ls n i c h →
+               runParser p ls n i (\ls' n' i' a → c ls' n' i' (f a)) h
+  {-# INLINE fmap #-}
+
+instance Applicative Parser where
+  pure a = Parser $ \ls n i c _ → c ls n i a
+  {-# INLINE pure #-}
+  p <*> p' = Parser $ \ls n i c h →
+               runParser p ls n i 
+                 (\ls' n' i' f →
+                    runParser p' ls' n' i'
+                      (\ls'' n'' i'' a → c ls'' n'' i'' (f a)) h)
+                 h
+  {-# INLINE (<*>) #-}
+  p *> p' = Parser $ \ls n i c h →
+              runParser p ls n i (\ls' n' i' _ → runParser p' ls' n' i' c h) h
+  {-# INLINE (*>) #-}
+  p <* p' = Parser $ \ls n i c h →
+              runParser p ls n i
+                        (\ls' n' i' a →
+                           runParser p' ls' n' i'
+                                     (\ls'' n'' i'' _ → c ls'' n'' i'' a) h)
+                        h
+  {-# INLINE (<*) #-}
+
+instance Alternative Parser where
+  empty = PC.unexpected "Alternative.empty"
+  {-# INLINE empty #-}
+  p <|> p' = Parser $ \ls n i c h →
+               runParser p ls n i c $ \ls' n' i' e → 
+                 if n' == n then runParser p' ls n' i' c h
+                            else h ls' n' i' e
+  {-# INLINE (<|>) #-}
+
+instance Parsing Parser where
+  try p = Parser $ \ls n i c h →
+            runParser p ls n i c (\ls' _ _ e → h ls' n i e)
+  {-# INLINE try #-}
+  p <?> l = Parser $ \ls n i c h →
+              runParser p (l : ls) n i (\_ n' i' a → c ls n' i' a) h
+  {-# INLINE (<?>) #-}
+  skipMany p = Parser $ \ls n i c h →
+                 runParser p ls n i
+                   (\ls' n' i' _ → runParser (PC.skipMany p) ls' n' i' c h)
+                   (\ls' n' i' _ → c ls' n' i' ())
+  skipSome p = p *> PC.skipMany p
+  {-# INLINE skipSome #-}
+  unexpected e = Parser $ \ls n i _ h → h ls n i e
+  {-# INLINE unexpected #-}
+  eof = Parser $ \ls n i c h → case i of
+                   [] → c ls n i ()
+                   _  → h ls n i "Parsing.eof"
+  {-# INLINABLE eof #-}
+  notFollowedBy p = Parser $ \ls n i c h →
+                      runParser p ls n i
+                                (\_ _ _ _ → h ls n i "Parsing.notFollowedBy")
+                                (\_ _ _ _ → c ls n i ())
+  {-# INLINE notFollowedBy #-}
+
+instance CharParsing Parser where
+  satisfy f = Parser $ \ls n i c h → case i of
+                         x : xs | f x → c ls n' xs x
+                                          where !n' = n + 1
+                         _ → h ls n i "CharParsing.satisfy"
+  {-# INLINABLE satisfy #-}
+  string s = Parser $ \ls n i c h → case stripPrefix s i of
+                        Just i' → c ls n' i' s
+                                    where !n' = n + fromIntegral (length s)
+                        Nothing → h ls n i "CharParsing.string"
+  {-# INLINABLE string #-}
+
+instance Monad Parser where
+  return = pure
+  {-# INLINE return #-}
+  p >>= f = Parser $ \ls n i c h →
+              runParser p ls n i
+                        (\ls' n' i' a → runParser (f a) ls' n' i' c h) h
+  {-# INLINE (>>=) #-}
+  (>>) = (*>)
+  {-# INLINE (>>) #-}
+  fail = PC.unexpected
+  {-# INLINE fail #-}
+
+parse ∷ Parser α → String → Parsed α
+parse p i = runParser p [] 0 i (\_  _ _ a → Parsed a)
+                               (\ls _ _ e → Malformed (reverse ls) e)
+{-# INLINE parse #-}
+
+-- | Use the built-in parser to parse a string. Intended for testing only.
+builtInParser ∷ (∀ μ . (Monad μ, CharParsing μ) ⇒ μ α) → String → Parsed α
+builtInParser p = parse p
+{-# INLINE builtInParser #-}
+
+-- | Parse a 'String' to extract the 'Textual' value.
+parseString ∷ Textual α ⇒ String → Parsed α
+parseString = parse $ textual <* PC.eof
+{-# INLINE parseString #-}
+
+-- | Provide a hint for the type system when using 'parseString'.
+parseStringAs ∷ Textual α ⇒ Proxy α → String → Parsed α
+parseStringAs _ = parseString
+{-# INLINE parseStringAs #-}
+
+-- | Parse a 'TS.Text' to extract the 'Textual' value.
+parseText ∷ Textual α ⇒ TS.Text → Parsed α
+parseText = parseString . TS.unpack
+{-# INLINE parseText #-}
+
+-- | Provide a hint for the type system when using 'parseText'.
+parseTextAs ∷ Textual α ⇒ Proxy α → TS.Text → Parsed α
+parseTextAs _ = parseText
+{-# INLINE parseTextAs #-}
+
+-- | Parse a lazy 'TL.Text' to extract the 'Textual' value.
+parseLazyText ∷ Textual α ⇒ TL.Text → Parsed α
+parseLazyText = parseString . TL.unpack
+{-# INLINE parseLazyText #-}
+
+-- | Provide a hint for the type system when using 'parseLazyText'.
+parseLazyTextAs ∷ Textual α ⇒ Proxy α → TL.Text → Parsed α
+parseLazyTextAs _ = parseLazyText
+{-# INLINE parseLazyTextAs #-}
+
+-- | Decode and parse an ASCII 'BS.ByteString' to extract the 'Textual' value.
+parseAscii ∷ Textual α ⇒ BS.ByteString → Parsed α
+parseAscii = parseString . BS8.unpack
+{-# INLINE parseAscii #-}
+
+-- | Provide a hint for the type system when using 'parseAscii'.
+parseAsciiAs ∷ Textual α ⇒ Proxy α → BS.ByteString → Parsed α
+parseAsciiAs _ = parseAscii
+{-# INLINE parseAsciiAs #-}
+
+-- | Decode and parse a lazy ASCII 'BL.ByteString' to extract
+--   the 'Textual' value.
+parseLazyAscii ∷ Textual α ⇒ BL.ByteString → Parsed α
+parseLazyAscii = parseString . BL8.unpack
+{-# INLINE parseLazyAscii #-}
+
+-- | Provide a hint for the type system when using 'parseLazyAscii'.
+parseLazyAsciiAs ∷ Textual α ⇒ BL.ByteString → Parsed α
+parseLazyAsciiAs = parseString . BL8.unpack
+{-# INLINE parseLazyAsciiAs #-}
+
+-- | Decode and parse a UTF-8 'BS.ByteString' to extract the 'Textual' value.
+parseUtf8 ∷ Textual α ⇒ BS.ByteString → Parsed α
+parseUtf8 = parseLazyText . decodeUtf8 . BL.fromStrict
+{-# INLINE parseUtf8 #-}
+
+-- | Provide a hint for the type system when using 'parseUtf8'.
+parseUtf8As ∷ Textual α ⇒ Proxy α → BS.ByteString → Parsed α
+parseUtf8As _ = parseUtf8
+{-# INLINE parseUtf8As #-}
+
+-- | Decode and parse a lazy UTF-8 'BL.ByteString' to extract
+--   the 'Textual' value.
+parseLazyUtf8 ∷ Textual α ⇒ BL.ByteString → Parsed α
+parseLazyUtf8 = parseLazyText . decodeUtf8
+{-# INLINE parseLazyUtf8 #-}
+
+-- | Provide a hint for the type system when using 'parseLazyUtf8'.
+parseLazyUtf8As ∷ Textual α ⇒ Proxy α → BL.ByteString → Parsed α
+parseLazyUtf8As _ = parseLazyUtf8
+{-# INLINE parseLazyUtf8As #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseString'@
+fromString ∷ Textual α ⇒ String → Maybe α
+fromString = maybeParsed . parseString
+{-# INLINE fromString #-}
+
+-- | Provide a hint for the type system when using 'fromString'.
+fromStringAs ∷ Textual α ⇒ Proxy α → String → Maybe α
+fromStringAs _ = fromString
+{-# INLINE fromStringAs #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseText'@
+fromText ∷ Textual α ⇒ TS.Text → Maybe α
+fromText = maybeParsed . parseText
+{-# INLINE fromText #-}
+
+-- | Provide a hint for the type system when using 'fromText'.
+fromTextAs ∷ Textual α ⇒ Proxy α → TS.Text → Maybe α
+fromTextAs _ = fromText
+{-# INLINE fromTextAs #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseLazyText'@
+fromLazyText ∷ Textual α ⇒ TL.Text → Maybe α
+fromLazyText = maybeParsed . parseLazyText
+{-# INLINE fromLazyText #-}
+
+-- | Provide a hint for the type system when using 'fromLazyText'.
+fromLazyTextAs ∷ Textual α ⇒ Proxy α → TL.Text → Maybe α
+fromLazyTextAs _ = fromLazyText
+{-# INLINE fromLazyTextAs #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseAscii'@
+fromAscii ∷ Textual α ⇒ BS.ByteString → Maybe α
+fromAscii = maybeParsed . parseAscii
+{-# INLINE fromAscii #-}
+
+-- | Provide a hint for the type system when using 'fromAscii'.
+fromAsciiAs ∷ Textual α ⇒ Proxy α → BS.ByteString → Maybe α
+fromAsciiAs _ = fromAscii
+{-# INLINE fromAsciiAs #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseLazyAscii'@
+fromLazyAscii ∷ Textual α ⇒ BL.ByteString → Maybe α
+fromLazyAscii = maybeParsed . parseLazyAscii
+{-# INLINE fromLazyAscii #-}
+
+-- | Provide a hint for the type system when using 'fromLazyAscii'.
+fromLazyAsciiAs ∷ Textual α ⇒ Proxy α → BL.ByteString → Maybe α
+fromLazyAsciiAs _ = fromLazyAscii
+{-# INLINE fromLazyAsciiAs #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseUtf8'@
+fromUtf8 ∷ Textual α ⇒ BS.ByteString → Maybe α
+fromUtf8 = maybeParsed . parseUtf8
+{-# INLINE fromUtf8 #-}
+
+-- | Provide a hint for the type system when using 'fromUtf8'.
+fromUtf8As ∷ Textual α ⇒ Proxy α → BS.ByteString → Maybe α
+fromUtf8As _ = fromUtf8
+{-# INLINE fromUtf8As #-}
+
+-- | A shorthand for @'maybeParsed' . 'parseLazyUtf8'@
+fromLazyUtf8 ∷ Textual α ⇒ BL.ByteString → Maybe α
+fromLazyUtf8 = maybeParsed . parseLazyUtf8
+{-# INLINE fromLazyUtf8 #-}
+
+-- | Provide a hint for the type system when using 'fromLazyUtf8'.
+fromLazyUtf8As ∷ Textual α ⇒ Proxy α → BL.ByteString → Maybe α
+fromLazyUtf8As _ = fromLazyUtf8
+{-# INLINE fromLazyUtf8As #-}
+
diff --git a/src/Data/Textual/Numerals.hs b/src/Data/Textual/Numerals.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Textual/Numerals.hs
@@ -0,0 +1,1641 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- | Parsers for numbers written in positional numeral systems.
+module Data.Textual.Numerals
+  (
+  -- * Positional numeral systems
+    PositionalSystem(..)
+  , BitSystem(..)
+  , Binary(..)
+  , Octal(..)
+  , Decimal(..)
+  , Hexadecimal(..)
+  , LowHex(..)
+  , UpHex(..)
+  -- * Single digits
+  , digitIn
+  , nzDigitIn
+  , binDigit
+  , nzBinDigit
+  , octDigit
+  , nzOctDigit
+  , decDigit
+  , nzDecDigit
+  , hexDigit
+  , nzHexDigit
+  , lowHexDigit
+  , nzLowHexDigit
+  , upHexDigit
+  , nzUpHexDigit
+  -- * Numbers
+  , nonNegative
+  , nnCompact
+  , nnUpTo
+  , nncUpTo
+  , nnBounded
+  , nncBounded
+  , nnBits
+  , nncBits
+  , nnBitsUpTo
+  , nncBitsUpTo
+  , nnbBits
+  , nncbBits
+  , nonPositive
+  , npCompact
+  , npUpTo
+  , npcUpTo
+  , npBounded
+  , npcBounded
+  , npBits
+  , npcBits
+  , npBitsUpTo
+  , npcBitsUpTo
+  , npbBits
+  , npcbBits
+  , Sign(..)
+  , optMinus
+  , optSign
+  , number'
+  , number
+  , compact'
+  , compact
+  , numberUpTo'
+  , numberUpTo
+  , compactUpTo'
+  , compactUpTo
+  , bounded'
+  , bounded
+  , cBounded'
+  , cBounded
+  , bits'
+  , bits
+  , cBits'
+  , cBits
+  , bitsUpTo'
+  , bitsUpTo
+  , cBitsUpTo'
+  , cBitsUpTo
+  , bBits'
+  , bBits
+  , cbBits'
+  , cbBits
+  ) where
+
+import Data.Typeable (Typeable)
+import Data.Int
+import Data.Word
+import Data.Bits (Bits(..))
+import Control.Applicative
+import Text.Printer.Numerals (
+         PositionalSystem(..), BitSystem(..),
+         Binary(..), Octal(..), Decimal(..), Hexadecimal(..),
+         LowHex(..), UpHex(..))
+import Text.Parser.Combinators (Parsing, (<?>))
+import qualified Text.Parser.Combinators as PC
+import Text.Parser.Char (CharParsing)
+import qualified Text.Parser.Char as PC
+
+-- | Parse a digit of the specified positional numeral system.
+digitIn ∷ (PositionalSystem s, Num α, CharParsing μ) ⇒ s → μ α
+digitIn s  =  unsafeFromDigitIn s <$> PC.satisfy (isDigitIn s)
+          <?> systemName s ++ " digit"
+{-# INLINE digitIn #-}
+
+-- | Parse a non-zero digit of the specified positional numeral system.
+nzDigitIn ∷ (PositionalSystem s, Num α, CharParsing μ) ⇒ s → μ α
+nzDigitIn s  =  unsafeFromDigitIn s <$> PC.satisfy (isNzDigitIn s)
+            <?> "non-zero " ++ systemName s ++ " digit"
+{-# INLINE nzDigitIn #-}
+
+-- | Parse a binary digit.
+binDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+binDigit = digitIn Binary
+{-# INLINE binDigit #-}
+
+-- | Parse a non-zero binary digit (/'1'/).
+nzBinDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+nzBinDigit = nzDigitIn Binary
+{-# INLINE nzBinDigit #-}
+
+-- | Parse a decimal digit.
+decDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+decDigit = digitIn Decimal
+{-# INLINE decDigit #-}
+
+-- | Parse a non-zero decimal digit.
+nzDecDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+nzDecDigit = nzDigitIn Decimal
+{-# INLINE nzDecDigit #-}
+
+-- | Parse an octal digit.
+octDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+octDigit = digitIn Octal
+{-# INLINE octDigit #-}
+
+-- | Parse a non-zero octal digit.
+nzOctDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+nzOctDigit = nzDigitIn Octal
+{-# INLINE nzOctDigit #-}
+
+-- | Parse a hexadecimal digit.
+hexDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+hexDigit = digitIn Hexadecimal
+{-# INLINE hexDigit #-}
+
+-- | Parse a non-zero hexadecimal digit.
+nzHexDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+nzHexDigit = nzDigitIn Hexadecimal
+{-# INLINE nzHexDigit #-}
+
+-- | Parse a lower case hexadecimal digit.
+lowHexDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+lowHexDigit = digitIn LowHex
+{-# INLINE lowHexDigit #-}
+
+-- | Parse a non-zero lower case hexadecimal digit.
+nzLowHexDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+nzLowHexDigit = nzDigitIn LowHex
+{-# INLINE nzLowHexDigit #-}
+
+-- | Parse an upper case hexadecimal digit.
+upHexDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+upHexDigit = digitIn UpHex
+{-# INLINE upHexDigit #-}
+
+-- | Parse a non-zero upper case hexadecimal digit.
+nzUpHexDigit ∷ (Num α, CharParsing μ) ⇒ μ α
+nzUpHexDigit = nzDigitIn UpHex
+{-# INLINE nzUpHexDigit #-}
+
+-- | Parse a non-negative number written in the specified positional
+--   numeral system.
+nonNegative ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → μ α
+nonNegative s = digit >>= go <?> systemName s ++ " digits"
+  where go !r = optional digit >>= \case
+                  Just d  → go (r * radix + d)
+                  Nothing → return r
+        radix = radixIn s
+        digit = digitIn s
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE nonNegative ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE nonNegative ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nonNegative ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nonNegative ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE nonNegative ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nonNegative ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nonNegative ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-negative number written in the specified positional
+--   numeral system. Leading zeroes are not allowed.
+nnCompact ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → μ α
+nnCompact s = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+                0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → PC.unexpected "leading zero"
+                      Nothing → return 0
+                r → go $ fromIntegral (r ∷ Word)
+  where go !r = optional digit >>= \case
+                  Just d  → go (r * radix + d)
+                  Nothing → return r
+        radix = radixIn s
+        digit = digitIn s
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE nnCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE nnCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nnCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nnCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE nnCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nnCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nnCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+moreThan ∷ CharParsing μ ⇒ Int → μ α
+moreThan n = PC.unexpected
+           $ "more than " ++ show n ++
+             case n of
+               1 → " digit"
+               _ → " digits"
+{-# INLINE moreThan #-}
+
+-- | Parse a non-negative number written in the specified positional
+--   numeral system (up to /n/ digits).
+nnUpTo ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → Int → μ α
+nnUpTo _ n | n <= 0 = empty
+nnUpTo s n = digit >>= go (n - 1) <?> systemName s ++ " digits"
+  where go 0 !r = optional (PC.satisfy $ isDigitIn s) >>= \case
+                    Just _  → moreThan n
+                    Nothing → return r
+        go l !r = optional digit >>= \case
+                    Just d  → go (l - 1) (r * radix + d)
+                    Nothing → return r
+        radix   = radixIn s
+        digit   = digitIn s
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int8 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int16 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int32 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int64 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word8 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word16 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word32 #-}
+{-# SPECIALIZE nnUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word64 #-}
+{-# SPECIALIZE nnUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE nnUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE nnUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → Int → μ α #-}
+{-# SPECIALIZE nnUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE nnUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE nnUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-negative number written in the specified positional
+--   numeral system (up to /n/ digits). Leading zeroes are not allowed.
+nncUpTo ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → Int → μ α
+nncUpTo _ n | n <= 0 = empty
+nncUpTo s n = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+                0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → PC.unexpected "leading zero"
+                      Nothing → return 0
+                r → go (n - 1) $ fromIntegral (r ∷ Word)
+  where go 0 !r = optional (PC.satisfy $ isDigitIn s) >>= \case
+                    Just _  → moreThan n
+                    Nothing → return r
+        go l !r = optional digit >>= \case
+                    Just d  → go (l - 1) (r * radix + d)
+                    Nothing → return r
+        radix   = radixIn s
+        digit   = digitIn s
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int8 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int16 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int32 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int64 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word8 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word16 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word32 #-}
+{-# SPECIALIZE nncUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word64 #-}
+{-# SPECIALIZE nncUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE nncUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE nncUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → Int → μ α #-}
+{-# SPECIALIZE nncUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE nncUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE nncUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-negative number written in the specified positional
+--   numeral system, failing on overflow.
+nnBounded ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+             Monad μ, CharParsing μ) ⇒ s → μ α
+nnBounded s = digit >>= go <?> systemName s ++ " digits"
+  where (q, r) = quotRem maxBound radix
+        go !n  = optional digit >>= \case
+                   Just n1 → if n < q || (n == q && n1 <= r)
+                             then go (n * radix + n1)
+                             else fail "out of bounds"
+                   Nothing → return n
+        radix  = radixIn s
+        digit  = digitIn s
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE nnBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE nnBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nnBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nnBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE nnBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nnBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nnBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-negative number written in the specified positional
+--   numeral system, failing on overflow. Leading zeroes are not allowed.
+nncBounded ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+              Monad μ, CharParsing μ) ⇒ s → μ α
+nncBounded s = (<?> systemName s ++ " digits") $ digit >>= \case
+                 0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                       Just _  → PC.unexpected "leading zero"
+                       Nothing → return 0
+                 n → go n
+  where (q, r) = quotRem maxBound radix
+        go !n  = optional digit >>= \case
+                   Just d  → if n < q || (n == q && d <= r)
+                             then go (n * radix + d)
+                             else fail "out of bounds"
+                   Nothing → return n
+        radix  = radixIn s
+        digit  = digitIn s
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE nncBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE nncBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nncBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nncBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE nncBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nncBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nncBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-negative binary number written in the specified
+--   positional numeral system.
+nnBits ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ) ⇒ s → μ α
+nnBits s = digit >>= go <?> systemName s ++ " digits"
+  where go !r     = optional digit >>= \case
+                      Just d  → go ((r `shiftL` digitBits) .|. d)
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE nnBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nnBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-negative binary number written in the specified
+--   positional numeral system. Leading zeroes are not allowed.
+nncBits ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ) ⇒ s → μ α
+nncBits s = (<?> systemName s ++ " digits") $ digit >>= \case
+              0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                    Just _  → PC.unexpected "leading zero"
+                    Nothing → return 0 
+              r → go r
+  where go !r     = optional digit >>= \case
+                      Just d  → go ((r `shiftL` digitBits) .|. d)
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE nncBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE nncBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nncBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nncBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nncBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nncBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-negative binary number written in the specified
+--   positional numeral system (up to /n/ digits).
+nnBitsUpTo ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+           ⇒ s → Int → μ α
+nnBitsUpTo _ n | n <= 0 = empty
+nnBitsUpTo s n = digit >>= go (n - 1) <?> systemName s ++ " digits"
+  where go 0 !r   = optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → moreThan n
+                      Nothing → return r
+        go l !r   = optional digit >>= \case
+                      Just d  → go (l - 1) ((r `shiftL` digitBits) .|. d)
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word8 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word16 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word32 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word64 #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE nnBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-negative binary number written in the specified
+--   positional numeral system (up to /n/ digits). Leading zeroes are not
+--   allowed.
+nncBitsUpTo ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+            ⇒ s → Int → μ α
+nncBitsUpTo _ n | n <= 0 = empty
+nncBitsUpTo s n = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+                    0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                          Just _  → PC.unexpected "leading zero"
+                          Nothing → return 0 
+                    r → go (n - 1) $ fromIntegral (r ∷ Word)
+  where go 0 !r   = optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → moreThan n
+                      Nothing → return r
+        go l !r   = optional digit >>= \case
+                      Just d  → go (l - 1) ((r `shiftL` digitBits) .|. d)
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word8 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word16 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word32 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word64 #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE nncBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-negative binary number written in the specified
+--   positional numeral system, failing on overflow.
+nnbBits ∷ (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+           Monad μ, CharParsing μ)
+        ⇒ s → μ α
+nnbBits s = digit >>= go <?> systemName s ++ " digits"
+  where q = maxBound `shiftR` digitBits
+        r = maxBound .&. digitMaskIn s
+        go !n = optional digit >>= \case
+                  Just d  → if n < q || (n == q && d <= r)
+                            then go ((n `shiftL` digitBits) .|. d)
+                            else fail "out of bounds"
+                  Nothing → return n
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE nnbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE nnbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nnbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nnbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nnbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nnbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-negative binary number written in the specified
+--   positional numeral system, failing on overflow. Leading zeroes are not
+--   allowed.
+nncbBits ∷ (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+            Monad μ, CharParsing μ)
+         ⇒ s → μ α
+nncbBits s = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+               0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                     Just _  → PC.unexpected "leading zero"
+                     Nothing → return 0
+               n → go $ fromIntegral (n ∷ Word)
+  where q = maxBound `shiftR` digitBits
+        r = maxBound .&. digitMaskIn s
+        go !n = optional digit >>= \case
+                  Just d  → if n < q || (n == q && d <= r)
+                            then go ((n `shiftL` digitBits) .|. d)
+                            else fail "out of bounds"
+                  Nothing → return n
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE nncbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE nncbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nncbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nncbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nncbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nncbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive number written in the specified positional
+--   numeral system. For example, parsing \"123\" as a decimal would produce
+--   /-123/, not /123/.
+nonPositive ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → μ α
+nonPositive s = (<?> systemName s ++ " digits") $ do
+                  r ← digitIn s
+                  go $ fromIntegral $ negate (r ∷ Int)
+  where go !r = optional digit >>= \case
+                  Just d  → go (r * radix - d)
+                  Nothing → return r
+        radix = radixIn s
+        digit = digitIn s
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE nonPositive ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE nonPositive ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE nonPositive ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE nonPositive ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE nonPositive ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE nonPositive ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE nonPositive ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive number written in the specified positional
+--   numeral system. Leading zeroes are not allowed.
+npCompact ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → μ α
+npCompact s = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+                0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → PC.unexpected "leading zero"
+                      Nothing → return 0
+                r → go $ fromIntegral $ negate (r ∷ Int)
+  where go !r = optional digit >>= \case
+                  Just d  → go (r * radix - d)
+                  Nothing → return r
+        radix = radixIn s
+        digit = digitIn s
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE npCompact ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE npCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE npCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npCompact ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive number written in the specified positional
+--   numeral system (up to /n/ digits).
+npUpTo ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → Int → μ α
+npUpTo _ n | n <= 0 = empty
+npUpTo s n = (<?> systemName s ++ " digits") $ do
+               r ← digitIn s
+               go (n - 1) $ fromIntegral $ negate (r ∷ Int)
+  where go 0 !r = optional (PC.satisfy $ isDigitIn s) >>= \case
+                    Just _  → moreThan n
+                    Nothing → return r
+        go l !r = optional digit >>= \case
+                    Just d  → go (l - 1) (r * radix - d)
+                    Nothing → return r
+        radix   = radixIn s
+        digit   = digitIn s
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int8 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int16 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int32 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int64 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word8 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word16 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word32 #-}
+{-# SPECIALIZE npUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word64 #-}
+{-# SPECIALIZE npUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE npUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE npUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → Int → μ α #-}
+{-# SPECIALIZE npUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE npUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE npUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-positive number written in the specified positional
+--   numeral system (up to /n/ digits). Leading zeroes are not allowed.
+npcUpTo ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → Int → μ α
+npcUpTo _ n | n <= 0 = empty
+npcUpTo s n = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+                0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → PC.unexpected "leading zero"
+                      Nothing → return 0
+                r → go (n - 1) $ fromIntegral $ negate (r ∷ Int)
+  where go 0 !r = optional (PC.satisfy $ isDigitIn s) >>= \case
+                    Just _  → moreThan n
+                    Nothing → return r
+        go l !r = optional digit >>= \case
+                    Just d  → go (l - 1) (r * radix - d)
+                    Nothing → return r
+        radix   = radixIn s
+        digit   = digitIn s
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int8 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int16 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int32 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Int64 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word8 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word16 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word32 #-}
+{-# SPECIALIZE npcUpTo ∷ (Monad μ, CharParsing μ) ⇒ Decimal → Int → μ Word64 #-}
+{-# SPECIALIZE npcUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE npcUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE npcUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Decimal → Int → μ α #-}
+{-# SPECIALIZE npcUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE npcUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE npcUpTo ∷ (Num α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-positive number written in the specified positional
+--   numeral system, failing on overflow.
+npBounded ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+             Monad μ, CharParsing μ)
+          ⇒ s → μ α
+npBounded s = (<?> systemName s ++ " digits") $ do
+                n ← digitIn s
+                go $ fromIntegral $ negate (n ∷ Int)
+  where (q, r1) = quotRem minBound radix
+        !r      = negate r1
+        go !n   = optional digit >>= \case
+                    Just d  → if n > q || (n == q && d <= r)
+                              then go (n * radix - d)
+                              else fail "out of bounds"
+                    Nothing → return n
+        radix   = radixIn s
+        digit   = digitIn s
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE npBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE npBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE npBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive number written in the specified positional
+--   numeral system, failing on overflow. Leading zeroes are not allowed.
+npcBounded ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+              Monad μ, CharParsing μ)
+           ⇒ s → μ α
+npcBounded s = (<?> systemName s ++ " digits") $ digitIn s >>= \case
+                 0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                       Just _  → PC.unexpected "leading zero"
+                       Nothing → return 0
+                 n → go $ fromIntegral $ negate (n ∷ Int)
+  where (q, r1) = quotRem minBound radix
+        !r      = negate r1
+        go !n   = optional digit >>= \case
+                    Just d  → if n > q || (n == q && d <= r)
+                              then go (n * radix - d)
+                              else fail "out of bounds"
+                    Nothing → return n
+        radix   = radixIn s
+        digit   = digitIn s
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int8 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int16 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int32 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Int64 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word8 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word16 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word32 #-}
+{-# SPECIALIZE npcBounded ∷ (Monad μ, CharParsing μ) ⇒ Decimal → μ Word64 #-}
+{-# SPECIALIZE npcBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npcBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npcBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Decimal → μ α #-}
+{-# SPECIALIZE npcBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npcBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npcBounded ∷ (Ord α, Bounded α, Integral α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive two\'s complement binary number written in
+--   the specified positional numeral system.
+npBits ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ) ⇒ s → μ α
+npBits s = (<?> systemName s ++ " digits") $ do
+             r ← digit
+             go $ fromIntegral $ negate (r ∷ Int)
+  where go !r     = optional digit >>= \case
+                      Just d1 → go ((r `shiftL` digitBits) + d)
+                        where !d = fromIntegral $ negate d1
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE npBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE npBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive two\'s complement binary number written in
+--   the specified positional numeral system (up to /n/ digits).
+npBitsUpTo ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+           ⇒ s → Int → μ α
+npBitsUpTo _ n | n <= 0 = empty
+npBitsUpTo s n = (<?> systemName s ++ " digits") $ do
+                   r ← digit
+                   go (n - 1) $ fromIntegral $ negate (r ∷ Int)
+  where go 0 !r   = optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → moreThan n
+                      Nothing → return r
+        go l !r   = optional digit >>= \case
+                      Just d1 → go (l - 1) ((r `shiftL` digitBits) + d)
+                        where !d = fromIntegral $ negate d1
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word8 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word16 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word32 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word64 #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE npBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-positive two\'s complement binary number written in
+--   the specified positional numeral system. Leading zeroes are not allowed.
+npcBits ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ) ⇒ s → μ α
+npcBits s = (<?> systemName s ++ " digits") $ digit >>= \case
+              0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                    Just _  → PC.unexpected "leading zero"
+                    Nothing → return 0
+              r → go $ fromIntegral $ negate (r ∷ Int)
+  where go !r     = optional digit >>= \case
+                      Just d1 → go ((r `shiftL` digitBits) + d)
+                        where !d = fromIntegral $ negate d1
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE npcBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE npcBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npcBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npcBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npcBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npcBits ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive two\'s complement binary number written in
+--   the specified positional numeral system (up to /n/ digits).
+--   Leading zeroes are not allowed.
+npcBitsUpTo ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+            ⇒ s → Int → μ α
+npcBitsUpTo _ n | n <= 0 = empty
+npcBitsUpTo s n = (<?> systemName s ++ " digits") $ digit >>= \case
+                    0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                          Just _  → PC.unexpected "leading zero"
+                          Nothing → return 0
+                    r → go (n - 1) $ fromIntegral $ negate (r ∷ Int)
+  where go 0 !r   = optional (PC.satisfy $ isDigitIn s) >>= \case
+                      Just _  → moreThan n
+                      Nothing → return r
+        go l !r   = optional digit >>= \case
+                      Just d1 → go (l - 1) ((r `shiftL` digitBits) + d)
+                        where !d = fromIntegral $ negate d1
+                      Nothing → return r
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Int64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Binary → Int → μ Word64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Int64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Octal → Int → μ Word64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Int64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ Word64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Int64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ LowHex → Int → μ Word64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Int64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word8 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word16 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word32 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Monad μ, CharParsing μ) ⇒ UpHex → Int → μ Word64 #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → Int → μ α #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → Int → μ α #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → Int → μ α #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → Int → μ α #-}
+{-# SPECIALIZE npcBitsUpTo ∷ (Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → Int → μ α #-}
+
+-- | Parse a non-positive two\'s complement binary number written in
+--   the specified positional numeral system, failing on overflow.
+npbBits ∷ ∀ s μ α
+        . (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+           Monad μ, CharParsing μ)
+        ⇒ s → μ α
+npbBits s = (<?> systemName s ++ " digits") $ do
+              n ← digit
+              go $ fromIntegral $ negate (n ∷ Int)
+  where q1 = minBound `shiftR` digitBits
+        r  = negate (lastDigitIn s (minBound ∷ α)) .&. digitMaskIn s
+        q  = if r == 0 then q1 else q1 + 1
+        go !n     = optional digit >>= \case
+                      Just d1 → if n > q || (n == q && d1 <= r)
+                                then go ((n `shiftL` digitBits) + d)
+                                else fail "out of bounds"
+                        where !d = fromIntegral $ negate d1
+                      Nothing → return n
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE npbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE npbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Parse a non-positive two\'s complement binary number written in
+--   the specified positional numeral system, failing on overflow.
+--   Leading zeroes are not allowed.
+npcbBits ∷ ∀ s μ α
+         . (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+            Monad μ, CharParsing μ)
+        ⇒ s → μ α
+npcbBits s = (<?> systemName s ++ " digits") $ digit >>= \case
+               0 → optional (PC.satisfy $ isDigitIn s) >>= \case
+                     Just _  → PC.unexpected "leading zero"
+                     Nothing → return 0
+               n → go $ fromIntegral $ negate (n ∷ Int)
+  where q1 = minBound `shiftR` digitBits
+        r  = negate (lastDigitIn s (minBound ∷ α)) .&. digitMaskIn s
+        q  = if r == 0 then q1 else q1 + 1
+        go !n     = optional digit >>= \case
+                      Just d1 → if n > q || (n == q && d1 <= r)
+                                then go ((n `shiftL` digitBits) + d)
+                                else fail "out of bounds"
+                        where !d = fromIntegral $ negate d1
+                      Nothing → return n
+        digitBits = digitBitsIn s
+        digit     = digitIn s
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Int64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Binary → μ Word64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Int64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Octal → μ Word64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Int64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ Hexadecimal → μ Word64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Int64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ LowHex → μ Word64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Int64 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word8 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word16 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word32 #-}
+{-# SPECIALIZE npcbBits ∷ (Monad μ, CharParsing μ) ⇒ UpHex → μ Word64 #-}
+{-# SPECIALIZE npcbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Binary → μ α #-}
+{-# SPECIALIZE npcbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Octal → μ α #-}
+{-# SPECIALIZE npcbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ Hexadecimal → μ α #-}
+{-# SPECIALIZE npcbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ LowHex → μ α #-}
+{-# SPECIALIZE npcbBits ∷ (Ord α, Bounded α, Num α, Bits α, Monad μ, CharParsing μ) ⇒ UpHex → μ α #-}
+
+-- | Sign of a number.
+data Sign = NonNegative | NonPositive
+            deriving (Typeable, Eq, Show, Read)
+
+-- | Optional minus sign.
+optMinus ∷ CharParsing μ ⇒ μ Sign
+optMinus  =  (pure NonPositive <* PC.char '-') <|> pure NonNegative
+         <?> "optional minus sign"
+{-# INLINE optMinus #-}
+
+-- | Optional minus or plus sign.
+optSign ∷ CharParsing μ ⇒ μ Sign
+optSign  =  (pure NonPositive <* PC.char '-')
+        <|> (pure NonNegative <* PC.char '+')
+        <|> pure NonNegative
+        <?> "optional sign"
+{-# INLINABLE optSign #-}
+
+-- | Parse a number written in the specified positional numeral system.
+--   The supplied parser is used to determine the sign of the number.
+number' ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ)
+        ⇒ μ Sign → s → μ α
+number' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nonNegative s
+  NonPositive → nonPositive s
+{-# INLINE number' #-}
+
+-- | A shorthand for 'number\'' 'optMinus'.
+number ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → μ α
+number = number' optMinus
+{-# INLINE number #-}
+
+-- | Parse a number written in the specified positional numeral system.
+--   The supplied parser is used to determine the sign of the number.
+--   Leading zeroes are not allowed.
+compact' ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ)
+         ⇒ μ Sign → s → μ α
+compact' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nnCompact s
+  NonPositive → npCompact s
+{-# INLINE compact' #-}
+
+-- | A shorthand for 'compact\'' 'optMinus'.
+compact ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ) ⇒ s → μ α
+compact = compact' optMinus
+{-# INLINE compact #-}
+
+-- | Parse a number written in the specified positional numeral system
+--   (up to /n/ digits). The supplied parser is used to determine the sign of
+--   the number.
+numberUpTo' ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ)
+            ⇒ μ Sign → s → Int → μ α
+numberUpTo' neg s n = (<?> systemName s) $ neg >>= \case
+  NonNegative → nnUpTo s n
+  NonPositive → npUpTo s n
+{-# INLINE numberUpTo' #-}
+
+-- | A shorthand for 'numberUpTo\'' 'optMinus'.
+numberUpTo ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ)
+           ⇒ s → Int → μ α
+numberUpTo = numberUpTo' optMinus
+{-# INLINE numberUpTo #-}
+
+-- | Parse a number written in the specified positional numeral system
+--   (up to /n/ digits). The supplied parser is used to determine the sign of
+--   the number. Leading zeroes are not allowed.
+compactUpTo' ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ)
+             ⇒ μ Sign → s → Int → μ α
+compactUpTo' neg s n = (<?> systemName s) $ neg >>= \case
+  NonNegative → nncUpTo s n
+  NonPositive → npcUpTo s n
+{-# INLINE compactUpTo' #-}
+
+-- | A shorthand for 'compactUpTo\'' 'optMinus'.
+compactUpTo ∷ (PositionalSystem s, Num α, Monad μ, CharParsing μ)
+           ⇒ s → Int → μ α
+compactUpTo = compactUpTo' optMinus
+{-# INLINE compactUpTo #-}
+
+-- | Parse a number written in the specified positional numeral system,
+--   failing on overflow. The supplied parser is used to determine the sign
+--   of the number.
+bounded' ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+            Monad μ, CharParsing μ)
+         ⇒ μ Sign → s → μ α
+bounded' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nnBounded s
+  NonPositive → npBounded s
+{-# INLINE bounded' #-}
+
+-- | A shorthand for 'bounded\'' 'optMinus'.
+bounded ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+           Monad μ, CharParsing μ) ⇒ s → μ α
+bounded = bounded' optMinus
+{-# INLINE bounded #-}
+
+-- | Parse a number written in the specified positional numeral system,
+--   failing on overflow. The supplied parser is used to determine the sign
+--   of the number. Leading zeroes are not allowed.
+cBounded' ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+             Monad μ, CharParsing μ)
+          ⇒ μ Sign → s → μ α
+cBounded' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nncBounded s
+  NonPositive → npcBounded s
+{-# INLINE cBounded' #-}
+
+-- | A shorthand for 'cBounded\'' 'optMinus'.
+cBounded ∷ (PositionalSystem s, Ord α, Bounded α, Integral α,
+            Monad μ, CharParsing μ) ⇒ s → μ α
+cBounded = cBounded' optMinus
+{-# INLINE cBounded #-}
+
+-- | Parse a (two\'s complement) binary number written in the specified
+--   positional numeral system. The supplied parser is used to determine
+--   the sign of the number.
+bits' ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+      ⇒ μ Sign → s → μ α
+bits' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nnBits s
+  NonPositive → npBits s
+{-# INLINE bits' #-}
+
+-- | A shorthand for 'bits\'' 'optMinus'.
+bits ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ) ⇒ s → μ α
+bits = bits' optMinus
+{-# INLINE bits #-}
+
+-- | Parse a (two\'s complement) binary number written in the specified
+--   positional numeral system. The supplied parser is used to determine
+--   the sign of the number. Leading zeroes are not allowed.
+cBits' ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+       ⇒ μ Sign → s → μ α
+cBits' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nncBits s
+  NonPositive → npcBits s
+{-# INLINE cBits' #-}
+
+-- | A shorthand for 'cBits\'' 'optMinus'.
+cBits ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ) ⇒ s → μ α
+cBits = cBits' optMinus
+{-# INLINE cBits #-}
+
+-- | Parse a (two\'s complement) binary number written in the specified
+--   positional numeral system (up to /n/ digits). The supplied parser is
+--   used to determine the sign of the number.
+bitsUpTo' ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+          ⇒ μ Sign → s → Int → μ α
+bitsUpTo' neg s n = (<?> systemName s) $ neg >>= \case
+  NonNegative → nnBitsUpTo s n
+  NonPositive → npBitsUpTo s n
+{-# INLINE bitsUpTo' #-}
+
+-- | A shorthand for 'bitsUpTo\'' 'optMinus'.
+bitsUpTo ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+         ⇒ s → Int → μ α
+bitsUpTo = bitsUpTo' optMinus
+{-# INLINE bitsUpTo #-}
+
+-- | Parse a (two\'s complement) binary number written in the specified
+--   positional numeral system (up to /n/ digits). The supplied parser is
+--   used to determine the sign of the number. Leading zeroes are not
+--   allowed.
+cBitsUpTo' ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+           ⇒ μ Sign → s → Int → μ α
+cBitsUpTo' neg s n = (<?> systemName s) $ neg >>= \case
+  NonNegative → nncBitsUpTo s n
+  NonPositive → npcBitsUpTo s n
+{-# INLINE cBitsUpTo' #-}
+
+-- | A shorthand for 'cBitsUpTo\'' 'optMinus'.
+cBitsUpTo ∷ (BitSystem s, Num α, Bits α, Monad μ, CharParsing μ)
+          ⇒ s → Int → μ α
+cBitsUpTo = cBitsUpTo' optMinus
+{-# INLINE cBitsUpTo #-}
+
+-- | Parse a (two\'s complement) binary number written in the specified
+--   positional numeral system, failing on overflow. The supplied parser is
+--   used to determine the sign of the number.
+bBits' ∷ (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+          Monad μ, CharParsing μ)
+       ⇒ μ Sign → s → μ α
+bBits' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nnbBits s
+  NonPositive → npbBits s
+{-# INLINE bBits' #-}
+
+-- | A shorthand for 'bBits\'' 'optMinus'.
+bBits ∷ (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+         Monad μ, CharParsing μ)
+      ⇒ s → μ α
+bBits = bBits' optMinus
+{-# INLINE bBits #-}
+
+-- | Parse a (two\'s complement) binary number written in the specified
+--   positional numeral system, failing on overflow. The supplied parser is
+--   used to determine the sign of the number. Leading zeroes are not
+--   allowed.
+cbBits' ∷ (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+           Monad μ, CharParsing μ)
+        ⇒ μ Sign → s → μ α
+cbBits' neg s = (<?> systemName s) $ neg >>= \case
+  NonNegative → nncbBits s
+  NonPositive → npcbBits s
+{-# INLINE cbBits' #-}
+
+-- | A shorthand for 'cbBits\'' 'optMinus'.
+cbBits ∷ (BitSystem s, Ord α, Bounded α, Num α, Bits α,
+          Monad μ, CharParsing μ)
+       ⇒ s → μ α
+cbBits = cbBits' optMinus
+{-# INLINE cbBits #-}
+
diff --git a/tests/Tests.hs b/tests/Tests.hs
new file mode 100644
--- /dev/null
+++ b/tests/Tests.hs
@@ -0,0 +1,288 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE Rank2Types #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+
+import Test.Framework (defaultMain)
+import Test.Framework.Providers.QuickCheck2 (testProperty)
+import Test.QuickCheck ((==>))
+
+import Data.Word (Word)
+import Data.Proxy (Proxy)
+import Data.Textual
+import Data.Textual.Numerals
+import Control.Applicative
+import Text.Printer (StringBuilder)
+import qualified Text.Printer as TP
+import qualified Text.Printer.Numerals as TP
+import Text.Parser.Combinators as PC
+import Text.Parser.Char (CharParsing)
+
+main = defaultMain
+  [ testProperty "nonNegative Binary Int" $ \i →
+      (i >= 0) ==>
+        parse (nonNegative Binary) (TP.binary i) == Parsed (i ∷ Int)
+  , testProperty "nonNegative Binary Word" $ \w →
+      parse (nonNegative Binary) (TP.binary w) == Parsed (w ∷ Word)
+  , testProperty "nonNegative Decimal Int" $ \i →
+      (i >= 0) ==>
+        parse (nonNegative Decimal) (TP.decimal i) == Parsed (i ∷ Int)
+  , testProperty "nonNegative Decimal Word" $ \w →
+      parse (nonNegative Decimal) (TP.decimal w) == Parsed (w ∷ Word)
+  , testProperty "nonNegative Hexadecimal Int" $ \i →
+      (i >= 0) ==>
+        parse (nonNegative Hexadecimal) (TP.upHex i) == Parsed (i ∷ Int)
+  , testProperty "nonNegative Hexadecimal Word" $ \w →
+      parse (nonNegative Hexadecimal) (TP.lowHex w) == Parsed (w ∷ Word)
+  , testProperty "nnCompact Decimal" $ \w →
+      parse (nnCompact Decimal) (TP.nnDecimal w) == Parsed (w ∷ Word)
+  , testProperty "nnCompact Decimal fails on \"00\"" $
+      isMalformed $ parseAs aWord (nnCompact Decimal) "00"
+  , testProperty "nnCompact Decimal fails on \"01\"" $
+      isMalformed $ parseAs aWord (nnCompact Decimal) "01"
+  , testProperty "nnUpTo Decimal 3" $ \w →
+      case parse (nnUpTo Decimal 3) (TP.nnDecimal w) of
+        Malformed _ _ | w >= 1000        → True
+        Parsed w'     | w' == (w ∷ Word) → True 
+        _                                → False
+  , testProperty "nncUpTo Decimal 3" $ \w →
+      case parse (nncUpTo Decimal 3) (TP.nnDecimal w) of
+        Malformed _ _ | w >= 1000        → True
+        Parsed w'     | w' == (w ∷ Word) → True 
+        _                                → False
+  , testProperty "nncUpTo Decimal fails on \"00\"" $
+      isMalformed $ parseAs aWord (nncUpTo Decimal 3) "00"
+  , testProperty "nncUpTo Decimal fails on \"01\"" $
+      isMalformed $ parseAs aWord (nncUpTo Decimal 3) "01"
+  , testProperty "nnBounded Hexadecimal Word" $ \w →
+      parse (nnBounded Hexadecimal) (TP.nnUpHex w) == Parsed (w ∷ Word)
+  , testProperty "nnBounded Hexadecimal Int" $ \i →
+      (i >= 0) ==>
+        parse (nnBounded Hexadecimal) (TP.nnUpHex i) == Parsed (i ∷ Int)
+  , testProperty "nnBounded Hexadecimal Word fails on overflow" $
+      isMalformed $ parseAs aWord (nnBounded Hexadecimal)
+                            (TP.nnUpHex $ toInteger (maxBound ∷ Word) + 1)
+  , testProperty "nnBounded Hexadecimal Int fails on overflow" $
+      isMalformed $ parseAs anInt (nnBounded Hexadecimal)
+                            (TP.nnUpHex $ toInteger (maxBound ∷ Int) + 1)
+  , testProperty "nncBounded Decimal fails on \"00\"" $
+      isMalformed $ parseAs aWord (nncBounded Decimal) "00"
+  , testProperty "nncBounded Decimal fails on \"01\"" $
+      isMalformed $ parseAs aWord (nncBounded Decimal) "01"
+  , testProperty "nnBits Binary Int" $ \i →
+      (i >= 0) ==>
+        parse (nnBits Binary) (TP.binaryBits i) == Parsed (i ∷ Int)
+  , testProperty "nnBits Binary Word" $ \w →
+      parse (nnBits Binary) (TP.nnBinaryBits w) == Parsed (w ∷ Word)
+  , testProperty "nnBits Hexadecimal Int" $ \i →
+      (i >= 0) ==>
+        parse (nnBits Hexadecimal) (TP.upHex i) == Parsed (i ∷ Int)
+  , testProperty "nnBits Hexadecimal Word" $ \w →
+      parse (nnBits Hexadecimal) (TP.nnLowHex w) == Parsed (w ∷ Word)
+  , testProperty "nncBits Octal" $ \w →
+      parse (nncBits Octal) (TP.nnOctal w) == Parsed (w ∷ Word)
+  , testProperty "nncBits Octal fails on \"00\"" $
+      isMalformed $ parseAs aWord (nncBits Octal) "00"
+  , testProperty "nncBits Octal fails on \"01\"" $
+      isMalformed $ parseAs aWord (nncBits Octal) "01"
+  , testProperty "nnBitsUpTo Hexadecimal 3" $ \w →
+      case parse (nnBitsUpTo Hexadecimal 3) (TP.nnLowHex w) of
+        Malformed _ _ | w >= 0x1000      → True
+        Parsed w'     | w' == (w ∷ Word) → True 
+        _                                → False
+  , testProperty "nncBitsUpTo Octal 3" $ \w →
+      case parse (nncBitsUpTo Octal 3) (TP.nnOctal w) of
+        Malformed _ _ | w >= 0o1000      → True
+        Parsed w'     | w' == (w ∷ Word) → True 
+        _                                → False
+  , testProperty "nncBitsUpTo LowHex fails on \"00\"" $
+      isMalformed $ parseAs aWord (nncBitsUpTo LowHex 3) "00"
+  , testProperty "nncBitsUpTo LowHex fails on \"01\"" $
+      isMalformed $ parseAs aWord (nncBitsUpTo LowHex 3) "01"
+  , testProperty "nnbBits Hexadecimal Word" $ \w →
+      parse (nnbBits Hexadecimal) (TP.nnUpHex w) == Parsed (w ∷ Word)
+  , testProperty "nnbBits Hexadecimal Int" $ \i →
+      (i >= 0) ==>
+        parse (nnbBits Hexadecimal) (TP.nnLowHexBits i) == Parsed (i ∷ Int)
+  , testProperty "nnbBits Hexadecimal Word fails on overflow" $
+      isMalformed $ parseAs aWord (nnbBits Hexadecimal)
+                            (TP.nnUpHexBits $ toInteger (maxBound ∷ Word) + 1)
+  , testProperty "nnbBits Hexadecimal Int fails on overflow" $
+      isMalformed $ parseAs anInt (nnbBits Hexadecimal)
+                            (TP.nnUpHexBits $ toInteger (maxBound ∷ Int) + 1)
+  , testProperty "nncbBits Octal fails on \"00\"" $
+      isMalformed $ parseAs aWord (nncbBits Octal) "00"
+  , testProperty "nncbBits Octal fails on \"01\"" $
+      isMalformed $ parseAs aWord (nncbBits Octal) "01"
+  , testProperty "nonPositive Binary" $ \i →
+      (i <= 0) ==>
+        parse (nonPositive Binary) (TP.npBinary i) == Parsed (i ∷ Int)
+  , testProperty "nonPositive Decimal" $ \i →
+      (i <= 0) ==>
+        parse (nonPositive Decimal) (TP.npDecimal i) == Parsed (i ∷ Int)
+  , testProperty "nonPositive Hexadecimal" $ \i →
+      (i <= 0) ==>
+        parse (nonPositive Hexadecimal) (TP.npLowHex i) == Parsed (i ∷ Int)
+  , testProperty "npCompact Decimal" $ \i →
+      (i <= 0) ==>
+        parse (npCompact Decimal) (TP.npDecimal i) == Parsed (i ∷ Int)
+  , testProperty "npCompact Decimal fails on \"00\"" $
+      isMalformed $ parseAs anInt (npCompact Decimal) "00"
+  , testProperty "npCompact Decimal fails on \"01\"" $
+      isMalformed $ parseAs anInt (npCompact Decimal) "01"
+  , testProperty "npUpTo Decimal 3" $ \i →
+      (i <= 0) ==> case parse (npUpTo Decimal 3) (TP.npDecimal i) of
+        Malformed _ _ | i <= -1000      → True
+        Parsed i'     | i' == (i ∷ Int) → True 
+        _                               → False
+  , testProperty "npcUpTo Decimal 3" $ \i →
+      (i <= 0) ==> case parse (npcUpTo Decimal 3) (TP.npDecimal i) of
+        Malformed _ _ | i <= -1000      → True
+        Parsed i'     | i' == (i ∷ Int) → True 
+        _                               → False
+  , testProperty "nncUpTo Decimal fails on \"00\"" $
+      isMalformed $ parseAs aWord (nncUpTo Decimal 3) "00"
+  , testProperty "nncUpTo Decimal fails on \"01\"" $
+      isMalformed $ parseAs aWord (nncUpTo Decimal 3) "01"
+  , testProperty "npBounded Hexadecimal" $ \i →
+      (i <= 0) ==>
+        parse (npBounded Hexadecimal) (TP.npLowHex i) == Parsed (i ∷ Int)
+  , testProperty "npBounded Hexadecimal fails on overflow" $
+      isMalformed $ parseAs anInt (npBounded Hexadecimal)
+                            (TP.npLowHex $ toInteger (minBound ∷ Int) - 1)
+  , testProperty "npcBounded Decimal fails on \"00\"" $
+      isMalformed $ parseAs anInt (npcBounded Decimal) "00"
+  , testProperty "npcBounded Decimal fails on \"01\"" $
+      isMalformed $ parseAs anInt (npcBounded Decimal) "01"
+  , testProperty "npBits Binary" $ \i →
+      (i <= 0) ==>
+        parse (npBits Binary) (TP.npBinaryBits i) == Parsed (i ∷ Int)
+  , testProperty "npBits Hexadecimal" $ \i →
+      (i <= 0) ==>
+        parse (npBits Hexadecimal) (TP.npUpHex i) == Parsed (i ∷ Int)
+  , testProperty "npcBits Octal" $ \i →
+      (i <= 0) ==>
+        parse (npcBits Octal) (TP.npOctal i) == Parsed (i ∷ Int)
+  , testProperty "npcBits Octal fails on \"00\"" $
+      isMalformed $ parseAs anInt (npcBits Octal) "00"
+  , testProperty "npcBits Octal fails on \"01\"" $
+      isMalformed $ parseAs anInt (npcBits Octal) "01"
+  , testProperty "npBitsUpTo Hexadecimal 3" $ \i →
+      (i <= 0) ==> case parse (npBitsUpTo Hexadecimal 3) (TP.npUpHex i) of
+        Malformed _ _ | i <= -0x1000    → True
+        Parsed i'     | i' == (i ∷ Int) → True 
+        _                               → False
+  , testProperty "npcBitsUpTo Octal 3" $ \i →
+      (i <= 0) ==> case parse (npcBitsUpTo Octal 3) (TP.npOctal i) of
+        Malformed _ _ | i <= -0o1000    → True
+        Parsed i'     | i' == (i ∷ Int) → True 
+        _                               → False
+  , testProperty "npcBitsUpTo UpHex fails on \"00\"" $
+      isMalformed $ parseAs anInt (npcBitsUpTo UpHex 3) "00"
+  , testProperty "npcBitsUpTo UpHex fails on \"01\"" $
+      isMalformed $ parseAs anInt (npcBitsUpTo UpHex 3) "01"
+  , testProperty "npbBits Hexadecimal" $ \i →
+      (i <= 0) ==>
+        parse (npbBits Hexadecimal) (TP.npUpHexBits i) == Parsed (i ∷ Int)
+  , testProperty "npbBits Hexadecimal fails on overflow" $
+      isMalformed $ parseAs anInt (npbBits Hexadecimal)
+                            (TP.npUpHexBits $ toInteger (minBound ∷ Int) - 1)
+  , testProperty "npcbBits Octal fails on \"00\"" $
+      isMalformed $ parseAs anInt (npcbBits Octal) "00"
+  , testProperty "npcbBits Octal fails on \"01\"" $
+      isMalformed $ parseAs anInt (npcbBits Octal) "01"
+  , testProperty "number Decimal" $ \i →
+      parse (number Decimal) (TP.decimal i) == Parsed (i ∷ Int)
+  , testProperty "compact Decimal" $ \i →
+      parse (number Decimal) (TP.decimal i) == Parsed (i ∷ Int)
+  , testProperty "compact Decimal fails on \"00\"" $
+      isMalformed $ parseAs anInt (compact Decimal) "00"
+  , testProperty "compact Decimal fails on \"01\"" $
+      isMalformed $ parseAs anInt (compact Decimal) "01"
+  , testProperty "compact Decimal fails on \"-01\"" $
+      isMalformed $ parseAs anInt (compact Decimal) "-01"
+  , testProperty "numberUpTo Decimal 3" $ \i →
+      case parseAs anInt (numberUpTo Decimal 3) (TP.decimal i) of
+        Malformed _ _ | i >= 1000 || i <= -1000 → True
+        Parsed i'     | i' == i                 → True 
+        _                                       → False
+  , testProperty "compactUpTo Decimal 3" $ \i →
+      case parseAs anInt (compactUpTo Decimal 3) (TP.decimal i) of
+        Malformed _ _ | i >= 1000 || i <= -1000 → True
+        Parsed i'     | i' == i                 → True 
+        _                                       → False
+  , testProperty "compactUpTo Decimal fails on \"00\"" $
+      isMalformed $ parseAs anInt (compactUpTo Decimal 3) "00"
+  , testProperty "compactUpTo Decimal fails on \"01\"" $
+      isMalformed $ parseAs anInt (compactUpTo Decimal 3) "01"
+  , testProperty "compactUpTo Decimal fails on \"-01\"" $
+      isMalformed $ parseAs anInt (compactUpTo Decimal 3) "-01"
+  , testProperty "bounded Decimal" $ \i →
+      parse (bounded Decimal) (TP.decimal i) == Parsed (i ∷ Int)
+  , testProperty "bounded Decimal fails on overflow (vs maxBound)" $
+      isMalformed $ parseAs anInt (bounded Decimal)
+                            (TP.decimal $ toInteger (maxBound ∷ Int) + 1)
+  , testProperty "bounded Decimal fails on overflow (vs minBound)" $
+      isMalformed $ parseAs anInt (bounded Decimal)
+                            (TP.decimal $ toInteger (minBound ∷ Int) - 1)
+  , testProperty "cBounded Decimal" $ \i →
+      parse (cBounded Decimal) (TP.decimal i) == Parsed (i ∷ Int)
+  , testProperty "cBounded Octal fails on \"00\"" $
+      isMalformed $ parseAs anInt (cBounded Octal) "00"
+  , testProperty "cBounded Octal fails on \"01\"" $
+      isMalformed $ parseAs anInt (cBounded Octal) "01"
+  , testProperty "cBounded Octal fails on \"-01\"" $
+      isMalformed $ parseAs anInt (cBounded Octal) "-01"
+  , testProperty "bits Binary" $ \i →
+      parse (bits Binary) (TP.binaryBits i) == Parsed (i ∷ Int)
+  , testProperty "bits Hexadecimal" $ \i →
+      parse (bits Hexadecimal) (TP.lowHexBits i) == Parsed (i ∷ Int)
+  , testProperty "cBits Octal" $ \i →
+      parse (cBits Octal) (TP.octalBits i) == Parsed (i ∷ Int)
+  , testProperty "cBits Octal fails on \"00\"" $
+      isMalformed $ parseAs anInt (cBits Octal) "00"
+  , testProperty "cBits Octal fails on \"01\"" $
+      isMalformed $ parseAs anInt (cBits Octal) "01"
+  , testProperty "cBits Octal fails on \"-01\"" $
+      isMalformed $ parseAs anInt (cBits Octal) "-01"
+  , testProperty "bitsUpTo LowHex 3" $ \i →
+      case parseAs anInt (bitsUpTo LowHex 3) (TP.lowHex i) of
+        Malformed _ _ | i >= 0x1000 || i <= -0x1000 → True
+        Parsed i'     | i' == i                     → True 
+        _                                           → False
+  , testProperty "cBitsUpTo UpHex 3" $ \i →
+      case parseAs anInt (cBitsUpTo UpHex 3) (TP.upHex i) of
+        Malformed _ _ | i >= 0x1000 || i <= -0x1000 → True
+        Parsed i'     | i' == i                     → True 
+        _                                           → False
+  , testProperty "cBitsUpTo Octal fails on \"00\"" $
+      isMalformed $ parseAs anInt (cBitsUpTo Octal 3) "00"
+  , testProperty "cBitsUpTo Octal fails on \"01\"" $
+      isMalformed $ parseAs anInt (cBitsUpTo Octal 3) "01"
+  , testProperty "cBitsUpTo Octal fails on \"-01\"" $
+      isMalformed $ parseAs anInt (cBitsUpTo Octal 3) "-01"
+  , testProperty "bBits LowHex" $ \i →
+      parse (bBits LowHex) (TP.lowHexBits i) == Parsed (i ∷ Int)
+  , testProperty "bBits LowHex fails on overflow (vs maxBound)" $
+      isMalformed $ parseAs anInt (bBits LowHex)
+                            (TP.lowHexBits $ toInteger (maxBound ∷ Int) + 1)
+  , testProperty "bBits UpHex fails on overflow (vs minBound)" $
+      isMalformed $ parseAs anInt (bBits UpHex)
+                            (TP.upHexBits $ toInteger (minBound ∷ Int) - 1)
+  , testProperty "cbBits Octal" $ \i →
+      parse (cbBits Octal) (TP.octal i) == Parsed (i ∷ Int)
+  , testProperty "cbBits Octal fails on \"00\"" $
+      isMalformed $ parseAs anInt (cbBits Octal) "00"
+  , testProperty "cbBits Octal fails on \"01\"" $
+      isMalformed $ parseAs anInt (cbBits Octal) "01"
+  , testProperty "cbBits Octal fails on \"-01\"" $
+      isMalformed $ parseAs anInt (cbBits Octal) "-01"
+  ]
+
+parse ∷ (∀ μ . (Monad μ, CharParsing μ) ⇒ μ α) → StringBuilder → Parsed α
+parse p b = builtInParser (p <* PC.eof) (TP.buildString b)
+
+parseAs ∷ Proxy α → (∀ μ . (Monad μ, CharParsing μ) ⇒ μ α) → StringBuilder
+        → Parsed α
+parseAs _ = parse
+
