diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,9 +0,0 @@
-Interactive interpreted usage without having installed first
-requires adding a search path for the respective environment:
-
-  hugs -98 -P:src:base21
-  ghci-7.0.4 -isrc:base40
-  ghci-7.4.1 -isrc:base45
-  ghci-7.8.1 -isrc:base47
-
-ghc < 7.6 has not been tested recently, reports welcome.
diff --git a/base21/Compat.hs b/base21/Compat.hs
deleted file mode 100644
--- a/base21/Compat.hs
+++ /dev/null
@@ -1,29 +0,0 @@
-module Compat
-  ( unsafeIOToST
-  , uncons
-  , packCStringLen
-  , unsafeUseAsCStringLen
-  , popCount
-  , zeroBits
-  ) where
-
-import Control.Monad.ST (unsafeIOToST)
-import Data.Bits (Bits, (.&.), shiftR, clearBit, bit)
-import qualified Data.ByteString as BS
-import Data.Word (Word8, Word64)
-import Foreign.C.String (CStringLen)
-
-uncons :: BS.ByteString -> Maybe (Word8, BS.ByteString)
-uncons s = if BS.null s then Nothing else Just (BS.head s, BS.tail s)
-
-unsafeUseAsCStringLen :: BS.ByteString -> (CStringLen -> IO a) -> IO a
-unsafeUseAsCStringLen = BS.useAsCStringLen
-
-packCStringLen :: CStringLen -> IO BS.ByteString
-packCStringLen = return . BS.packCStringLen
-
-popCount :: Word64 -> Int
-popCount = fromIntegral . sum . map (.&. 1) . take 64 . iterate (`shiftR` 1)
-
-zeroBits :: Bits b => b
-zeroBits = clearBit (bit 0) 0
diff --git a/base40/Compat.hs b/base40/Compat.hs
deleted file mode 100644
--- a/base40/Compat.hs
+++ /dev/null
@@ -1,19 +0,0 @@
-module Compat
-  ( unsafeIOToST
-  , uncons
-  , packCStringLen
-  , unsafeUseAsCStringLen
-  , popCount
-  , zeroBits
-  ) where
-
-import Control.Monad.ST (unsafeIOToST)
-import Data.ByteString (uncons, packCStringLen)
-import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
-import Data.Bits (Bits, (.&.), shiftR, clearBit, bit)
-
-popCount :: Word64 -> Int
-popCount = fromIntegral . sum . map (.&. 1) . take 64 . iterate (`shiftR` 1)
-
-zeroBits :: Bits b => b
-zeroBits = clearBit (bit 0) 0
diff --git a/base45/Compat.hs b/base45/Compat.hs
deleted file mode 100644
--- a/base45/Compat.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-module Compat
-  ( unsafeIOToST
-  , uncons
-  , packCStringLen
-  , unsafeUseAsCStringLen
-  , popCount
-  , zeroBits
-  ) where
-
-import Control.Monad.ST.Unsafe (unsafeIOToST)
-import Data.ByteString (uncons, packCStringLen)
-import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
-import Data.Bits (Bits, popCount, clearBit, bit)
-
-zeroBits :: Bits b => b
-zeroBits = clearBit (bit 0) 0
diff --git a/base47/Compat.hs b/base47/Compat.hs
deleted file mode 100644
--- a/base47/Compat.hs
+++ /dev/null
@@ -1,13 +0,0 @@
-module Compat
-  ( unsafeIOToST
-  , uncons
-  , packCStringLen
-  , unsafeUseAsCStringLen
-  , popCount
-  , zeroBits
-  ) where
-
-import Control.Monad.ST.Unsafe (unsafeIOToST)
-import Data.ByteString (uncons, packCStringLen)
-import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
-import Data.Bits (popCount, zeroBits)
diff --git a/bitwise.cabal b/bitwise.cabal
--- a/bitwise.cabal
+++ b/bitwise.cabal
@@ -1,5 +1,5 @@
 Name:                bitwise
-Version:             0.2
+Version:             1.0.0.1
 Synopsis:            fast multi-dimensional unboxed bit packed Bool arrays
 Description:
   Unboxed multidimensional bit packed Bool arrays with fast aggregate
@@ -54,14 +54,7 @@
 Category:            Data, Data Structures, Bit Vectors
 Build-type:          Simple
 
-Cabal-version:       >= 1.9.2
-
-Extra-source-files:
-  README
-  base21/Compat.hs
-  base40/Compat.hs
-  base45/Compat.hs
-  base47/Compat.hs
+Cabal-version:       >= 1.10
 
 Library
   Exposed-modules:
@@ -74,29 +67,16 @@
 
   Other-modules:
     Data.Array.BitArray.Internal
-    Compat
 
   Build-depends:
+    base >= 4.7 && < 4.12,
     bytestring < 0.11,
     array < 0.6
 
   HS-source-dirs: src
 
-  if (impl(hugs))
-    HS-source-dirs: base21
-    Build-depends:  base >= 2.1 && < 4.0
-
-  if (impl(ghc < 7.4))
-    HS-source-dirs: base40
-    Build-depends:  base >= 4.0 && < 4.5
-
-  if (impl(ghc >= 7.4) && impl(ghc < 7.8))
-    HS-source-dirs: base45
-    Build-depends:  base >= 4.5 && < 4.7
-
-  if (impl(ghc >= 7.8))
-    HS-source-dirs: base47
-    Build-depends:  base >= 4.7 && < 4.12
+  Default-Language: Haskell2010
+  Other-Extensions: PatternGuards
 
   GHC-Options:        -Wall
 
@@ -107,6 +87,7 @@
     bitwise,
     base,
     QuickCheck >= 2.4 && < 2.12
+  Default-Language: Haskell2010
 
 Benchmark bitwise-benchmark
   type:    exitcode-stdio-1.0
@@ -117,6 +98,7 @@
     array,
     bytestring,
     criterion >= 0.6 && < 1.5
+  Default-Language: Haskell2010
 
 source-repository head
   type:     git
@@ -125,4 +107,4 @@
 source-repository this
   type:     git
   location: https://code.mathr.co.uk/bitwise.git
-  tag:      v0.2
+  tag:      v1.0.0.1
diff --git a/src/Codec/Image/PBM.hs b/src/Codec/Image/PBM.hs
--- a/src/Codec/Image/PBM.hs
+++ b/src/Codec/Image/PBM.hs
@@ -54,8 +54,7 @@
 import qualified Data.Array.Unboxed as U
 import qualified Data.ByteString as BS
 
-import qualified Compat as BSC
-import Data.Bits.Bitwise (packWord8BE, unpackWord8LE)
+import Data.Bits.Bitwise (fromListBE, toListLE)
 import Data.Array.BitArray (BitArray, bounds, elems, listArray, false, (//), assocs, ixmap)
 import Data.Array.BitArray.ByteString (toByteString, fromByteString)
 
@@ -142,8 +141,8 @@
 
 -- | Decode a binary PBM (P4) image.
 decodePBM :: BS.ByteString -> Either (DecodeError BS.ByteString) (PBM, BS.ByteString)
-decodePBM s =                    case BSC.uncons s of
-  Just (cP, s) | cP == char 'P' -> case BSC.uncons s of
+decodePBM s =                    case BS.uncons s of
+  Just (cP, s) | cP == char 'P' -> case BS.uncons s of
     Just (c4, s) | c4 == char '4' -> case int (skipSpaceComment s) of
       Just (iw, s) | iw > 0         -> case int (skipSpaceComment s) of
         Just (ih, s) | ih > 0         -> case skipSingleSpace s of
@@ -161,19 +160,19 @@
     _ -> Left (BadMagicN s)
   _ -> Left (BadMagicP s)
   where
-    skipSpaceComment t = case (\t -> (t, BSC.uncons t)) (BS.dropWhile isSpace t) of
-      (_, Just (cH, t)) | cH == char '#' -> case BSC.uncons (BS.dropWhile (/= char '\n') t) of
+    skipSpaceComment t = case (\t -> (t, BS.uncons t)) (BS.dropWhile isSpace t) of
+      (_, Just (cH, t)) | cH == char '#' -> case BS.uncons (BS.dropWhile (/= char '\n') t) of
         Just (cL, t) | cL == char '\n' -> skipSpaceComment t
         _ -> Left (BadSpace t)
       (t, _) -> Right t
-    skipSingleSpace t = case BSC.uncons t of
+    skipSingleSpace t = case BS.uncons t of
       Just (cS, t) | isSpace cS -> Just t
       _ -> Nothing
     int (Left _) = Nothing
     int (Right t) = case BS.span isDigit t of
       (d, t)
         | BS.length d > 0 &&
-          fmap ((/= char '0') . fst) (BSC.uncons d) == Just True -> case reads (map unchar $ BS.unpack d) of
+          fmap ((/= char '0') . fst) (BS.uncons d) == Just True -> case reads (map unchar $ BS.unpack d) of
             [(d, "")] -> Just (d, t)
             _ -> Nothing
       _ -> Nothing
@@ -293,8 +292,7 @@
 
 -- | A slow way to reverse bit order.
 bitReverse :: Word8 -> Word8
-bitReverse w = case unpackWord8LE w of
-  (a, b, c, d, e, f, g, h) -> packWord8BE a b c d e f g h
+bitReverse = fromListBE . toListLE
 
 -- | White space characters as defined by the PBM specification.
 pbmSpace :: String
diff --git a/src/Data/Array/BitArray/ByteString.hs b/src/Data/Array/BitArray/ByteString.hs
--- a/src/Data/Array/BitArray/ByteString.hs
+++ b/src/Data/Array/BitArray/ByteString.hs
@@ -1,7 +1,7 @@
 {-|
 
 Module      :  Data.Array.BitArray.ByteString
-Copyright   :  (c) Claude Heiland-Allen 2012
+Copyright   :  (c) Claude Heiland-Allen 2012,2018
 License     :  BSD3
 
 Maintainer  :  claude@mathr.co.uk
@@ -22,7 +22,8 @@
   ) where
 
 import Data.Bits (shiftR, (.&.))
-import Data.ByteString (ByteString)
+import Data.ByteString (ByteString, packCStringLen)
+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
 import Data.Ix (Ix, rangeSize)
 import Data.Word (Word8)
 import Control.Monad (when)
@@ -32,7 +33,6 @@
 import Foreign.Storable (peekByteOff, pokeByteOff)
 import System.IO.Unsafe (unsafePerformIO)
 
-import Compat (packCStringLen, unsafeUseAsCStringLen)
 import Data.Bits.Bitwise (mask)
 import Data.Array.BitArray (BitArray)
 import Data.Array.BitArray.IO (IOBitArray)
diff --git a/src/Data/Array/BitArray/IO.hs b/src/Data/Array/BitArray/IO.hs
--- a/src/Data/Array/BitArray/IO.hs
+++ b/src/Data/Array/BitArray/IO.hs
@@ -1,7 +1,7 @@
 {-|
 
 Module      :  Data.Array.BitArray.IO
-Copyright   :  (c) Claude Heiland-Allen 2012
+Copyright   :  (c) Claude Heiland-Allen 2012,2018
 License     :  BSD3
 
 Maintainer  :  claude@mathr.co.uk
@@ -51,6 +51,7 @@
 
 import Control.Monad (forM_, when)
 import Data.Bits (shiftL, shiftR, testBit, setBit, clearBit, (.&.), complement)
+import qualified Data.Bits
 import Data.Ix (Ix, index, inRange, range, rangeSize)
 import Data.List (foldl1')
 import Data.Word (Word8, Word64)
@@ -61,7 +62,6 @@
 
 import Data.Bits.Bitwise (packWord8LE, mask)
 import qualified Data.Bits.Bitwise as Bitwise
-import qualified Compat as Compat
 
 import Data.Array.BitArray.Internal
   ( IOBitArray(..)
@@ -389,7 +389,7 @@
       loop p n acc
         | n < count = acc `seq` do
             w <- peekElemOff p n
-            loop p (n + 1) (acc + Compat.popCount w)
+            loop p (n + 1) (acc + Data.Bits.popCount w)
         | otherwise = rest full acc
       rest m acc
         | m < total = acc `seq` do
diff --git a/src/Data/Array/BitArray/ST.hs b/src/Data/Array/BitArray/ST.hs
--- a/src/Data/Array/BitArray/ST.hs
+++ b/src/Data/Array/BitArray/ST.hs
@@ -1,7 +1,7 @@
 {-|
 
 Module      :  Data.Array.BitArray.ST
-Copyright   :  (c) Claude Heiland-Allen 2012
+Copyright   :  (c) Claude Heiland-Allen 2012,2018
 License     :  BSD3
 
 Maintainer  :  claude@mathr.co.uk
@@ -52,7 +52,7 @@
 import Control.Monad.ST (ST)
 import Data.Ix (Ix)
 
-import Compat (unsafeIOToST)
+import Control.Monad.ST.Unsafe (unsafeIOToST)
 import Data.Array.BitArray.Internal (BitArray)
 import Data.Array.BitArray.IO (IOBitArray)
 import qualified Data.Array.BitArray.IO as IO
diff --git a/src/Data/Bits/Bitwise.hs b/src/Data/Bits/Bitwise.hs
--- a/src/Data/Bits/Bitwise.hs
+++ b/src/Data/Bits/Bitwise.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE PatternGuards #-}
 {-|
 
 Module      :  Data.Bits.Bitwise
@@ -44,9 +45,8 @@
 import Prelude hiding (repeat, map, zipWith, any, all, or, and, splitAt)
 import qualified Prelude as P
 
-import Compat (zeroBits)
-
-import Data.Bits (Bits(complement, (.&.), (.|.), xor, bit, shiftL, shiftR, testBit, bitSize))
+import Data.Bits (Bits(complement, (.&.), (.|.), xor, bit, shiftL, shiftR, testBit, bitSizeMaybe, zeroBits),
+                  FiniteBits(finiteBitSize))
 import Data.List (foldl')
 import Data.Word (Word8)
 
@@ -178,11 +178,14 @@
   where
     f b i = fromBool b .|. (i `shiftL` 1)
 
--- | Convert a 'Bits' (with a defined 'bitSize') to a list of bits, in
+-- | Convert a 'Bits' to a list of bits, in
 --   little-endian order.
 {-# INLINE toListLE #-}
 toListLE :: (Bits b) => b -> [Bool] {- ^ \[least significant bit, ..., most significant bit\] -}
-toListLE b = P.map (testBit b) [0 .. bitSize b - 1]
+toListLE b0 | Just n <- bitSizeMaybe b0 = P.map (testBit b0) [0..n-1]
+            | otherwise = go b0
+  where go b | zeroBits == b = []
+             | otherwise = testBit b 0 : go (b `shiftR` 1)
 
 -- | Convert a big-endian list of bits to 'Bits'.
 {-# INLINE fromListBE #-}
@@ -191,8 +194,8 @@
   where
     f i b = (i `shiftL` 1) .|. fromBool b
 
--- | Convert a 'Bits' (with a defined 'bitSize') to a list of bits, in
+-- | Convert a 'FiniteBits' to a list of bits, in
 --   big-endian order.
 {-# INLINE toListBE #-}
-toListBE :: (Bits b) => b -> [Bool] {- ^ \[most significant bit, ..., least significant bit\] -}
-toListBE b = P.map (testBit b) [bitSize b - 1, bitSize b - 2 .. 0]
+toListBE :: (FiniteBits b) => b -> [Bool] {- ^ \[most significant bit, ..., least significant bit\] -}
+toListBE b = P.map (testBit b) [finiteBitSize b - 1, finiteBitSize b - 2 .. 0]
