diff --git a/bitvec.cabal b/bitvec.cabal
--- a/bitvec.cabal
+++ b/bitvec.cabal
@@ -1,71 +1,69 @@
-name:                   bitvec
-version:                0.1.0.2
-stability:              experimental
-
-cabal-version:          >= 1.9.2
-build-type:             Simple
-
-author:                 James Cook <mokus@deepbondi.net>
-maintainer:             James Cook <mokus@deepbondi.net>
-license:                PublicDomain
-license-file:           LICENSE
-homepage:               https://github.com/mokus0/bitvec
-
-category:               Data, Bit Vectors
-synopsis:               Unboxed vectors of bits / dense IntSets
-description:            Another bit-array library for Haskell.  This one defines a `Bit` 
-                        type (which is an instance of all the "expected" classes, including
-                        numeric ones) and makes that type an instance of `Data.Vector.Unboxed.
-                        Unbox`, so we get a lot of nice APIs for free.  `Bool` is already an
-                        unboxable type, but the current unboxed `Vector` implementation packs
-                        each bit as a byte.  This one packs 8 bits per byte, as expected
-                        (`UArray` from the `array` package also uses one bit per `Bool`).
-                        .
-                        In addition to the `Vector` interface, there are several high-level
-                        operations and some low-level ones suitable for building new bulk
-                        operations by viewing the bit-vector as a word vector.
-
-tested-with:            GHC == 7.0.4,
-                        GHC == 7.2.2,
-                        GHC == 7.4.2,
-                        GHC == 7.6.3,
-                        GHC == 7.8.4,
-                        GHC == 7.10.1,
-                        GHC == 7.11
+name: bitvec
+version: 0.1.1.0
+cabal-version: >=1.10
+build-type: Simple
+license: PublicDomain
+license-file: LICENSE
+maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>
+homepage: https://github.com/Bodigrim/bitvec
+synopsis: Unboxed vectors of bits / dense IntSets
+description:
+  Another bit-array library for Haskell.  This one defines a `Bit`
+  type (which is an instance of all the "expected" classes, including
+  numeric ones) and makes that type an instance of `Data.Vector.Unboxed.
+  Unbox`, so we get a lot of nice APIs for free.  `Bool` is already an
+  unboxable type, but the current unboxed `Vector` implementation packs
+  each bit as a byte.  This one packs 8 bits per byte, as expected
+  (`UArray` from the `array` package also uses one bit per `Bool`).
+  .
+  In addition to the `Vector` interface, there are several high-level
+  operations and some low-level ones suitable for building new bulk
+  operations by viewing the bit-vector as a word vector.
+category: Data, Bit Vectors
+author: James Cook <mokus@deepbondi.net>,
+        Andrew Lelechenko <andrew.lelechenko@gmail.com>
+tested-with: GHC ==8.0.2 GHC ==8.2.2 GHC ==8.4.3 GHC ==8.6.3
 
 source-repository head
   type: git
-  location: git://github.com/mokus0/bitvec.git
+  location: git://github.com/Bodigrim/bitvec.git
 
-Test-Suite bitvec-tests
-  type:                 exitcode-stdio-1.0
-  hs-source-dirs:       src test
-  ghc-options:          -threaded -fwarn-unused-imports -fwarn-unused-binds
-  main-is:              Main.hs
-  other-modules:        Support
-                        Tests.Bit
-                        Tests.MVector
-                        Tests.SetOps
-                        Tests.Vector
-  build-depends:        base >= 3,
-                        HUnit,
-                        primitive,
-                        vector >= 0.8,
-                        test-framework,
-                        test-framework-hunit,
-                        test-framework-quickcheck2,
-                        QuickCheck
+library
+  exposed-modules:
+      Data.Bit
+      Data.Vector.Unboxed.Bit
+      Data.Vector.Unboxed.Mutable.Bit
+  build-depends:
+      base >=3 && <5,
+      primitive -any,
+      vector >=0.8
+  default-language: Haskell2010
+  hs-source-dirs: src
+  other-modules:
+      Data.Bit.Internal
+      Data.Vector.Unboxed.Bit.Internal
+  ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-type-defaults
 
-Library
-  hs-source-dirs:       src
-  ghc-options:          -fwarn-unused-imports -fwarn-unused-binds -fwarn-type-defaults
-  exposed-modules:      Data.Bit
-                        Data.Vector.Unboxed.Bit
-                        Data.Vector.Unboxed.Mutable.Bit
-  other-modules:        Data.Bit.Internal
-                        Data.Vector.Unboxed.Bit.Internal
-  build-depends:        base >= 3 && < 5,
-                        primitive,
-                        vector >= 0.8
-  if impl(ghc == 7.2.1)
-    ghc-options:        -trust vector 
+test-suite bitvec-tests
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  build-depends:
+    base >=3,
+    bitvec -any,
+    HUnit -any,
+    primitive -any,
+    vector >=0.8,
+    test-framework -any,
+    test-framework-hunit -any,
+    test-framework-quickcheck2 -any,
+    QuickCheck >=2.10,
+    quickcheck-classes >=0.6.1
+  default-language: Haskell2010
+  hs-source-dirs: test
+  other-modules:
+    Support
+    Tests.Bit
+    Tests.MVector
+    Tests.SetOps
+    Tests.Vector
+  ghc-options: -threaded -fwarn-unused-imports -fwarn-unused-binds
diff --git a/src/Data/Bit.hs b/src/Data/Bit.hs
--- a/src/Data/Bit.hs
+++ b/src/Data/Bit.hs
@@ -4,6 +4,9 @@
 #else
 #define safe
 #endif
+
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
 module Data.Bit
      ( Bit
      , fromBool
@@ -28,8 +31,8 @@
 liftInt2  :: (Int -> Int -> Int) -> (Bit -> Bit -> Bit)
 liftInt2  op x y = fromIntegral (fromIntegral x `op` fromIntegral y)
 
--- | The 'Num' instance is currently based on integers mod 2, so (+) and (-) are 
--- XOR, (*) is AND, and all the unary operations are identities.  Saturating 
+-- | The 'Num' instance is currently based on integers mod 2, so (+) and (-) are
+-- XOR, (*) is AND, and all the unary operations are identities.  Saturating
 -- operations would also be a sensible alternative.
 instance Num Bit where
     fromInteger = fromBool . odd
@@ -44,9 +47,9 @@
     toRational (Bit True ) = 1
 
 instance Integral Bit where
-    quotRem _ 0 = error "divide by zero"
-    quotRem x 1 = (x, 0)
-    
+    quotRem _ (Bit False) = error "divide by zero"
+    quotRem x (Bit True ) = (x, 0)
+
     divMod = quotRem
     toInteger (Bit False) = 0
     toInteger (Bit True ) = 1
@@ -55,33 +58,34 @@
     (.&.) = liftBool2 (&&)
     (.|.) = liftBool2 (||)
     xor = liftBool2 (/=)
-    
+
     complement (Bit x) = Bit (not x)
-    
+
     shift b 0 = b
-    shift b _ = 0
-    
+    shift _ _ = 0
+
     rotate = const
-    
+
     bit 0 = 1
     bit _ = 0
-    
+
     setBit _ 0 = 1
     setBit b _ = b
-    
+
     clearBit _ 0 = 0
     clearBit b _ = b
-    
+
     complementBit b 0 = complement b
     complementBit b _ = b
-    
+
     testBit b 0 = toBool b
     testBit _ _ = False
-    
-    bitSize  _ = 1
-    
+
+    bitSizeMaybe _ = Just 1
+    bitSize _ = 1
+
     isSigned _ = False
-    
+
 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704
 
     popCount = fromEnum
diff --git a/src/Data/Bit/Internal.hs b/src/Data/Bit/Internal.hs
--- a/src/Data/Bit/Internal.hs
+++ b/src/Data/Bit/Internal.hs
@@ -11,7 +11,6 @@
 import safe Data.Bits
 import safe Data.List
 import safe Data.Typeable
-import safe Data.Word
 
 #if !MIN_VERSION_base(4,3,0)
 import safe Control.Monad
@@ -22,11 +21,11 @@
 #endif
 
 
-newtype Bit = Bit Bool
+newtype Bit = Bit { toBool :: Bool }
     deriving (Bounded, Eq, Ord, Typeable)
 
-fromBool    b  = Bit b
-toBool (Bit b) =     b
+fromBool :: Bool -> Bit
+fromBool b  = Bit b
 
 instance Enum Bit where
     toEnum      = fromBool . toEnum
@@ -41,37 +40,53 @@
 
 -- |The number of 'Bit's in a 'Word'.  A handy constant to have around when defining 'Word'-based bulk operations on bit vectors.
 wordSize :: Int
-wordSize = bitSize (0 :: Word)
+wordSize = finiteBitSize (0 :: Word)
 
 lgWordSize, wordSizeMask, wordSizeMaskC :: Int
-lgWordSize = lg2 wordSize
+lgWordSize = case wordSize of
+    32 -> 5
+    64 -> 6
+    _  -> lg2 wordSize
+
 wordSizeMask = wordSize - 1
 wordSizeMaskC = complement wordSizeMask
 
+divWordSize :: Bits a => a -> a
 divWordSize x = shiftR x lgWordSize
+
+modWordSize :: Int -> Int
 modWordSize x = x .&. (wordSize - 1)
 
+mulWordSize :: Bits a => a -> a
 mulWordSize x = shiftL x lgWordSize
 
 -- number of words needed to store n bits
-nWords nBits = divWordSize (nBits + wordSize - 1)
+nWords :: Int -> Int
+nWords ns = divWordSize (ns + wordSize - 1)
 
 -- number of bits storable in n words
-nBits nWords = mulWordSize nWords
+nBits :: Bits a => a -> a
+nBits ns = mulWordSize ns
 
+aligned :: Int -> Bool
 aligned    x = (x .&. wordSizeMask == 0)
+
+notAligned :: Int -> Bool
 notAligned x = x /= alignDown x
 
 -- round a number of bits up to the nearest multiple of word size
+alignUp :: Int -> Int
 alignUp x
     | x == x'   = x'
     | otherwise = x' + wordSize
     where x' = alignDown x
+
 -- round a number of bits down to the nearest multiple of word size
+alignDown :: Int -> Int
 alignDown x = x .&. wordSizeMaskC
 
 readBit :: Int -> Word -> Bit
-readBit i w = fromBool (testBit w i)
+readBit i w = fromBool (w .&. (1 `unsafeShiftL` i) /= 0)
 
 extendToWord :: Bit -> Word
 extendToWord (Bit False) = 0
@@ -81,14 +96,18 @@
 mask :: Int -> Word
 mask b = m
     where
-        m   | b >= bitSize m    = complement 0
-            | b < 0             = 0
-            | otherwise         = bit b - 1
+        m   | b >= finiteBitSize m = complement 0
+            | b < 0                = 0
+            | otherwise            = bit b - 1
 
+masked :: Int -> Word -> Word
 masked b x = x .&. mask b
+
+isMasked :: Int -> Word -> Bool
 isMasked b x = (masked b x == x)
 
 -- meld 2 words by taking the low 'b' bits from 'lo' and the rest from 'hi'
+meld :: Int -> Word -> Word -> Word
 meld b lo hi = (lo .&. m) .|. (hi .&. complement m)
     where m = mask b
 
@@ -107,17 +126,17 @@
 
 -- this could be given a more general type, but it would be wrong; it works for any fixed word size, but only for unsigned types
 reverseWord :: Word -> Word
-reverseWord x = foldr swap x masks
+reverseWord xx = foldr swap xx masks
     where
         nextMask (d, x) = (d', x `xor` shift x d')
             where !d' = d `shiftR` 1
-        
-        !(_:masks) = 
+
+        !(_:masks) =
             takeWhile ((0 /=) . snd)
-            (iterate nextMask (bitSize x, maxBound))
-        
+            (iterate nextMask (finiteBitSize xx, maxBound))
+
         swap (n, m) x = ((x .&. m) `shiftL`  n) .|. ((x .&. complement m) `shiftR`  n)
-        
+
         -- TODO: is an unrolled version like "loop lgWordSize" faster than the generic implementation above?  If so, can that be fixed?
         -- loop 0 x = x
         -- loop 1 x = loop 0 (((x .&. 0x5555555555555555) `shiftL`  1) .|. ((x .&. 0xAAAAAAAAAAAAAAAA) `shiftR`  1))
@@ -128,6 +147,7 @@
         -- loop 6 x = loop 5 (((x .&. 0x00000000FFFFFFFF) `shiftL` 32) .|. ((x .&. 0xFFFFFFFF00000000) `shiftR` 32))
         -- loop _ _ = error "reverseWord only implemented for up to 64 bit words!"
 
+reversePartialWord :: Int -> Word -> Word
 reversePartialWord n w
     | n >= wordSize = reverseWord w
     | otherwise     = reverseWord w `shiftR` (wordSize - n)
diff --git a/src/Data/Vector/Unboxed/Bit.hs b/src/Data/Vector/Unboxed/Bit.hs
--- a/src/Data/Vector/Unboxed/Bit.hs
+++ b/src/Data/Vector/Unboxed/Bit.hs
@@ -9,47 +9,47 @@
 module Data.Vector.Unboxed.Bit
      ( module Data.Bit
      , module U
-     
+
      , wordSize
      , wordLength
      , fromWords
      , toWords
      , indexWord
-     
+
      , pad
      , padWith
-     
+
      , zipWords
-     
+
      , union
      , unions
-     
+
      , intersection
      , intersections
      , difference
      , symDiff
-     
+
      , invert
-     
+
      , select
      , selectBits
-     
+
      , exclude
      , excludeBits
-     
+
      , countBits
      , listBits
-     
+
      , and
      , or
-     
+
      , any
      , anyBits
      , all
      , allBits
-     
+
      , reverse
-     
+
      , first
      , findIndex
      ) where
@@ -79,7 +79,7 @@
 fromWords n ws
     | n <= m    = BitVec 0 n (V.take (nWords n) ws)
     | otherwise = pad n (BitVec 0 m ws)
-    where 
+    where
          m = nBits (V.length ws)
 
 -- |Given a vector of bits, extract an unboxed vector of words.  If the bits don't completely fill the words, the last word will be zero-padded.
@@ -97,9 +97,9 @@
         zipWords (flip op) ys xs
     | otherwise =  runST $ do
         -- TODO: eliminate this extra traversal
-        xs <- V.thaw xs
-        B.zipInPlace op xs ys
-        Unsafe.unsafeFreeze xs
+        xs1 <- V.thaw xs
+        B.zipInPlace op xs1 ys
+        Unsafe.unsafeFreeze xs1
 
 -- |(internal) N-ary 'zipWords' with specified output length.  Makes all kinds of assumptions; mainly only valid for union and intersection.
 {-# INLINE zipMany #-}
@@ -110,11 +110,18 @@
     P.mapM_ (B.zipInPlace op ys) xss
     Unsafe.unsafeFreeze ys
 
-union        = zipWords (.|.)
+union :: Vector Bit -> Vector Bit -> Vector Bit
+union = zipWords (.|.)
+
+intersection :: Vector Bit -> Vector Bit -> Vector Bit
 intersection = zipWords (.&.)
-difference   = zipWords diff
-symDiff      = zipWords xor
 
+difference :: Vector Bit -> Vector Bit -> Vector Bit
+difference = zipWords diff
+
+symDiff :: Vector Bit -> Vector Bit -> Vector Bit
+symDiff = zipWords xor
+
 unions :: Int -> [U.Vector Bit] -> U.Vector Bit
 unions = zipMany 0 (.|.)
 
@@ -130,26 +137,26 @@
     Unsafe.unsafeFreeze ys
 
 -- | Given a vector of bits and a vector of things, extract those things for which the corresponding bit is set.
--- 
+--
 -- For example, @select (V.map (fromBool . p) x) x == V.filter p x@.
 select :: (V.Vector v1 Bit, V.Vector v2 t) => v1 Bit -> v2 t -> [t]
 select is xs = L.unfoldr next 0
     where
         n = min (V.length is) (V.length xs)
-        
+
         next j
             | j >= n             = Nothing
             | toBool (is V.! j)  = Just (xs V.! j, j + 1)
             | otherwise          = next           (j + 1)
 
 -- | Given a vector of bits and a vector of things, extract those things for which the corresponding bit is unset.
--- 
+--
 -- For example, @exclude (V.map (fromBool . p) x) x == V.filter (not . p) x@.
 exclude :: (V.Vector v1 Bit, V.Vector v2 t) => v1 Bit -> v2 t -> [t]
 exclude is xs = L.unfoldr next 0
     where
         n = min (V.length is) (V.length xs)
-        
+
         next j
             | j >= n             = Nothing
             | toBool (is V.! j)  = next           (j + 1)
@@ -157,15 +164,15 @@
 
 selectBits :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit
 selectBits is xs = runST $ do
-    xs <- U.thaw xs
-    n <- B.selectBitsInPlace is xs
-    Unsafe.unsafeFreeze (MV.take n xs)
+    xs1 <- U.thaw xs
+    n <- B.selectBitsInPlace is xs1
+    Unsafe.unsafeFreeze (MV.take n xs1)
 
 excludeBits :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit
 excludeBits is xs = runST $ do
-    xs <- U.thaw xs
-    n <- B.excludeBitsInPlace is xs
-    Unsafe.unsafeFreeze (MV.take n xs)
+    xs1 <- U.thaw xs
+    n <- B.excludeBitsInPlace is xs1
+    Unsafe.unsafeFreeze (MV.take n xs1)
 
 -- |return the number of ones in a bit vector
 countBits :: U.Vector Bit -> Int
@@ -182,7 +189,7 @@
         !n = V.length v
         loop bs !i
             | i >= n    = bs []
-            | otherwise = 
+            | otherwise =
                 loop (bs . bitsInWord i (indexWord v i)) (i + wordSize)
 
 -- | 'True' if all bits in the vector are set
@@ -205,12 +212,14 @@
             | otherwise = (indexWord v i /= 0)
                         || loop (i + wordSize)
 
+all :: (Bit -> Bool) -> Vector Bit -> Bool
 all p = case (p 0, p 1) of
     (False, False) -> U.null
     (False,  True) -> allBits 1
     (True,  False) -> allBits 0
     (True,   True) -> flip seq True
 
+any :: (Bit -> Bool) -> Vector Bit -> Bool
 any p = case (p 0, p 1) of
     (False, False) -> flip seq False
     (False,  True) -> anyBits 1
@@ -218,11 +227,11 @@
     (True,   True) -> not . U.null
 
 allBits, anyBits :: Bit -> U.Vector Bit -> Bool
-allBits 0 = not . or
-allBits 1 = and
+allBits (Bit False) = not . or
+allBits (Bit True) = and
 
-anyBits 0 = not . and
-anyBits 1 = or
+anyBits (Bit False) = not . and
+anyBits (Bit True) = or
 
 reverse :: U.Vector Bit -> U.Vector Bit
 reverse xs = runST $ do
@@ -239,11 +248,12 @@
         !n = V.length xs
         !ff | toBool b  = ffs
             | otherwise = ffs . complement
-        
+
         loop !i
             | i >= n    = Nothing
             | otherwise = fmap (i +) (ff (indexWord xs i)) `mplus` loop (i + wordSize)
 
+findIndex :: (Bit -> Bool) -> Vector Bit -> Maybe Int
 findIndex p xs = case (p 0, p 1) of
     (False, False) -> Nothing
     (False,  True) -> first 1 xs
diff --git a/src/Data/Vector/Unboxed/Bit/Internal.hs b/src/Data/Vector/Unboxed/Bit/Internal.hs
--- a/src/Data/Vector/Unboxed/Bit/Internal.hs
+++ b/src/Data/Vector/Unboxed/Bit/Internal.hs
@@ -2,14 +2,18 @@
 {-# LANGUAGE CPP                   #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE ViewPatterns          #-}
+
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
 module Data.Vector.Unboxed.Bit.Internal
      ( Bit
      , U.Vector(BitVec)
      , U.MVector(BitMVec)
-     
+
      , padWith
      , pad
-     
+
      , indexWord
      , readWord
      , writeWord
@@ -24,7 +28,6 @@
 import qualified Data.Vector.Generic         as V
 import qualified Data.Vector.Generic.Mutable as MV
 import qualified Data.Vector.Unboxed         as U
-import           Data.Word
 
 -- Ints are offset and length in bits
 data instance U.MVector s Bit = BitMVec !Int !Int !(U.MVector s Word)
@@ -34,7 +37,7 @@
 
 -- | read a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.).  If the offset is such that the word extends past the end of the vector, the result is zero-padded.
 indexWord :: U.Vector Bit -> Int -> Word
-indexWord (BitVec 0 n v) i 
+indexWord (BitVec 0 n v) i
     | aligned i         = masked b lo
     | j + 1 == nWords n = masked b (extractWord k lo 0 )
     | otherwise         = masked b (extractWord k lo hi)
@@ -63,7 +66,7 @@
 -- | write a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.).  If the offset is such that the word extends past the end of the vector, the word is truncated and as many low-order bits as possible are written.
 writeWord :: PrimMonad m => U.MVector (PrimState m) Bit -> Int -> Word -> m ()
 writeWord (BitMVec 0 n v) i x
-    | aligned i    = 
+    | aligned i    =
         if b < wordSize
             then do
                 y <- MV.read v j
@@ -108,68 +111,170 @@
 
 instance U.Unbox Bit
 
+loMask :: Int -> Word
+loMask n = 1 `shiftL` n - 1
+
+hiMask :: Int -> Word
+hiMask n = complement (1 `shiftL` n - 1)
+
 instance MV.MVector U.MVector Bit where
 #if MIN_VERSION_vector(0,11,0)
-    basicInitialize (BitMVec _ _ v) = MV.basicInitialize v
+    {-# INLINE basicInitialize #-}
+    basicInitialize (BitMVec _ 0 _) = pure ()
+    basicInitialize (BitMVec 0 n v) = case modWordSize n of
+        0 -> MV.basicInitialize v
+        nMod -> do
+            let vLen = MV.basicLength v
+            MV.basicInitialize (MV.slice 0 (vLen - 1) v)
+            MV.modify v (\val -> val .&. hiMask nMod) (vLen - 1)
+    basicInitialize (BitMVec s n v) = case modWordSize (s + n) of
+        0 -> do
+            let vLen = MV.basicLength v
+            MV.basicInitialize (MV.slice 1 (vLen - 1) v)
+            MV.modify v (\val -> val .&. loMask s) 0
+        nMod -> do
+            let vLen = MV.basicLength v
+                lohiMask = loMask s .|. hiMask nMod
+            if vLen == 1
+                then MV.modify v (\val -> val .&. lohiMask) 0
+                else do
+                    MV.basicInitialize (MV.slice 1 (vLen - 2) v)
+                    MV.modify v (\val -> val .&. loMask s) 0
+                    MV.modify v (\val -> val .&. hiMask nMod) (vLen - 1)
 #endif
-    
+
+    {-# INLINE basicUnsafeNew #-}
     basicUnsafeNew       n   = liftM (BitMVec 0 n) (MV.basicUnsafeNew       (nWords n))
+
+    {-# INLINE basicUnsafeReplicate #-}
     basicUnsafeReplicate n x = liftM (BitMVec 0 n) (MV.basicUnsafeReplicate (nWords n) (extendToWord x))
-    
+
+    {-# INLINE basicOverlaps #-}
     basicOverlaps (BitMVec _ _ v1) (BitMVec _ _ v2) = MV.basicOverlaps v1 v2
-    
+
+    {-# INLINE basicLength #-}
     basicLength      (BitMVec _ n _)     = n
-    basicUnsafeRead  (BitMVec 0 _ v) i   = liftM (readBit (modWordSize i)) (MV.basicUnsafeRead v (divWordSize i))
-    basicUnsafeRead  (BitMVec s n v) i   = MV.basicUnsafeRead (BitMVec 0 (n + s) v) (i + s)
-    basicUnsafeWrite (BitMVec 0 _ v) i x = do
-        let j = divWordSize i; k = modWordSize i
+
+    {-# INLINE basicUnsafeRead #-}
+    basicUnsafeRead  (BitMVec s _ v) !i'   = let i = s + i' in liftM (readBit (modWordSize i)) (MV.basicUnsafeRead v (divWordSize i))
+
+    {-# INLINE basicUnsafeWrite #-}
+    basicUnsafeWrite (BitMVec s _ v) !i' !x = do
+        let i = s + i'
+        let j = divWordSize i; k = modWordSize i; kk = 1 `unsafeShiftL` k
         w <- MV.basicUnsafeRead v j
-        MV.basicUnsafeWrite v j $ if toBool x
-            then setBit   w k
-            else clearBit w k
-        
-    basicUnsafeWrite (BitMVec s n v) i x =
-         MV.basicUnsafeWrite (BitMVec 0 (n + s) v) (i + s) x
-    basicSet         (BitMVec _ _ v)   x = MV.basicSet v (extendToWord x)
-    
+        when (fromBool (w .&. kk /= 0) /= x) $
+            MV.basicUnsafeWrite v j (w `xor` kk)
+
+    {-# INLINE basicClear #-}
+    basicClear _ = pure ()
+
+    {-# INLINE basicSet #-}
+    basicSet (BitMVec _ 0 _) _ = pure ()
+    basicSet (BitMVec 0 n v) (extendToWord -> x) = case modWordSize n of
+        0 ->  MV.basicSet v x
+        nMod -> do
+            let vLen = MV.basicLength v
+            MV.basicSet (MV.slice 0 (vLen - 1) v) x
+            MV.modify v (\val -> val .&. hiMask nMod .|. x .&. loMask nMod) (vLen - 1)
+    basicSet (BitMVec s n v) (extendToWord -> x) = case modWordSize (s + n) of
+        0 -> do
+            let vLen = MV.basicLength v
+            MV.basicSet (MV.slice 1 (vLen - 1) v) x
+            MV.modify v (\val -> val .&. loMask s .|. x .&. hiMask s) 0
+        nMod -> do
+            let vLen = MV.basicLength v
+                lohiMask = loMask s .|. hiMask nMod
+            if vLen == 1
+                then MV.modify v (\val -> val .&. lohiMask .|. x .&. complement lohiMask) 0
+                else do
+                    MV.basicSet (MV.slice 1 (vLen - 2) v) x
+                    MV.modify v (\val -> val .&. loMask s .|. x .&. hiMask s) 0
+                    MV.modify v (\val -> val .&. hiMask nMod .|. x .&. loMask nMod) (vLen - 1)
+
     {-# INLINE basicUnsafeCopy #-}
+    basicUnsafeCopy _ (BitMVec _ 0 _) = pure ()
+    basicUnsafeCopy (BitMVec 0 _ dst) (BitMVec 0 n src) = case modWordSize n of
+        0 -> MV.basicUnsafeCopy dst src
+        nMod -> do
+            let vLen = MV.basicLength src
+            MV.basicUnsafeCopy (MV.slice 0 (vLen - 1) dst) (MV.slice 0 (vLen - 1) src)
+            valSrc <- MV.basicUnsafeRead src (vLen - 1)
+            MV.modify dst (\val -> val .&. hiMask nMod .|. valSrc .&. loMask nMod) (vLen - 1)
+    basicUnsafeCopy (BitMVec dstShift _ dst) (BitMVec s n src)
+        | dstShift == s = case modWordSize (s + n) of
+            0 -> do
+                let vLen = MV.basicLength src
+                MV.basicUnsafeCopy (MV.slice 1 (vLen - 1) dst) (MV.slice 1 (vLen - 1) src)
+                valSrc <- MV.basicUnsafeRead src 0
+                MV.modify dst (\val -> val .&. loMask s .|. valSrc .&. hiMask s) 0
+            nMod -> do
+                let vLen = MV.basicLength src
+                    lohiMask = loMask s .|. hiMask nMod
+                if vLen == 1
+                    then do
+                        valSrc <- MV.basicUnsafeRead src 0
+                        MV.modify dst (\val -> val .&. lohiMask .|. valSrc .&. complement lohiMask) 0
+                    else do
+                        MV.basicUnsafeCopy (MV.slice 1 (vLen - 2) dst) (MV.slice 1 (vLen - 2) src)
+                        valSrcFirst <- MV.basicUnsafeRead src 0
+                        MV.modify dst (\val -> val .&. loMask s .|. valSrcFirst .&. hiMask s) 0
+                        valSrcLast <- MV.basicUnsafeRead src (vLen - 1)
+                        MV.modify dst (\val -> val .&. hiMask nMod .|. valSrcLast .&. loMask nMod) (vLen - 1)
+
     basicUnsafeCopy dst@(BitMVec _ len _) src = do_copy 0
       where
         n = alignUp len
-        
+
         do_copy i
             | i < n = do
                 x <- readWord src i
                 writeWord dst i x
                 do_copy (i+wordSize)
             | otherwise = return ()
-    
+
+    {-# INLINE basicUnsafeMove #-}
+    basicUnsafeMove !dst !src@(BitMVec srcShift srcLen _)
+        | MV.basicOverlaps dst src = do
+            -- Align shifts of src and srcCopy to speed up basicUnsafeCopy srcCopy src
+            -- TODO write tests on copy and move inside array
+            srcCopy <- BitMVec srcShift srcLen <$> MV.basicUnsafeNew (nWords (srcShift + srcLen))
+            MV.basicUnsafeCopy srcCopy src
+            MV.basicUnsafeCopy dst srcCopy
+        | otherwise = MV.basicUnsafeCopy dst src
+
     {-# INLINE basicUnsafeSlice #-}
     basicUnsafeSlice offset n (BitMVec s _ v) =
         BitMVec relStartBit n (MV.basicUnsafeSlice startWord (endWord - startWord) v)
-            where 
+            where
                 absStartBit = s + offset
                 relStartBit = modWordSize absStartBit
                 absEndBit   = absStartBit + n
                 endWord     = nWords absEndBit
                 startWord   = divWordSize absStartBit
 
+    {-# INLINE basicUnsafeGrow #-}
+    basicUnsafeGrow (BitMVec s n v) by =
+        BitMVec s (n + by) <$> if delta == 0 then pure v else MV.basicUnsafeGrow v delta
+        where
+            delta = nWords (s + n + by) - nWords (s + n)
+
+
 instance V.Vector U.Vector Bit where
     basicUnsafeFreeze (BitMVec s n v) = liftM (BitVec  s n) (V.basicUnsafeFreeze v)
     basicUnsafeThaw   (BitVec  s n v) = liftM (BitMVec s n) (V.basicUnsafeThaw   v)
     basicLength       (BitVec  _ n _) = n
-    
-    basicUnsafeIndexM (BitVec 0 _ v) i = liftM (readBit (modWordSize i)) (V.basicUnsafeIndexM v (divWordSize i))
-    basicUnsafeIndexM (BitVec s n v) i = V.basicUnsafeIndexM (BitVec 0 (n + s) v) (i + s)
-    
+
+    basicUnsafeIndexM (BitVec s _ v) !i' = let i = s + i' in liftM (readBit (modWordSize i)) (V.basicUnsafeIndexM v (divWordSize i))
+
     basicUnsafeCopy dst src = do
-        src <- V.basicUnsafeThaw src
-        MV.basicUnsafeCopy dst src
-    
+        src1 <- V.basicUnsafeThaw src
+        MV.basicUnsafeCopy dst src1
+
     {-# INLINE basicUnsafeSlice #-}
     basicUnsafeSlice offset n (BitVec s _ v) =
         BitVec relStartBit n (V.basicUnsafeSlice startWord (endWord - startWord) v)
-            where 
+            where
                 absStartBit = s + offset
                 relStartBit = modWordSize absStartBit
                 absEndBit   = absStartBit + n
@@ -177,20 +282,20 @@
                 startWord   = divWordSize absStartBit
 
 padWith :: Bit -> Int -> U.Vector Bit -> U.Vector Bit
-padWith b n' bitvec@(BitVec s n v)
+padWith b n' bitvec@(BitVec _ n _)
     | n' <= n   = bitvec
     | otherwise = runST $ do
         mv@(BitMVec mvStart _ ws) <- MV.replicate n' b
         when (mvStart /= 0) (fail "assertion failed: offset /= 0 after MV.new")
-        
+
         V.copy (MV.basicUnsafeSlice 0 n mv) bitvec
-        
+
         when (notAligned n) $ do
             let i = divWordSize n
                 j = modWordSize n
             x <- MV.read ws i
             MV.write ws i (meld j x (extendToWord b))
-        
+
         V.unsafeFreeze mv
 
 pad :: Int -> U.Vector Bit -> U.Vector Bit
diff --git a/src/Data/Vector/Unboxed/Mutable/Bit.hs b/src/Data/Vector/Unboxed/Mutable/Bit.hs
--- a/src/Data/Vector/Unboxed/Mutable/Bit.hs
+++ b/src/Data/Vector/Unboxed/Mutable/Bit.hs
@@ -9,21 +9,21 @@
 module Data.Vector.Unboxed.Mutable.Bit
      ( module Data.Bit
      , module U
-     
+
      , wordSize
      , wordLength
      , cloneFromWords
      , cloneToWords
      , readWord
      , writeWord
-     
+
      , mapMInPlaceWithIndex
      , mapInPlaceWithIndex
      , mapMInPlace
      , mapInPlace
-     
+
      , zipInPlace
-     
+
      , unionInPlace
      , intersectionInPlace
      , differenceInPlace
@@ -31,18 +31,18 @@
      , invertInPlace
      , selectBitsInPlace
      , excludeBitsInPlace
-     
+
      , countBits
      , listBits
-     
+
      , and
      , or
-     
+
      , any
      , anyBits
      , all
      , allBits
-     
+
      , reverseInPlace
      ) where
 
@@ -73,26 +73,26 @@
     let wordsNeeded = nWords n
         wordsGiven  = MV.length ws
         fillNeeded  = wordsNeeded - wordsGiven
-    
+
     v <- MV.new wordsNeeded
-    
+
     if fillNeeded > 0
         then do
             MV.copy (MV.slice          0 wordsGiven v) ws
             MV.set  (MV.slice wordsGiven fillNeeded v) 0
         else do
             MV.copy v (MV.slice 0 wordsNeeded ws)
-    
+
     return (BitMVec 0 n v)
 
 -- |clone a vector of bits to a new unboxed vector of words.  If the bits don't completely fill the words, the last word will be zero-padded.
 cloneToWords :: PrimMonad m => U.MVector (PrimState m) Bit -> m (U.MVector (PrimState m) Word)
 cloneToWords v@(BitMVec s n ws)
     | aligned s = do
-        ws <- MV.clone (MV.slice (divWordSize s) (nWords n) ws)
+        ws1 <- MV.clone (MV.slice (divWordSize s) (nWords n) ws)
         when (not (aligned n)) $ do
-            readWord v (alignDown n) >>= MV.write ws (divWordSize n)
-        return ws
+            readWord v (alignDown n) >>= MV.write ws1 (divWordSize n)
+        return ws1
     | otherwise = cloneWords v
 
 -- |Map a function over a bit vector one 'Word' at a time ('wordSize' bits at a time).  The function will be passed the bit index (which will always be 'wordSize'-aligned) and the current value of the corresponding word.  The returned word will be written back to the vector.  If there is a partial word at the end of the vector, it will be zero-padded when passed to the function and truncated when the result is written back to the array.
@@ -101,13 +101,13 @@
     PrimMonad m =>
         (Int -> Word -> m Word)
      -> U.MVector (PrimState m) Bit -> m ()
-mapMInPlaceWithIndex f xs@(BitMVec 0 n v) = loop 0 0
+mapMInPlaceWithIndex f xs@(BitMVec 0 _ v) = loop 0 0
     where
         !n_ = alignDown (MV.length xs)
         loop !i !j
             | i >= n_   = when (n_ /= MV.length xs) $ do
                 readWord xs i >>= f i >>= writeWord xs i
-                
+
             | otherwise = do
                 MV.read v j >>= f i >>= MV.write v j
                 loop (i + wordSize) (j + 1)
@@ -147,15 +147,15 @@
         -- WARNING: relies on guarantee by mapMInPlaceWithIndex that index will always be aligned!
         !n = min (MV.length xs) (V.length ys)
         {-# INLINE g #-}
-        g !i !x = 
+        g !i !x =
             let !w = masked (n2 - i) (v V.! divWordSize i)
              in f x w
 zipInPlace f xs ys =
     mapInPlaceWithIndex g (MV.basicUnsafeSlice 0 n xs)
-    where 
+    where
         !n = min (MV.length xs) (V.length ys)
         {-# INLINE g #-}
-        g !i !x = 
+        g !i !x =
             let !w = indexWord ys i
              in f x w
 
@@ -261,11 +261,11 @@
     (True,   True) -> return . not . MV.null
 
 allBits, anyBits :: PrimMonad m => Bit -> U.MVector (PrimState m) Bit -> m Bool
-allBits 0 = liftM not . or
-allBits 1 = and
+allBits (Bit False) = liftM not . or
+allBits (Bit True) = and
 
-anyBits 0 = liftM not . and
-anyBits 1 = or
+anyBits (Bit False) = liftM not . and
+anyBits (Bit True) = or
 
 reverseInPlace :: PrimMonad m => U.MVector (PrimState m) Bit -> m ()
 reverseInPlace xs = loop 0 (MV.length xs)
@@ -274,26 +274,26 @@
             | i' <= j'  = do
                 x <- readWord xs i
                 y <- readWord xs j'
-                
+
                 writeWord xs i  (reverseWord y)
                 writeWord xs j' (reverseWord x)
-                
+
                 loop i' j'
             | i' < j    = do
                 let w = (j - i) `shiftR` 1
                     k  = j - w
                 x <- readWord xs i
                 y <- readWord xs k
-                
+
                 writeWord xs i (meld w (reversePartialWord w y) x)
                 writeWord xs k (meld w (reversePartialWord w x) y)
-                
+
                 loop i' j'
             | i  < j    = do
                 let w = j - i
                 x <- readWord xs i
                 writeWord xs i (meld w (reversePartialWord w x) x)
             | otherwise = return ()
-            where    
+            where
                 !i' = i + wordSize
                 !j' = j - wordSize
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -8,7 +8,8 @@
 import Tests.MVector (mvectorTests)
 import Tests.Vector (vectorTests)
 
-main = defaultMain 
+main :: IO ()
+main = defaultMain
     [ bitTests
     , mvectorTests
     , setOpTests
diff --git a/test/Support.hs b/test/Support.hs
--- a/test/Support.hs
+++ b/test/Support.hs
@@ -1,20 +1,20 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE RankNTypes          #-}
+
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
 module Support where
 
-import Control.Applicative
 import Control.Monad.ST
 import Data.Bit
 import Data.Bits
-import Data.Word
 import qualified Data.Vector.Generic         as V
 import qualified Data.Vector.Generic.Mutable as M
 import qualified Data.Vector.Generic.New     as N
 import qualified Data.Vector.Unboxed         as U
 import Data.Vector.Unboxed.Bit (wordSize)
 import Test.QuickCheck
-import Test.QuickCheck.Function
 
 instance Arbitrary Bit where
     arbitrary = fromBool <$> arbitrary
@@ -26,9 +26,6 @@
 instance Function Bit where
     function f = functionMap toBool fromBool f
 
-instance Function Word where
-    function f = functionMap (fromIntegral :: Word -> Int) fromIntegral f
-
 instance (Arbitrary a, U.Unbox a) => Arbitrary (U.Vector a) where
     arbitrary = V.new <$> arbitrary
 
@@ -41,7 +38,7 @@
 -- this instance is designed to make sure that the arbitrary vectors we work with are not all nicely aligned; we need to deal with cases where the vector is a weird slice of some other vector.
 instance (V.Vector v a, Arbitrary a) => Arbitrary (N.New v a) where
     arbitrary = frequency
-        [ (10, newFromList <$> arbitrary) 
+        [ (10, newFromList <$> arbitrary)
         , (1,  N.drop <$> arbitrary <*> arbitrary)
         , (1,  N.take <$> arbitrary <*> arbitrary)
         , (1,  slice <$> arbitrary <*> arbitrary <*> arbitrary)
@@ -50,6 +47,7 @@
                  let (s', n') = trimSlice s n (M.length v)
                   in M.slice s' n' v
 
+trimSlice :: Integral a => a -> a -> a -> (a, a)
 trimSlice s n l = (s', n')
     where
          s' | l == 0    = 0
@@ -57,6 +55,7 @@
          n' | s' == 0   = 0
             | otherwise = n `mod` (l - s')
 
+sliceList :: Int -> Int -> [a] -> [a]
 sliceList s n = take n . drop s
 
 packBitsToWord :: [Bit] -> (Word, [Bit])
@@ -79,25 +78,29 @@
 writeWordL xs n w = pre ++ writeWordL post 0 w
     where (pre, post) = splitAt n xs
 
+prop_writeWordL_preserves_length :: [Bit] -> NonNegative Int -> Word -> Bool
 prop_writeWordL_preserves_length xs (NonNegative n) w =
     length (writeWordL xs n w) == length xs
 
+prop_writeWordL_preserves_prefix :: [Bit] -> NonNegative Int -> Word -> Bool
 prop_writeWordL_preserves_prefix xs (NonNegative n) w =
     take n (writeWordL xs n w) == take n xs
 
+prop_writeWordL_preserves_suffix :: [Bit] -> NonNegative Int -> Word -> Bool
 prop_writeWordL_preserves_suffix xs (NonNegative n) w =
     drop (n + wordSize) (writeWordL xs n w) == drop (n + wordSize) xs
 
-prop_writeWordL_readWordL xs n w =
+prop_writeWordL_readWordL :: [Bit] -> Int -> Bool
+prop_writeWordL_readWordL xs n =
     writeWordL xs n (readWordL xs n) == xs
 
 -- the opposite is more work to state, but these tests together with the simplicity of the definitions makes me reasonably confident in these as a reference implementation.
 
 withNonEmptyMVec :: Eq t =>
        (U.Vector Bit -> t)
-    -> (forall s. U.MVector s Bit -> ST s t) 
+    -> (forall s. U.MVector s Bit -> ST s t)
     -> Property
 withNonEmptyMVec f g = forAll arbitrary $ \xs ->
-     let xs' = V.new xs 
+     let xs' = V.new xs
       in not (U.null xs') ==> f xs' == runST (N.run xs >>= g)
 
diff --git a/test/Tests/Bit.hs b/test/Tests/Bit.hs
--- a/test/Tests/Bit.hs
+++ b/test/Tests/Bit.hs
@@ -2,20 +2,25 @@
 
 import Data.Bit
 import Data.Bits
-import Test.HUnit
-import Test.Framework (testGroup)
+import Test.HUnit ((@?=))
+import Test.Framework (Test, testGroup)
 import Test.Framework.Providers.HUnit (testCase)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
 
-b0 = 0 :: Bit
-b1 = 1 :: Bit
+b0 :: Bit
+b0 = 0
 
+b1 :: Bit
+b1 = 1
+
+testOp :: (Eq a, Show a) => String -> (Bit -> a) -> (Bit -> a) -> [Test]
 testOp opName op rOp =
     [ testCase (unwords [opName, show x])
         (op x @?= rOp x)
     | x <- [0, 1 :: Bit]
     ]
 
+testBinop :: (Eq a, Show a) => String -> (Bit -> Bit -> a) -> (Bit -> Bit -> a) -> [Test]
 testBinop opName op rOp =
     [ testCase (unwords [show x, opName, show y])
         (op x y @?= rOp x y)
@@ -23,6 +28,7 @@
     , y <- [0, 1 :: Bit]
     ]
 
+bitTests :: Test
 bitTests = testGroup "Data.Bit"
     [ testGroup "basic assertions"
         [ testCase "toBool 0"       (toBool 0       @?= False)
@@ -43,4 +49,5 @@
         ]
     ]
 
+prop_fromInteger :: Integer -> Bool
 prop_fromInteger x = fromInteger x == fromBool (odd x)
diff --git a/test/Tests/MVector.hs b/test/Tests/MVector.hs
--- a/test/Tests/MVector.hs
+++ b/test/Tests/MVector.hs
@@ -5,19 +5,26 @@
 import Control.Monad
 import Control.Monad.ST
 import Data.Bit
+import Data.Proxy
 import Data.STRef
 import qualified Data.Vector.Generic             as V
+import qualified Data.Vector.Generic.Mutable     as M (basicInitialize, basicSet)
 import qualified Data.Vector.Generic.New         as N
 import qualified Data.Vector.Unboxed.Bit         as B
 import qualified Data.Vector.Unboxed.Mutable.Bit as U
 import qualified Data.Vector.Unboxed.Mutable     as M
-import Data.Word
-import Test.Framework (testGroup)
+import Test.Framework (Test, testGroup)
+import Test.Framework.Providers.HUnit (testCase)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
+import Test.HUnit (assertEqual)
+import Test.QuickCheck
+import Test.QuickCheck.Classes
 
+mvectorTests :: Test
 mvectorTests = testGroup "Data.Vector.Unboxed.Mutable.Bit"
     [ testGroup "Data.Vector.Unboxed.Mutable functions"
         [ testProperty "slice"          prop_slice_def
+        , testProperty "grow"           prop_grow_def
         ]
     , testProperty "wordLength"     prop_wordLength_def
     , testGroup "Read/write Words"
@@ -33,21 +40,167 @@
     , testProperty "countBits"      prop_countBits_def
     , testProperty "listBits"       prop_listBits_def
     , testProperty "reverseInPlace" prop_reverseInPlace_def
+    , testGroup "MVector laws" $ map (uncurry testProperty) $ lawsProperties $ muvectorLaws (Proxy :: Proxy Bit)
+    , testCase "basicInitialize 1" case_write_init_read1
+    , testCase "basicInitialize 2" case_write_init_read2
+    , testCase "basicInitialize 3" case_write_init_read3
+    , testCase "basicInitialize 4" case_write_init_read4
+    , testCase "basicSet 1" case_write_set_read1
+    , testCase "basicSet 2" case_write_set_read2
+    , testCase "basicSet 3" case_write_set_read3
+    , testCase "basicSet 4" case_write_set_read4
+    , testCase "basicSet 5" case_set_read1
+    , testCase "basicSet 6" case_set_read2
+    , testCase "basicSet 7" case_set_read3
+    , testCase "basicUnsafeCopy1" case_write_copy_read1
+    , testCase "basicUnsafeCopy2" case_write_copy_read2
+    , testCase "basicUnsafeCopy3" case_write_copy_read3
+    , testCase "basicUnsafeCopy4" case_write_copy_read4
+    , testCase "basicUnsafeCopy5" case_write_copy_read5
     ]
 
+case_write_init_read1 :: IO ()
+case_write_init_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.write arr 0 (fromBool True)
+    M.basicInitialize (M.slice 1 1 arr)
+    M.read arr 0
+
+case_write_init_read2 :: IO ()
+case_write_init_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.write arr 1 (fromBool True)
+    M.basicInitialize (M.slice 0 1 arr)
+    M.read arr 1
+
+case_write_init_read3 :: IO ()
+case_write_init_read3 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.write arr 0 (fromBool True)
+    M.write arr 1 (fromBool True)
+    M.basicInitialize (M.slice 1 0 arr)
+    (,) <$> M.read arr 0 <*> M.read arr 1
+
+case_write_init_read4 :: IO ()
+case_write_init_read4 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do
+    arr <- M.new 3
+    M.write arr 0 (fromBool True)
+    M.write arr 2 (fromBool True)
+    M.basicInitialize (M.slice 1 1 arr)
+    (,) <$> M.read arr 0 <*> M.read arr 2
+
+case_write_set_read1 :: IO ()
+case_write_set_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.write arr 0 (fromBool True)
+    M.basicSet (M.slice 1 1 arr) (fromBool False)
+    M.read arr 0
+
+case_write_set_read2 :: IO ()
+case_write_set_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.write arr 1 (fromBool True)
+    M.basicSet (M.slice 0 1 arr) (fromBool False)
+    M.read arr 1
+
+case_write_set_read3 :: IO ()
+case_write_set_read3 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.write arr 0 (fromBool True)
+    M.write arr 1 (fromBool True)
+    M.basicSet (M.slice 1 0 arr) (fromBool False)
+    (,) <$> M.read arr 0 <*> M.read arr 1
+
+case_write_set_read4 :: IO ()
+case_write_set_read4 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do
+    arr <- M.new 3
+    M.write arr 0 (fromBool True)
+    M.write arr 2 (fromBool True)
+    M.basicSet (M.slice 1 1 arr) (fromBool False)
+    (,) <$> M.read arr 0 <*> M.read arr 2
+
+case_set_read1 :: IO ()
+case_set_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 1
+    M.basicSet arr (fromBool True)
+    M.read arr 0
+
+case_set_read2 :: IO ()
+case_set_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 2
+    M.basicSet (M.slice 1 1 arr) (fromBool True)
+    M.read arr 1
+
+case_set_read3 :: IO ()
+case_set_read3 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    arr <- M.new 192
+    M.basicSet (M.slice 71 121 arr) (fromBool True)
+    M.read arr 145
+
+case_write_copy_read1 :: IO ()
+case_write_copy_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    src <- M.slice 37 28 <$> M.new 65
+    M.write src 27 (fromBool True)
+    dst <- M.slice 37 28 <$> M.new 65
+    M.copy dst src
+    M.read dst 27
+
+case_write_copy_read2 :: IO ()
+case_write_copy_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    src <- M.slice 32 33 <$> M.new 65
+    M.write src 0 (fromBool True)
+    dst <- M.slice 32 33 <$> M.new 65
+    M.copy dst src
+    M.read dst 0
+
+case_write_copy_read3 :: IO ()
+case_write_copy_read3 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    src <- M.slice 1 1 <$> M.new 2
+    M.write src 0 (fromBool True)
+    dst <- M.slice 1 1 <$> M.new 2
+    M.copy dst src
+    M.read dst 0
+
+case_write_copy_read4 :: IO ()
+case_write_copy_read4 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    src <- M.slice 12 52 <$> M.new 64
+    M.write src 22 (fromBool True)
+    dst <- M.slice 12 52 <$> M.new 64
+    M.copy dst src
+    M.read dst 22
+
+case_write_copy_read5 :: IO ()
+case_write_copy_read5 = assertEqual "should be equal" (fromBool True) $ runST $ do
+    src <- M.slice 48 80 <$> M.new 128
+    M.write src 46 (fromBool True)
+    dst <- M.slice 48 80 <$> M.new 128
+    M.copy dst src
+    M.read dst 46
+
 prop_slice_def :: Int -> Int -> N.New U.Vector Bit -> Bool
 prop_slice_def s n xs = runST $ do
     let xs' = V.new xs
         (s', n') = trimSlice s n (V.length xs')
-    xs <- N.run xs
-    xs <- V.unsafeFreeze (M.slice s' n' xs)
-    
-    return (B.toList xs == sliceList s' n' (B.toList xs'))
+    xs1 <- N.run xs
+    xs2 <- V.unsafeFreeze (M.slice s' n' xs1)
 
+    return (B.toList xs2 == sliceList s' n' (B.toList xs'))
+
+prop_grow_def :: B.Vector Bit -> NonNegative Int -> Bool
+prop_grow_def xs (NonNegative m) = runST $ do
+    let n = B.length xs
+    v0 <- B.thaw xs
+    v1 <- M.grow v0 m
+    fv0 <- B.freeze v0
+    fv1 <- B.freeze v1
+    return (fv0 == B.take n fv1)
+
+prop_readWord_def :: Int -> Property
 prop_readWord_def n = withNonEmptyMVec
     (\xs ->   readWordL (B.toList xs) (n `mod` V.length xs))
     (\xs -> U.readWord            xs  (n `mod` M.length xs))
 
+prop_writeWord_def :: Int -> Word -> Property
 prop_writeWord_def n w = withNonEmptyMVec
     (\xs -> B.fromList
                $ writeWordL (B.toList xs) (n `mod` V.length xs) w)
@@ -60,7 +213,7 @@
     == runST (fmap U.length (N.run xs >>= U.cloneToWords))
 
 prop_cloneFromWords_def :: Int -> Int -> N.New U.Vector Word -> Bool
-prop_cloneFromWords_def maxN n' ws 
+prop_cloneFromWords_def maxN n' ws
     =  runST (N.run ws >>= U.cloneFromWords n >>= V.unsafeFreeze)
     == B.fromWords n (V.new ws)
     where n = n' `mod` maxN
@@ -71,27 +224,27 @@
     == B.toWords (V.new xs)
 
 prop_mapMInPlaceWithIndex_leftToRight :: N.New U.Vector Bit -> Bool
-prop_mapMInPlaceWithIndex_leftToRight xs 
+prop_mapMInPlaceWithIndex_leftToRight xs
     = runST $ do
         x <- newSTRef (-1)
-        xs <- N.run xs
+        xs1 <- N.run xs
         let f i _ = do
                 j <- readSTRef x
                 writeSTRef x i
                 return (if i > j then maxBound else 0)
-        U.mapMInPlaceWithIndex f xs
-        xs <- V.unsafeFreeze xs
-        return (all toBool (B.toList xs))
+        U.mapMInPlaceWithIndex f xs1
+        xs2 <- V.unsafeFreeze xs1
+        return (all toBool (B.toList xs2))
 
 prop_mapMInPlaceWithIndex_aligned :: N.New U.Vector Bit -> Bool
 prop_mapMInPlaceWithIndex_aligned xs = runST $ do
     ok <- newSTRef True
-    xs <- N.run xs
+    xs1 <- N.run xs
     let aligned i   = i `mod` U.wordSize == 0
         f i x = do
             when (not (aligned i)) (writeSTRef ok False)
             return x
-    U.mapMInPlaceWithIndex f xs
+    U.mapMInPlaceWithIndex f xs1
     readSTRef ok
 
 prop_countBits_def :: N.New U.Vector Bit -> Bool
diff --git a/test/Tests/SetOps.hs b/test/Tests/SetOps.hs
--- a/test/Tests/SetOps.hs
+++ b/test/Tests/SetOps.hs
@@ -5,27 +5,27 @@
 import Data.Bit
 import Data.Bits
 import qualified Data.Vector.Unboxed.Bit as U
-import Data.Word
-import Test.Framework (testGroup)
+import Test.Framework (Test, testGroup)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
 
+setOpTests :: Test
 setOpTests = testGroup "Set operations"
     [ testProperty "union"          prop_union_def
     , testProperty "intersection"   prop_intersection_def
     , testProperty "difference"     prop_difference_def
     , testProperty "symDiff"        prop_symDiff_def
-    
+
     , testProperty "unions"         (prop_unions_def 1000)
     , testProperty "intersections"  (prop_unions_def 1000)
-    
+
     , testProperty "invert"         prop_invert_def
-    
+
     , testProperty "select"         prop_select_def
     , testProperty "exclude"        prop_exclude_def
 
     , testProperty "selectBits"     prop_selectBits_def
     , testProperty "excludeBits"    prop_excludeBits_def
-    
+
     , testProperty "countBits"      prop_countBits_def
     ]
 
diff --git a/test/Tests/Vector.hs b/test/Tests/Vector.hs
--- a/test/Tests/Vector.hs
+++ b/test/Tests/Vector.hs
@@ -6,16 +6,16 @@
 import Data.Bits
 import Data.List
 import qualified Data.Vector.Unboxed.Bit as U
-import Data.Word
-import Test.Framework (testGroup)
+import Test.Framework (Test, testGroup)
 import Test.Framework.Providers.HUnit (testCase)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
-import Test.HUnit
+import Test.HUnit ((@?=))
 import Test.QuickCheck
 import Test.QuickCheck.Function
 
+vectorTests :: Test
 vectorTests = testGroup "Data.Vector.Unboxed.Bit"
-    [ testCase     "wordSize correct"           (U.wordSize @?= bitSize (0 :: Word))
+    [ testCase     "wordSize correct"           (U.wordSize @?= finiteBitSize (0 :: Word))
     , testGroup "Data.Vector.Unboxed functions"
         [ testProperty "toList . fromList == id"    prop_toList_fromList
         , testProperty "fromList . toList == id"    prop_fromList_toList
@@ -79,7 +79,7 @@
                 (w, bs') -> w : loop bs'
 
 prop_indexWord_def :: Int -> U.Vector Bit -> Property
-prop_indexWord_def n xs 
+prop_indexWord_def n xs
     = not (U.null xs)
     ==> readWordL  (U.toList xs) n'
      == U.indexWord xs           n'
