diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,5 @@
+  - 0.3: use only total functions on `FiniteBits`, requires GHC >= 7.8
+  - 0.2.2: build on GHC 7.6, integrate tests with cabal build
+  - 0.2.1: `toList'` function
+  - 0.2: split `C.B.G.Bits` and `C.B.G.List` APIs
+  - 0.1: initial Hackage release
diff --git a/Codec/Binary/Gray/Bits.hs b/Codec/Binary/Gray/Bits.hs
--- a/Codec/Binary/Gray/Bits.hs
+++ b/Codec/Binary/Gray/Bits.hs
@@ -13,37 +13,31 @@
     ) where
 
 import Data.Bits
-    ( Bits, testBit, setBit, clearBit, bitSize
+    ( FiniteBits, testBit, setBit, clearBit, finiteBitSize
     , shiftL, shiftR, complement, xor, (.&.), (.|.), isSigned)
 
 import qualified Codec.Binary.Gray.List as L
 
 -- | Right shift without extension of the sign bit (reset it to zero).
-shiftR' :: (Bits a, Num a) => a -> Int -> a
+shiftR' :: (FiniteBits a, Num a) => a -> Int -> a
 shiftR' n 0    = n
 shiftR' n s
   | isSigned n && signum n == -1 =
-      let n' = clearBit (shiftR n 1) (bitSize n - 1)
+      let n' = clearBit (shiftR n 1) (finiteBitSize n - 1)
       in  shiftR' n' (s-1)
   | otherwise  = shiftR n s
 
 -- | Convert an integer number from binary to Gray code.
---
--- 'gray' is undefined for negative numbers of types that do not have
--- fixed bitsize, e.g. for negative 'Integer's.
-gray :: (Bits a, Num a) => a -> a
+gray :: (FiniteBits a, Num a) => a -> a
 gray n = n `xor` (shiftR' n 1)
 
 -- | Convert an integer number from Gray code to binary.
---
--- 'binary' is undefined for types that do not have fixed bitsize,
--- e.g. for 'Integer'.
-binary :: (Bits a, Num a) => a -> a
+binary :: (FiniteBits a, Num a) => a -> a
 binary 0 = 0
 binary n =
   binary' mask0 n (copyMSB n)
   where
-    sz = bitSize n - 1
+    sz = finiteBitSize n - 1
     mask0 = let m = setBit 0 sz in  (m, m)
     copyMSB n = (setBit 0 sz) .&. n
 
@@ -51,7 +45,7 @@
   | complement maskReady == 0 = nbin
   | otherwise =
      let
-       sz = bitSize ngray - 1
+       sz = finiteBitSize ngray - 1
        nReady = maskReady .&. nbin
        maskReady' = setBit (shiftR maskReady 1) sz
        maskLast' = shiftR' maskLast 1
@@ -61,5 +55,5 @@
 
 -- | Render binary code as a string of @0@s and @1@s.
 -- For example, @(42::Int8)@ is formatted as @101010@.
-showBits :: (Bits a, Num a) => a -> String
+showBits :: (FiniteBits a, Num a) => a -> String
 showBits = L.showBits . L.toList
diff --git a/Codec/Binary/Gray/List.hs b/Codec/Binary/Gray/List.hs
--- a/Codec/Binary/Gray/List.hs
+++ b/Codec/Binary/Gray/List.hs
@@ -13,7 +13,7 @@
     , showBits
     ) where
 
-import Data.Bits (Bits, testBit, bitSize, shiftR, isSigned)
+import Data.Bits (FiniteBits, Bits, testBit, finiteBitSize, bitSizeMaybe, shiftR, isSigned)
 
 boolXOR :: Bool -> Bool -> Bool
 boolXOR p q = (p && not q) || (not p && q)
@@ -35,25 +35,35 @@
 -- | Convert a number to a list of bits in usual binary encoding (most
 -- significant bit last). Truncates unset major bits.
 --
--- This function is undefined for negative numbers of types that do not
--- have fixed bitsize, like 'Integer'.
+-- The function may be also applied to unbounded integral types (like
+-- 'Integer'): it will return a list of bits for positive values, and
+-- an empty list for negative values or zero.
 toList :: (Bits b, Num b) => b -> [Bool]
 toList 0 = []
-toList i
-  | isSigned i && signum i == (-1) =
-      let b = map not . toList $ negate i - 1
-      in  b ++ (take (bitSize i - length b) $ repeat True) -- pad major bits
-  | otherwise        =
+toList i =
+  let mbSize = bitSizeMaybe i
+      isNegative = isSigned i && signum i == (-1)
+  in  case (mbSize, isNegative) of
+        (Just _, False) -> positiveToList i
+        (Just size, True) -> negativeToList size i
+        (Nothing, False) -> positiveToList i
+        (Nothing, True) -> []
+  where
+    positiveToList i =
       let rest = toList $ shiftR i 1  -- works only for positive i
       in  (testBit i 0 : rest)
+    negativeToList bsize i =
+        let b = map not . toList $ negate i - 1
+        in  b ++ (take (bsize - length b) $ repeat True)
+        --    ^^^ pad major bits
 
 -- | Convert a number to a list of bits in usual binary encoding (most
 -- significant bit last).
 --
 -- Like 'toList', but returns all unset major bits too. So the length
--- of the output is always the same length as @bitSize i@.
-toList' :: (Bits b, Num b) => b -> [Bool]
-toList' i = map (testBit i) [0..bitSize i - 1]
+-- of the output is always the same length as @finiteBitSize i@.
+toList' :: (FiniteBits b, Num b) => b -> [Bool]
+toList' i = map (testBit i) [0..finiteBitSize i - 1]
 
 -- | Convert a list of bits in binary encoding to a number.
 fromList :: (Bits b, Num b) => [Bool] -> b
diff --git a/Codec/Binary/Gray_props.hs b/Codec/Binary/Gray_props.hs
--- a/Codec/Binary/Gray_props.hs
+++ b/Codec/Binary/Gray_props.hs
@@ -5,8 +5,9 @@
 import qualified Codec.Binary.Gray.Bits as B
 import qualified Codec.Binary.Gray.List as L
 
-import Data.Bits (testBit, bitSize, Bits)
+import Data.Bits (testBit, finiteBitSize, Bits, FiniteBits)
 import Data.Function (on)
+import Data.Word (Word)
 
 ---
 --- Properties of list-based functions
@@ -25,7 +26,7 @@
 prop_lists_correct_bits_Int =
   label "toList is correct [Int]" $
   forAll (arbitrary :: Gen Int) $ \i ->
-      let bts = map (testBit i) [0..(bitSize i)-1]
+      let bts = map (testBit i) [0..(finiteBitSize i)-1]
           padded = (L.toList i) ++ (repeat False)
       in  all id $ zipWith (==) bts padded
 
@@ -64,7 +65,7 @@
            else go (d+1) xs ys
 
 ---
---- Properties of functions for Bits types
+--- Properties of functions for FiniteBits types
 ---
 prop_bits_id = label "binary . gray == gray . binary == id" $
   forAll (arbitrary :: Gen Int) $ \i ->
@@ -79,9 +80,9 @@
   forAll (arbitrary :: Gen Int) $ \i ->
       (hammingBits `on` B.gray) i (i+1) == 1
 
-prop_bits_gray_succ_Integer = label "hamming x (x+1) == 1 [Integer]" $
-  forAll (arbitrary :: Gen (NonNegative Integer)) $ \(NonNegative i) ->
-      (hammingBits `on` B.gray) i (i+1) == 1
+prop_bits_gray_succ_Word = label "hamming x (x+1) == 1 [Word]" $
+  forAll (arbitrary :: Gen Word) $ \w ->
+      (hammingBits `on` B.gray) w (w+1) == 1
 
 hammingBits :: (Bits a, Num a) => a -> a -> Int
 hammingBits = hamming `on` L.toList
@@ -102,7 +103,7 @@
   prop_bits_id .&.
   prop_bits_same_as_lists .&.
   prop_bits_gray_succ_Int .&.
-  prop_bits_gray_succ_Integer
+  prop_bits_gray_succ_Word
 
 all_props =
   prop_lists .&. prop_bits
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Sergey Astanin 2010
+Copyright Sergey Astanin 2010-2014
 
 All rights reserved.
 
diff --git a/gray-code.cabal b/gray-code.cabal
--- a/gray-code.cabal
+++ b/gray-code.cabal
@@ -7,7 +7,7 @@
 -- The package version. See the Haskell package versioning policy
 -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
 -- standards guiding when and how versions should be incremented.
-Version:             0.2.2
+Version:             0.3
 
 -- A short (one-line) description of the package.
 Synopsis:            Gray code encoder/decoder.
@@ -19,8 +19,8 @@
    .
    This package allows to convert numbers to one of the possible Gray
    codes and back. Two binary representations of a number are supported:
-   @[Bool]@ and types of @Bits@ type class.
-   @Bits@ is the default implementation.
+   @[Bool]@ and types of @FiniteBits@ type class.
+   @FiniteBits@ is the default implementation.
 
 -- URL for the project homepage or repository.
 Homepage:            http://bitbucket.org/astanin/hs-gray-code
@@ -53,6 +53,9 @@
 Extra-source-files:
      Codec/Binary/Gray_props.hs
 
+Extra-doc-files:
+     CHANGELOG
+
 -- Constraint on the version of Cabal needed to build this package.
 Cabal-version:       >=1.8
 
@@ -66,7 +69,7 @@
 
   -- Packages needed in order to build this package.
   Build-depends:
-     base >= 3 && < 5
+     base >= 4.7 && < 5
 
   -- Modules not exported by this package.
   -- Other-modules:
