diff --git a/Data/HashMap/Array.hs b/Data/HashMap/Array.hs
--- a/Data/HashMap/Array.hs
+++ b/Data/HashMap/Array.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples #-}
-{-# OPTIONS_GHC -funbox-strict-fields #-}
+{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
 
 -- | Zero based arrays.
 --
@@ -48,15 +48,18 @@
     , map'
     , traverse
     , filter
+    , toList
     ) where
 
 import qualified Data.Traversable as Traversable
 import Control.Applicative (Applicative)
 import Control.DeepSeq
-import Control.Monad.ST
+import Control.Monad.ST hiding (runST)
 import GHC.Exts
 import GHC.ST (ST(..))
 import Prelude hiding (filter, foldr, length, map, read)
+
+import Data.HashMap.Unsafe (runST)
 
 ------------------------------------------------------------------------
 
diff --git a/Data/HashMap/Base.hs b/Data/HashMap/Base.hs
--- a/Data/HashMap/Base.hs
+++ b/Data/HashMap/Base.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE BangPatterns, CPP, DeriveDataTypeable, MagicHash #-}
-{-# OPTIONS_GHC -funbox-strict-fields #-}
+{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
 
 module Data.HashMap.Base
     (
@@ -36,6 +36,7 @@
       -- * Difference and intersection
     , difference
     , intersection
+    , intersectionWith
 
       -- * Folds
     , foldl'
@@ -76,7 +77,7 @@
 
 import Control.Applicative ((<$>), Applicative(pure))
 import Control.DeepSeq (NFData(rnf))
-import Control.Monad.ST (ST, runST)
+import Control.Monad.ST (ST)
 import Data.Bits ((.&.), (.|.), complement)
 import qualified Data.Foldable as Foldable
 import qualified Data.List as L
@@ -89,6 +90,7 @@
 import qualified Data.Hashable as H
 import Data.Hashable (Hashable)
 import Data.HashMap.PopCount (popCount)
+import Data.HashMap.Unsafe (runST)
 import Data.HashMap.UnsafeShift (unsafeShiftL, unsafeShiftR)
 import Data.Typeable (Typeable)
 
@@ -103,6 +105,7 @@
 hash = fromIntegral . H.hash
 
 data Leaf k v = L !k v
+  deriving (Eq)
 
 instance (NFData k, NFData v) => NFData (Leaf k v) where
     rnf (L k v) = rnf k `seq` rnf v
@@ -149,10 +152,22 @@
 instance Traversable (HashMap k) where
     traverse f = traverseWithKey (const f)
 
--- NOTE: This is just a placeholder.
 instance (Eq k, Eq v) => Eq (HashMap k v) where
-    a == b = toList a == toList b
+    (==) = equal
 
+equal :: (Eq k, Eq v) => HashMap k v -> HashMap k v -> Bool
+equal (BitmapIndexed b1 ary1) (BitmapIndexed b2 ary2) =
+    b1 == b2 && A.toList ary1 == A.toList ary2
+equal (Leaf k1 v1) (Leaf k2 v2) =
+    k1 == k2 && v1 == v2
+equal (Full ary1) (Full ary2) =
+    A.toList ary1 == A.toList ary2
+equal (Collision k1 ary1) (Collision k2 ary2) =
+    k1 == k2 && A.length ary1 == A.length ary2
+      && L.null (A.toList ary1 L.\\ A.toList ary2)
+equal Empty Empty = True
+equal _     _     = False
+
 ------------------------------------------------------------------------
 -- * Construction
 
@@ -254,42 +269,38 @@
 -- key in this map.  If this map previously contained a mapping for
 -- the key, the old value is replaced.
 insert :: (Eq k, Hashable k) => k -> v -> HashMap k v -> HashMap k v
-insert k0 v0 m0 = runST (go h0 k0 v0 0 m0)
+insert k0 v0 m0 = go h0 k0 v0 0 m0
   where
     h0 = hash k0
-    go !h !k x !_ Empty = return $! Leaf h (L k x)
+    go !h !k x !_ Empty = Leaf h (L k x)
     go h k x s t@(Leaf hy l@(L ky y))
         | hy == h = if ky == k
                     then if x `ptrEq` y
-                         then return t
-                         else return $! Leaf h (L k x)
-                    else return $! collision h l (L k x)
-        | otherwise = two s h k x hy ky y
+                         then t
+                         else Leaf h (L k x)
+                    else collision h l (L k x)
+        | otherwise = runST (two s h k x hy ky y)
     go h k x s t@(BitmapIndexed b ary)
-        | b .&. m == 0 = do
-            !ary' <- A.insert' ary i $! Leaf h (L k x)
-            return $! bitmapIndexedOrFull (b .|. m) ary'
-        | otherwise = do
-            st <- A.index_ ary i
-            !st' <- go h k x (s+bitsPerSubkey) st
-            if st' `ptrEq` st
-                then return t
-                else do
-                    ary' <- A.update' ary i st'
-                    return $! BitmapIndexed b ary'
+        | b .&. m == 0 =
+            let ary' = A.insert ary i $! Leaf h (L k x)
+            in bitmapIndexedOrFull (b .|. m) ary'
+        | otherwise =
+            let !st  = A.index ary i
+                !st' = go h k x (s+bitsPerSubkey) st
+            in if st' `ptrEq` st
+               then t
+               else BitmapIndexed b (A.update ary i st')
       where m = mask h s
             i = sparseIndex b m
-    go h k x s t@(Full ary) = do
-        st <- A.index_ ary i
-        !st' <- go h k x (s+bitsPerSubkey) st
-        if st' `ptrEq` st
-            then return t
-            else do
-                ary' <- update16' ary i st'
-                return $! Full ary'
+    go h k x s t@(Full ary) =
+        let !st  = A.index ary i
+            !st' = go h k x (s+bitsPerSubkey) st
+        in if st' `ptrEq` st
+            then t
+            else Full (update16 ary i st')
       where i = index h s
     go h k x s t@(Collision hy v)
-        | h == hy   = return $! Collision h (updateOrSnocWith const k x v)
+        | h == hy   = Collision h (updateOrSnocWith const k x v)
         | otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE insert #-}
@@ -338,7 +349,7 @@
   where
     go s h1 k1 v1 h2 k2 v2
         | bp1 == bp2 = do
-            st <- go (s+bitsPerSubkey) h1 k1 v1 h2 k2 v2 
+            st <- go (s+bitsPerSubkey) h1 k1 v1 h2 k2 v2
             ary <- A.singleton' st
             return $! BitmapIndexed bp1 ary
         | otherwise  = do
@@ -362,34 +373,34 @@
 -- >   where f new old = new + old
 insertWith :: (Eq k, Hashable k) => (v -> v -> v) -> k -> v -> HashMap k v
             -> HashMap k v
-insertWith f k0 v0 m0 = runST (go h0 k0 v0 0 m0)
+insertWith f k0 v0 m0 = go h0 k0 v0 0 m0
   where
     h0 = hash k0
-    go !h !k x !_ Empty = return $! Leaf h (L k x)
+    go !h !k x !_ Empty = Leaf h (L k x)
     go h k x s (Leaf hy l@(L ky y))
         | hy == h = if ky == k
-                    then return $! Leaf h (L k (f x y))
-                    else return $! collision h l (L k x)
-        | otherwise = two s h k x hy ky y
+                    then Leaf h (L k (f x y))
+                    else collision h l (L k x)
+        | otherwise = runST (two s h k x hy ky y)
     go h k x s (BitmapIndexed b ary)
-        | b .&. m == 0 = do
-            ary' <- A.insert' ary i $! Leaf h (L k x)
-            return $! bitmapIndexedOrFull (b .|. m) ary'
-        | otherwise = do
-            st <- A.index_ ary i
-            st' <- go h k x (s+bitsPerSubkey) st
-            ary' <- A.update' ary i st'
-            return $! BitmapIndexed b ary'
+        | b .&. m == 0 =
+            let ary' = A.insert ary i $! Leaf h (L k x)
+            in bitmapIndexedOrFull (b .|. m) ary'
+        | otherwise =
+            let st   = A.index ary i
+                st'  = go h k x (s+bitsPerSubkey) st
+                ary' = A.update ary i st'
+            in BitmapIndexed b ary'
       where m = mask h s
             i = sparseIndex b m
-    go h k x s (Full ary) = do
-        st <- A.index_ ary i
-        st' <- go h k x (s+bitsPerSubkey) st
-        ary' <- update16' ary i st'
-        return $! Full ary'
+    go h k x s (Full ary) =
+        let st   = A.index ary i
+            st'  = go h k x (s+bitsPerSubkey) st
+            ary' = update16 ary i st'
+        in Full ary'
       where i = index h s
     go h k x s t@(Collision hy v)
-        | h == hy   = return $! Collision h (updateOrSnocWith f k x v)
+        | h == hy   = Collision h (updateOrSnocWith f k x v)
         | otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE insertWith #-}
@@ -434,54 +445,48 @@
 -- | /O(log n)/ Remove the mapping for the specified key from this map
 -- if present.
 delete :: (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
-delete k0 m0 = runST (go h0 k0 0 m0)
+delete k0 m0 = go h0 k0 0 m0
   where
     h0 = hash k0
-    go !_ !_ !_ Empty = return Empty
+    go !_ !_ !_ Empty = Empty
     go h k _ t@(Leaf hy (L ky _))
-        | hy == h && ky == k = return Empty
-        | otherwise          = return t
+        | hy == h && ky == k = Empty
+        | otherwise          = t
     go h k s t@(BitmapIndexed b ary)
-        | b .&. m == 0 = return t
-        | otherwise = do
+        | b .&. m == 0 = t
+        | otherwise =
             let !st = A.index ary i
-            !st' <- go h k (s+bitsPerSubkey) st
-            if st' `ptrEq` st
-                then return t
+                !st' = go h k (s+bitsPerSubkey) st
+            in if st' `ptrEq` st
+                then t
                 else case st' of
-                Empty | A.length ary == 1 -> return Empty
-                      | otherwise -> do
-                          ary' <- A.delete' ary i
-                          return $! BitmapIndexed (b .&. complement m) ary'
-                _ -> do
-                    ary' <- A.update' ary i st'
-                    return $! BitmapIndexed b ary'
+                Empty | A.length ary == 1 -> Empty
+                      | otherwise -> BitmapIndexed (b .&. complement m) (A.delete ary i)
+                _ -> BitmapIndexed b (A.update ary i st')
       where m = mask h s
             i = sparseIndex b m
-    go h k s t@(Full ary) = do
-        let !st = A.index ary i
-        !st' <- go h k (s+bitsPerSubkey) st
-        if st' `ptrEq` st
-            then return t
+    go h k s t@(Full ary) =
+        let !st   = A.index ary i
+            !st' = go h k (s+bitsPerSubkey) st
+        in if st' `ptrEq` st
+            then t
             else case st' of
-            Empty -> do
-                ary' <- A.delete' ary i
-                let bm = fullNodeMask .&. complement (1 `unsafeShiftL` i)
-                return $! BitmapIndexed bm ary'
-            _ -> do
-                ary' <- A.update' ary i st'
-                return $! Full ary'
+            Empty ->
+                let ary' = A.delete ary i
+                    bm   = fullNodeMask .&. complement (1 `unsafeShiftL` i)
+                in BitmapIndexed bm ary'
+            _ -> Full (A.update ary i st')
       where i = index h s
     go h k _ t@(Collision hy v)
         | h == hy = case indexOf k v of
             Just i
                 | A.length v == 2 ->
                     if i == 0
-                    then return $! Leaf h (A.index v 1)
-                    else return $! Leaf h (A.index v 0)
-                | otherwise -> return $! Collision h (A.delete v i)
-            Nothing -> return t
-        | otherwise = return t
+                    then Leaf h (A.index v 1)
+                    else Leaf h (A.index v 0)
+                | otherwise -> Collision h (A.delete v i)
+            Nothing -> t
+        | otherwise = t
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE delete #-}
 #endif
@@ -623,20 +628,20 @@
     mary <- A.new_ (popCount b')
     -- iterate over nonzero bits of b1 .|. b2
     -- it would be nice if we could shift m by more than 1 each time
-    let hasBit b m = b .&. m /= 0
+    let ba = b1 .&. b2
         go !i !i1 !i2 !m
-            | m > b'                     = return ()
-            | hasBit b1 m && hasBit b2 m = do
+            | m > b'        = return ()
+            | b' .&. m == 0 = go i i1 i2 (m `unsafeShiftL` 1)
+            | ba .&. m /= 0 = do
                 A.write mary i $! f (A.index ary1 i1) (A.index ary2 i2)
                 go (i+1) (i1+1) (i2+1) (m `unsafeShiftL` 1)
-            | hasBit b1 m                = do
+            | b1 .&. m /= 0 = do
                 A.write mary i =<< A.index_ ary1 i1
                 go (i+1) (i1+1) (i2  ) (m `unsafeShiftL` 1)
-            | hasBit b2 m                = do
+            | otherwise     = do
                 A.write mary i =<< A.index_ ary2 i2
                 go (i+1) (i1  ) (i2+1) (m `unsafeShiftL` 1)
-            | otherwise                  = go i i1 i2 (m `unsafeShiftL` 1)
-    go 0 0 0 1
+    go 0 0 0 (b' .&. negate b') -- XXX: b' must be non-zero
     return mary
     -- TODO: For the case where b1 .&. b2 == b1, i.e. when one is a
     -- subset of the other, we could use a slightly simpler algorithm,
@@ -665,6 +670,9 @@
                            A.map' (\ (L k v) -> L k (f v)) ary
 {-# INLINE map #-}
 
+-- TODO: We should be able to use mutation to create the new
+-- 'HashMap'.
+
 -- | /O(n)/ Transform this map by accumulating an Applicative result
 -- from every value.
 traverseWithKey :: Applicative f => (k -> v1 -> f v2) -> HashMap k v1
@@ -682,7 +690,7 @@
 ------------------------------------------------------------------------
 -- * Difference and intersection
 
--- | /O(n+m)/ Difference of two maps. Return elements of the first map
+-- | /O(n*log m)/ Difference of two maps. Return elements of the first map
 -- not existing in the second.
 difference :: (Eq k, Hashable k) => HashMap k v -> HashMap k w -> HashMap k v
 difference a b = foldlWithKey' go empty a
@@ -694,7 +702,7 @@
 {-# INLINABLE difference #-}
 #endif
 
--- | /O(n+m)/ Intersection of two maps. Return elements of the first
+-- | /O(n*log m)/ Intersection of two maps. Return elements of the first
 -- map for keys existing in the second.
 intersection :: (Eq k, Hashable k) => HashMap k v -> HashMap k w -> HashMap k v
 intersection a b = foldlWithKey' go empty a
@@ -704,6 +712,20 @@
                  _      -> m
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE intersection #-}
+#endif
+
+-- | /O(n+m)/ Intersection of two maps. If a key occurs in both maps
+-- the provided function is used to combine the values from the two
+-- maps.
+intersectionWith :: (Eq k, Hashable k) => (v1 -> v2 -> v3) -> HashMap k v1
+                 -> HashMap k v2 -> HashMap k v3
+intersectionWith f a b = foldlWithKey' go empty a
+  where
+    go m k v = case lookup k b of
+                 Just w -> insert k (f v w) m
+                 _      -> m
+#if __GLASGOW_HASKELL__ >= 700
+{-# INLINABLE intersectionWith #-}
 #endif
 
 ------------------------------------------------------------------------
diff --git a/Data/HashMap/Lazy.hs b/Data/HashMap/Lazy.hs
--- a/Data/HashMap/Lazy.hs
+++ b/Data/HashMap/Lazy.hs
@@ -62,6 +62,7 @@
       -- * Difference and intersection
     , difference
     , intersection
+    , intersectionWith
 
       -- * Folds
     , foldl'
diff --git a/Data/HashMap/Strict.hs b/Data/HashMap/Strict.hs
--- a/Data/HashMap/Strict.hs
+++ b/Data/HashMap/Strict.hs
@@ -63,6 +63,7 @@
       -- * Difference and intersection
     , difference
     , intersection
+    , intersectionWith
 
       -- * Folds
     , foldl'
@@ -93,8 +94,8 @@
 import qualified Data.HashMap.Array as A
 import qualified Data.HashMap.Base as HM
 import Data.HashMap.Base hiding (
-    adjust, fromList, fromListWith, insert, insertWith, map, singleton,
-    unionWith)
+    adjust, fromList, fromListWith, insert, insertWith, intersectionWith, map,
+    singleton, unionWith)
 
 ------------------------------------------------------------------------
 -- * Construction
@@ -124,34 +125,34 @@
 -- >   where f new old = new + old
 insertWith :: (Eq k, Hashable k) => (v -> v -> v) -> k -> v -> HashMap k v
            -> HashMap k v
-insertWith f k0 !v0 m0 = runST (go h0 k0 v0 0 m0)
+insertWith f k0 !v0 m0 = go h0 k0 v0 0 m0
   where
     h0 = hash k0
-    go !h !k x !_ Empty = return $ Leaf h (L k x)
+    go !h !k x !_ Empty = Leaf h (L k x)
     go h k x s (Leaf hy l@(L ky y))
         | hy == h = if ky == k
-                    then let !v' = f x y in return $! Leaf h (L k v')
-                    else return $! collision h l (L k x)
-        | otherwise = two s h k x hy ky y
+                    then let !v' = f x y in Leaf h (L k v')
+                    else collision h l (L k x)
+        | otherwise = runST (two s h k x hy ky y)
     go h k x s (BitmapIndexed b ary)
-        | b .&. m == 0 = do
-            ary' <- A.insert' ary i $! Leaf h (L k x)
-            return $! bitmapIndexedOrFull (b .|. m) ary'
-        | otherwise = do
-            st <- A.index_ ary i
-            st' <- go h k x (s+bitsPerSubkey) st
-            ary' <- A.update' ary i st'
-            return $! BitmapIndexed b ary'
+        | b .&. m == 0 =
+            let ary' = A.insert ary i $! Leaf h (L k x)
+            in bitmapIndexedOrFull (b .|. m) ary'
+        | otherwise =
+            let st   = A.index ary i
+                st'  = go h k x (s+bitsPerSubkey) st
+                ary' = A.update ary i st'
+            in BitmapIndexed b ary'
       where m = mask h s
             i = sparseIndex b m
-    go h k x s (Full ary) = do
-        st <- A.index_ ary i
-        st' <- go h k x (s+bitsPerSubkey) st
-        ary' <- update16' ary i st'
-        return $! Full ary'
+    go h k x s (Full ary) =
+        let st   = A.index ary i
+            st'  = go h k x (s+bitsPerSubkey) st
+            ary' = update16 ary i st'
+        in Full ary'
       where i = index h s
     go h k x s t@(Collision hy v)
-        | h == hy   = return $! Collision h (updateOrSnocWith f k x v)
+        | h == hy   = Collision h (updateOrSnocWith f k x v)
         | otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE insertWith #-}
@@ -329,6 +330,23 @@
 {-# INLINE map #-}
 
 -- TODO: Should we add a strict traverseWithKey?
+
+------------------------------------------------------------------------
+-- * Difference and intersection
+
+-- | /O(n+m)/ Intersection of two maps. If a key occurs in both maps
+-- the provided function is used to combine the values from the two
+-- maps.
+intersectionWith :: (Eq k, Hashable k) => (v1 -> v2 -> v3) -> HashMap k v1
+                 -> HashMap k v2 -> HashMap k v3
+intersectionWith f a b = foldlWithKey' go empty a
+  where
+    go m k v = case HM.lookup k b of
+                 Just w -> insert k (f v w) m
+                 _      -> m
+#if __GLASGOW_HASKELL__ >= 700
+{-# INLINABLE intersectionWith #-}
+#endif
 
 ------------------------------------------------------------------------
 -- ** Lists
diff --git a/Data/HashMap/Unsafe.hs b/Data/HashMap/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/Data/HashMap/Unsafe.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE MagicHash, Rank2Types, UnboxedTuples #-}
+
+-- | This module exports a workaround for this bug:
+--
+--    http://hackage.haskell.org/trac/ghc/ticket/5916
+--
+-- Please read the comments in ghc/libraries/base/GHC/ST.lhs to
+-- understand what's going on here.
+--
+-- Code that uses this module should be compiled with -fno-full-laziness
+module Data.HashMap.Unsafe
+    ( runST
+    ) where
+
+import GHC.Base (realWorld#)
+import GHC.ST hiding (runST, runSTRep)
+
+-- | Return the value computed by a state transformer computation.
+-- The @forall@ ensures that the internal state used by the 'ST'
+-- computation is inaccessible to the rest of the program.
+runST :: (forall s. ST s a) -> a
+runST st = runSTRep (case st of { ST st_rep -> st_rep })
+{-# INLINE runST #-}
+
+runSTRep :: (forall s. STRep s a) -> a
+runSTRep st_rep = case st_rep realWorld# of
+                        (# _, r #) -> r
+{-# INLINE [0] runSTRep #-}
diff --git a/tests/HashMapProperties.hs b/tests/HashMapProperties.hs
--- a/tests/HashMapProperties.hs
+++ b/tests/HashMapProperties.hs
@@ -71,19 +71,23 @@
 
 -- White-box test that tests the case of deleting one of two keys from
 -- a map, where the keys' hash values collide.
-pDeleteCollision :: AlwaysCollide -> AlwaysCollide -> Bool -> Property
-pDeleteCollision k1 k2 keepFst = k1 /= k2 ==> HM.member toKeep $ HM.delete toDelete $
-                                 HM.fromList [(k1, 1 :: Int), (k2, 2)]
+pDeleteCollision :: AlwaysCollide -> AlwaysCollide -> AlwaysCollide -> Int
+                 -> Property
+pDeleteCollision k1 k2 k3 idx = (k1 /= k2) && (k2 /= k3) && (k1 /= k3) ==>
+                                HM.member toKeep $ HM.delete toDelete $
+                                HM.fromList [(k1, 1 :: Int), (k2, 2), (k3, 3)]
   where
-    (toDelete, toKeep)
-        | keepFst   = (k2, k1)
-        | otherwise = (k1, k2)
-
--- White-box test that tests the case of deleting one of many keys
--- from a map, where the keys' hash values collide.
-pDeleteCollisionMany :: AlwaysCollide -> [(AlwaysCollide, Int)] -> Bool
-pDeleteCollisionMany k kvs = not $ (HM.member k) $ HM.delete k $
-                             HM.fromList ((k, 1):kvs)
+    which = idx `mod` 3
+    toDelete
+        | which == 0 = k1
+        | which == 1 = k2
+        | which == 2 = k3
+        | otherwise = error "Impossible"
+    toKeep
+        | which == 0 = k2
+        | which == 1 = k3
+        | which == 2 = k1
+        | otherwise = error "Impossible"
 
 pInsertWith :: Key -> [(Key, Int)] -> Bool
 pInsertWith k = M.insertWith (+) k 1 `eq_` HM.insertWith (+) k 1
@@ -122,6 +126,10 @@
 pIntersection xs ys = M.intersection (M.fromList xs) `eq_`
                       HM.intersection (HM.fromList xs) $ ys
 
+pIntersectionWith :: [(Key, Int)] -> [(Key, Int)] -> Bool
+pIntersectionWith xs ys = M.intersectionWith (-) (M.fromList xs) `eq_`
+                          HM.intersectionWith (-) (HM.fromList xs) $ ys
+
 ------------------------------------------------------------------------
 -- ** Folds
 
@@ -187,7 +195,6 @@
       , testProperty "insert" pInsert
       , testProperty "delete" pDelete
       , testProperty "deleteCollision" pDeleteCollision
-      , testProperty "deleteCollisionMany" pDeleteCollisionMany
       , testProperty "insertWith" pInsertWith
       , testProperty "adjust" pAdjust
       ]
@@ -206,6 +213,7 @@
     , testGroup "difference and intersection"
       [ testProperty "difference" pDifference
       , testProperty "intersection" pIntersection
+      , testProperty "intersectionWith" pIntersectionWith
       ]
     -- Filter
     , testGroup "filter"
diff --git a/tests/Regressions.hs b/tests/Regressions.hs
--- a/tests/Regressions.hs
+++ b/tests/Regressions.hs
@@ -13,6 +13,14 @@
     m = HM.fromList (zip ns (repeat []))    
     m' = HM.delete 10 m
 
+issue39 :: Assertion
+issue39 = assert $ hm1 == hm2
+  where
+    hm1 = HM.fromList ([a, b] `zip` [1, 1 :: Int ..])
+    hm2 = HM.fromList ([b, a] `zip` [1, 1 :: Int ..])
+    a = (1, -1) :: (Int, Int)
+    b = (-1, 1) :: (Int, Int)
+
 ------------------------------------------------------------------------
 -- * Test list
 
@@ -20,6 +28,7 @@
 tests =
     [
       testCase "issue32" issue32
+    , testCase "issue39" issue39
     ]
 
 ------------------------------------------------------------------------
diff --git a/unordered-containers.cabal b/unordered-containers.cabal
--- a/unordered-containers.cabal
+++ b/unordered-containers.cabal
@@ -1,5 +1,5 @@
 name:           unordered-containers
-version:        0.2.1.0
+version:        0.2.2.0
 synopsis:       Efficient hashing-based container types
 description:
   Efficient hashing-based container types.  The containers have been
@@ -32,12 +32,13 @@
     Data.HashMap.Array
     Data.HashMap.Base
     Data.HashMap.PopCount
+    Data.HashMap.Unsafe
     Data.HashMap.UnsafeShift
 
   build-depends:
-    base >= 4 && < 4.6,
-    deepseq >= 1.1 && < 1.4,
-    hashable >= 1.0.1.1 && < 1.2
+    base >= 4 && < 5,
+    deepseq >= 1.1,
+    hashable >= 1.0.1.1
 
   if impl(ghc < 7.4)
     c-sources: cbits/popc.c
@@ -57,11 +58,11 @@
 
   build-depends:
     base,
-    containers >= 0.4.1 && < 0.5,
-    hashable >= 1.0.1.1 && < 1.2,
+    containers >= 0.4.1,
+    hashable >= 1.0.1.1,
     QuickCheck >= 2.4.0.1,
-    test-framework >= 0.3.3 && < 0.6,
-    test-framework-quickcheck2 >= 0.2.9 && < 0.3,
+    test-framework >= 0.3.3,
+    test-framework-quickcheck2 >= 0.2.9,
     unordered-containers
 
   ghc-options: -Wall
@@ -74,11 +75,11 @@
 
   build-depends:
     base,
-    containers >= 0.4.1 && < 0.5,
-    hashable >= 1.0.1.1 && < 1.2,
+    containers >= 0.4.1,
+    hashable >= 1.0.1.1,
     QuickCheck >= 2.4.0.1,
-    test-framework >= 0.3.3 && < 0.6,
-    test-framework-quickcheck2 >= 0.2.9 && < 0.3,
+    test-framework >= 0.3.3,
+    test-framework-quickcheck2 >= 0.2.9,
     unordered-containers
 
   ghc-options: -Wall
@@ -91,11 +92,11 @@
 
   build-depends:
     base,
-    containers >= 0.4.2 && < 0.5,
-    hashable >= 1.0.1.1 && < 1.2,
+    containers >= 0.4.2,
+    hashable >= 1.0.1.1,
     QuickCheck >= 2.4.0.1,
-    test-framework >= 0.3.3 && < 0.6,
-    test-framework-quickcheck2 >= 0.2.9 && < 0.3,
+    test-framework >= 0.3.3,
+    test-framework-quickcheck2 >= 0.2.9,
     unordered-containers
 
   ghc-options: -Wall
@@ -108,9 +109,9 @@
 
   build-depends:
     base,
-    hashable >= 1.0.1.1 && < 1.2,
+    hashable >= 1.0.1.1,
     HUnit,
-    test-framework >= 0.3.3 && < 0.6,
+    test-framework >= 0.3.3,
     test-framework-hunit,
     unordered-containers
 
