Hello community,

here is the log from the commit of package ghc-unordered-containers for 
openSUSE:Factory checked in at 2016-06-14 23:08:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-unordered-containers (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-unordered-containers.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-unordered-containers"

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/ghc-unordered-containers/ghc-unordered-containers.changes
        2015-05-21 08:13:21.000000000 +0200
+++ 
/work/SRC/openSUSE:Factory/.ghc-unordered-containers.new/ghc-unordered-containers.changes
   2016-06-14 23:08:37.000000000 +0200
@@ -1,0 +2,24 @@
+Fri Jun 10 07:00:11 UTC 2016 - mimi...@gmail.com
+
+- update to 0.2.7.1
+- remove useless _service
+* Fix linker error related to popcnt.
+
+-------------------------------------------------------------------
+Sat Feb 20 08:32:45 UTC 2016 - mimi...@gmail.com
+
+- update to 0.2.7.0
+* support criterion-1.1
+* Add unionWithKey for hash maps.
+
+-------------------------------------------------------------------
+Tue Feb 16 20:05:18 UTC 2016 - mimi...@gmail.com
+
+- update to 0.2.6.0
+* Mark several modules as Trustworthy.
+* Add Hashable instances for HashMap and HashSet.
+* Add mapMaybe, mapMaybeWithKey, update, alter, and intersectionWithKey.
+* Add roles.
+* Add Hashable and Semigroup instances.
+
+-------------------------------------------------------------------

Old:
----
  _service
  unordered-containers-0.2.5.1.tar.gz

New:
----
  unordered-containers-0.2.7.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-unordered-containers.spec ++++++
--- /var/tmp/diff_new_pack.mhRwJk/_old  2016-06-14 23:08:37.000000000 +0200
+++ /var/tmp/diff_new_pack.mhRwJk/_new  2016-06-14 23:08:37.000000000 +0200
@@ -19,7 +19,7 @@
 %global pkg_name unordered-containers
 
 Name:           ghc-unordered-containers
-Version:        0.2.5.1
+Version:        0.2.7.1
 Release:        0
 Summary:        Efficient hashing-based container types
 License:        BSD-3-Clause

++++++ unordered-containers-0.2.5.1.tar.gz -> 
unordered-containers-0.2.7.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/CHANGES.md 
new/unordered-containers-0.2.7.1/CHANGES.md
--- old/unordered-containers-0.2.5.1/CHANGES.md 1970-01-01 01:00:00.000000000 
+0100
+++ new/unordered-containers-0.2.7.1/CHANGES.md 2016-06-09 02:00:11.000000000 
+0200
@@ -0,0 +1,30 @@
+## 0.2.7.1
+
+ * Fix linker error related to popcnt.
+
+ * Haddock improvements.
+
+ * Fix benchmark compilation when downloaded from Hackage.
+
+## 0.2.7.0
+
+ * Support criterion 1.1
+
+ * Add unionWithKey for hash maps.
+
+## 0.2.6.0
+
+ * Mark several modules as Trustworthy.
+
+ * Add Hashable instances for HashMap and HashSet.
+
+ * Add mapMaybe, mapMaybeWithKey, update, alter, and
+   intersectionWithKey.
+
+ * Add roles.
+
+ * Add Hashable and Semigroup instances.
+
+## 0.2.5.1 (2014-10-11)
+
+ * Support base-4.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/Data/HashMap/Array.hs 
new/unordered-containers-0.2.7.1/Data/HashMap/Array.hs
--- old/unordered-containers-0.2.5.1/Data/HashMap/Array.hs      2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/Data/HashMap/Array.hs      2016-06-09 
02:00:11.000000000 +0200
@@ -53,7 +53,6 @@
 import Control.Applicative (Applicative)
 #endif
 import Control.DeepSeq
-import Control.Monad.ST hiding (runST)
 -- GHC 7.7 exports toList/fromList from GHC.Exts
 -- In order to avoid warnings on previous GHC versions, we provide
 -- an explicit import list instead of only hiding the offending symbols
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/Data/HashMap/Base.hs 
new/unordered-containers-0.2.7.1/Data/HashMap/Base.hs
--- old/unordered-containers-0.2.5.1/Data/HashMap/Base.hs       2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/Data/HashMap/Base.hs       2016-06-09 
02:00:11.000000000 +0200
@@ -1,6 +1,8 @@
 {-# LANGUAGE BangPatterns, CPP, DeriveDataTypeable, MagicHash #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE PatternGuards #-}
 #if __GLASGOW_HASKELL__ >= 708
+{-# LANGUAGE RoleAnnotations #-}
 {-# LANGUAGE TypeFamilies #-}
 #endif
 {-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
@@ -26,11 +28,14 @@
     , unsafeInsert
     , delete
     , adjust
+    , update
+    , alter
 
       -- * Combine
       -- ** Union
     , union
     , unionWith
+    , unionWithKey
     , unions
 
       -- * Transformations
@@ -42,6 +47,7 @@
     , difference
     , intersection
     , intersectionWith
+    , intersectionWithKey
 
       -- * Folds
     , foldl'
@@ -50,6 +56,8 @@
     , foldrWithKey
 
       -- * Filter
+    , mapMaybe
+    , mapMaybeWithKey
     , filter
     , filterWithKey
 
@@ -79,16 +87,19 @@
     , update16M
     , update16With'
     , updateOrConcatWith
+    , updateOrConcatWithKey
+    , filterMapAux
     ) where
 
-#if __GLASGOW_HASKELL__ >= 709
-import Data.Functor ((<$>))
-#else
+#if __GLASGOW_HASKELL__ < 710
 import Control.Applicative ((<$>), Applicative(pure))
 import Data.Monoid (Monoid(mempty, mappend))
 import Data.Traversable (Traversable(..))
 import Data.Word (Word)
 #endif
+#if __GLASGOW_HASKELL__ >= 711
+import Data.Semigroup (Semigroup((<>)))
+#endif
 import Control.DeepSeq (NFData(rnf))
 import Control.Monad.ST (ST)
 import Data.Bits ((.&.), (.|.), complement)
@@ -140,6 +151,10 @@
     | Collision !Hash !(A.Array (Leaf k v))
       deriving (Typeable)
 
+#if __GLASGOW_HASKELL__ >= 708
+type role HashMap nominal representational
+#endif
+
 instance (NFData k, NFData v) => NFData (HashMap k v) where
     rnf Empty                 = ()
     rnf (BitmapIndexed _ ary) = rnf ary
@@ -153,10 +168,20 @@
 instance Foldable.Foldable (HashMap k) where
     foldr f = foldrWithKey (const f)
 
+#if __GLASGOW_HASKELL__ >= 711
+instance (Eq k, Hashable k) => Semigroup (HashMap k v) where
+  (<>) = union
+  {-# INLINE (<>) #-}
+#endif
+
 instance (Eq k, Hashable k) => Monoid (HashMap k v) where
   mempty = empty
   {-# INLINE mempty #-}
+#if __GLASGOW_HASKELL__ >= 711
+  mappend = (<>)
+#else
   mappend = union
+#endif
   {-# INLINE mappend #-}
 
 instance (Data k, Data v, Eq k, Hashable k) => Data (HashMap k v) where
@@ -213,11 +238,39 @@
     go [] [] = True
     go _  _  = False
 
-    toList' (BitmapIndexed _ ary) a = A.foldr toList' a ary
-    toList' (Full ary)            a = A.foldr toList' a ary
-    toList' l@(Leaf _ _)          a = l : a
-    toList' c@(Collision _ _)     a = c : a
-    toList' Empty                 a = a
+instance (Hashable k, Hashable v) => Hashable (HashMap k v) where
+    hashWithSalt salt hm = go salt (toList' hm [])
+      where
+        go :: Int -> [HashMap k v] -> Int
+        go s [] = s
+        go s (Leaf _ l : tl)
+          = s `hashLeafWithSalt` l `go` tl
+        -- For collisions we hashmix hash value
+        -- and then array of values' hashes sorted
+        go s (Collision h a : tl)
+          = (s `H.hashWithSalt` h) `hashCollisionWithSalt` a `go` tl
+        go s (_ : tl) = s `go` tl
+
+        hashLeafWithSalt :: Int -> Leaf k v -> Int
+        hashLeafWithSalt s (L k v) = s `H.hashWithSalt` k `H.hashWithSalt` v
+
+        hashCollisionWithSalt :: Int -> A.Array (Leaf k v) -> Int
+        hashCollisionWithSalt s
+          = L.foldl' H.hashWithSalt s . arrayHashesSorted
+
+        arrayHashesSorted :: A.Array (Leaf k v) -> [Int]
+        arrayHashesSorted = L.sort . L.map leafValueHash . A.toList
+
+        leafValueHash :: Leaf k v -> Int
+        leafValueHash (L _ v) = H.hash v
+
+  -- Helper to get 'Leaf's and 'Collision's as a list.
+toList' :: HashMap k v -> [HashMap k v] -> [HashMap k v]
+toList' (BitmapIndexed _ ary) a = A.foldr toList' a ary
+toList' (Full ary)            a = A.foldr toList' a ary
+toList' l@(Leaf _ _)          a = l : a
+toList' c@(Collision _ _)     a = c : a
+toList' Empty                 a = a
 
 -- Helper function to detect 'Leaf's and 'Collision's.
 isLeafOrCollision :: HashMap k v -> Bool
@@ -460,8 +513,7 @@
 unsafeInsertWith f k0 v0 m0 = runST (go h0 k0 v0 0 m0)
   where
     h0 = hash k0
-    go :: (Eq k, Hashable k) => Hash -> k -> v -> Shift -> HashMap k v
-       -> ST s (HashMap k v)
+    go :: Hash -> k -> v -> Shift -> HashMap k v -> ST s (HashMap k v)
     go !h !k x !_ Empty = return $! Leaf h (L k x)
     go h k x s (Leaf hy l@(L ky y))
         | hy == h = if ky == k
@@ -574,6 +626,24 @@
         | otherwise = t
 {-# INLINABLE adjust #-}
 
+-- | /O(log n)/  The expression (@'update' f k map@) updates the value @x@ at 
@k@,
+-- (if it is in the map). If (f k x) is @'Nothing', the element is deleted.
+-- If it is (@'Just' y), the key k is bound to the new value y.
+update :: (Eq k, Hashable k) => (a -> Maybe a) -> k -> HashMap k a -> HashMap 
k a
+update f = alter (>>= f)
+{-# INLINABLE update #-}
+
+
+-- | /O(log n)/  The expression (@'alter' f k map@) alters the value @x@ at 
@k@, or
+-- absence thereof. @alter@ can be used to insert, delete, or update a value 
in a
+-- map. In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.
+alter :: (Eq k, Hashable k) => (Maybe v -> Maybe v) -> k -> HashMap k v -> 
HashMap k v
+alter f k m =
+  case f (lookup k m) of
+    Nothing -> delete k m
+    Just v  -> insert k v m
+{-# INLINABLE alter #-}
+
 ------------------------------------------------------------------------
 -- * Combine
 
@@ -588,7 +658,15 @@
 -- result.
 unionWith :: (Eq k, Hashable k) => (v -> v -> v) -> HashMap k v -> HashMap k v
           -> HashMap k v
-unionWith f = go 0
+unionWith f = unionWithKey (const f)
+{-# INLINE unionWith #-}
+
+-- | /O(n+m)/ The union of two maps.  If a key occurs in both maps,
+-- the provided function (first argument) will be used to compute the
+-- result.
+unionWithKey :: (Eq k, Hashable k) => (k -> v -> v -> v) -> HashMap k v -> 
HashMap k v
+          -> HashMap k v
+unionWithKey f = go 0
   where
     -- empty vs. anything
     go !_ t1 Empty = t1
@@ -596,17 +674,17 @@
     -- leaf vs. leaf
     go s t1@(Leaf h1 l1@(L k1 v1)) t2@(Leaf h2 l2@(L k2 v2))
         | h1 == h2  = if k1 == k2
-                      then Leaf h1 (L k1 (f v1 v2))
+                      then Leaf h1 (L k1 (f k1 v1 v2))
                       else collision h1 l1 l2
         | otherwise = goDifferentHash s h1 h2 t1 t2
     go s t1@(Leaf h1 (L k1 v1)) t2@(Collision h2 ls2)
-        | h1 == h2  = Collision h1 (updateOrSnocWith f k1 v1 ls2)
+        | h1 == h2  = Collision h1 (updateOrSnocWithKey f k1 v1 ls2)
         | otherwise = goDifferentHash s h1 h2 t1 t2
     go s t1@(Collision h1 ls1) t2@(Leaf h2 (L k2 v2))
-        | h1 == h2  = Collision h1 (updateOrSnocWith (flip f) k2 v2 ls1)
+        | h1 == h2  = Collision h1 (updateOrSnocWithKey (flip . f) k2 v2 ls1)
         | otherwise = goDifferentHash s h1 h2 t1 t2
     go s t1@(Collision h1 ls1) t2@(Collision h2 ls2)
-        | h1 == h2  = Collision h1 (updateOrConcatWith f ls1 ls2)
+        | h1 == h2  = Collision h1 (updateOrConcatWithKey f ls1 ls2)
         | otherwise = goDifferentHash s h1 h2 t1 t2
     -- branch vs. branch
     go s (BitmapIndexed b1 ary1) (BitmapIndexed b2 ary2) =
@@ -668,7 +746,7 @@
       where
         m1 = mask h1 s
         m2 = mask h2 s
-{-# INLINE unionWith #-}
+{-# INLINE unionWithKey #-}
 
 -- | Strict in the result of @f@.
 unionArrayBy :: (a -> a -> a) -> Bitmap -> Bitmap -> A.Array a -> A.Array a
@@ -777,6 +855,18 @@
                  _      -> m
 {-# INLINABLE intersectionWith #-}
 
+-- | /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.
+intersectionWithKey :: (Eq k, Hashable k) => (k -> v1 -> v2 -> v3)
+                    -> HashMap k v1 -> HashMap k v2 -> HashMap k v3
+intersectionWithKey f a b = foldlWithKey' go empty a
+  where
+    go m k v = case lookup k b of
+                 Just w -> insert k (f k v w) m
+                 _      -> m
+{-# INLINABLE intersectionWithKey #-}
+
 ------------------------------------------------------------------------
 -- * Folds
 
@@ -835,14 +925,47 @@
     A.unsafeFreeze mary2
 {-# INLINE trim #-}
 
+-- | /O(n)/ Transform this map by applying a function to every value
+--   and retaining only some of them.
+mapMaybeWithKey :: (k -> v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
+mapMaybeWithKey f = filterMapAux onLeaf onColl
+  where onLeaf (Leaf h (L k v)) | Just v' <- f k v = Just (Leaf h (L k v'))
+        onLeaf _ = Nothing
+
+        onColl (L k v) | Just v' <- f k v = Just (L k v')
+                       | otherwise = Nothing
+{-# INLINE mapMaybeWithKey #-}
+
+-- | /O(n)/ Transform this map by applying a function to every value
+--   and retaining only some of them.
+mapMaybe :: (v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
+mapMaybe f = mapMaybeWithKey (const f)
+{-# INLINE mapMaybe #-}
+
 -- | /O(n)/ Filter this map by retaining only elements satisfying a
 -- predicate.
 filterWithKey :: forall k v. (k -> v -> Bool) -> HashMap k v -> HashMap k v
-filterWithKey pred = go
+filterWithKey pred = filterMapAux onLeaf onColl
+  where onLeaf t@(Leaf _ (L k v)) | pred k v = Just t
+        onLeaf _ = Nothing
+
+        onColl el@(L k v) | pred k v = Just el
+        onColl _ = Nothing
+{-# INLINE filterWithKey #-}
+
+
+-- | Common implementation for 'filterWithKey' and 'mapMaybeWithKey',
+--   allowing the former to former to reuse terms.
+filterMapAux :: forall k v1 v2
+              . (HashMap k v1 -> Maybe (HashMap k v2))
+             -> (Leaf k v1 -> Maybe (Leaf k v2))
+             -> HashMap k v1
+             -> HashMap k v2
+filterMapAux onLeaf onColl = go
   where
     go Empty = Empty
-    go t@(Leaf _ (L k v))
-        | pred k v  = t
+    go t@Leaf{}
+        | Just t' <- onLeaf t = t'
         | otherwise = Empty
     go (BitmapIndexed b ary) = filterA ary b
     go (Full ary) = filterA ary fullNodeMask
@@ -854,9 +977,9 @@
             mary <- A.new_ n
             step ary0 mary b0 0 0 1 n
       where
-        step :: A.Array (HashMap k v) -> A.MArray s (HashMap k v)
+        step :: A.Array (HashMap k v1) -> A.MArray s (HashMap k v2)
              -> Bitmap -> Int -> Int -> Bitmap -> Int
-             -> ST s (HashMap k v)
+             -> ST s (HashMap k v2)
         step !ary !mary !b i !j !bi n
             | i >= n = case j of
                 0 -> return Empty
@@ -883,9 +1006,9 @@
             mary <- A.new_ n
             step ary0 mary 0 0 n
       where
-        step :: A.Array (Leaf k v) -> A.MArray s (Leaf k v)
+        step :: A.Array (Leaf k v1) -> A.MArray s (Leaf k v2)
              -> Int -> Int -> Int
-             -> ST s (HashMap k v)
+             -> ST s (HashMap k v2)
         step !ary !mary i !j n
             | i >= n    = case j of
                 0 -> return Empty
@@ -895,10 +1018,10 @@
                                  return $! Collision h ary2
                   | otherwise -> do ary2 <- trim mary j
                                     return $! Collision h ary2
-            | pred k v  = A.write mary j el >> step ary mary (i+1) (j+1) n
+            | Just el <- onColl (A.index ary i)
+                = A.write mary j el >> step ary mary (i+1) (j+1) n
             | otherwise = step ary mary (i+1) j n
-          where el@(L k v) = A.index ary i
-{-# INLINE filterWithKey #-}
+{-# INLINE filterMapAux #-}
 
 -- | /O(n)/ Filter this map by retaining only elements which values
 -- satisfy a predicate.
@@ -928,7 +1051,7 @@
 -- ** Lists
 
 -- | /O(n)/ Return a list of this map's elements.  The list is
--- produced lazily.
+-- produced lazily. The order of its elements is unspecified.
 toList :: HashMap k v -> [(k, v)]
 toList t = build (\ c z -> foldrWithKey (curry c) z t)
 {-# INLINE toList #-}
@@ -986,7 +1109,12 @@
 
 updateOrSnocWith :: Eq k => (v -> v -> v) -> k -> v -> A.Array (Leaf k v)
                  -> A.Array (Leaf k v)
-updateOrSnocWith f k0 v0 ary0 = go k0 v0 ary0 0 (A.length ary0)
+updateOrSnocWith f = updateOrSnocWithKey (const f)
+{-# INLINABLE updateOrSnocWith #-}
+
+updateOrSnocWithKey :: Eq k => (k -> v -> v -> v) -> k -> v -> A.Array (Leaf k 
v)
+                 -> A.Array (Leaf k v)
+updateOrSnocWithKey f k0 v0 ary0 = go k0 v0 ary0 0 (A.length ary0)
   where
     go !k v !ary !i !n
         | i >= n = A.run $ do
@@ -996,12 +1124,16 @@
             A.write mary n (L k v)
             return mary
         | otherwise = case A.index ary i of
-            (L kx y) | k == kx   -> A.update ary i (L k (f v y))
+            (L kx y) | k == kx   -> A.update ary i (L k (f k v y))
                      | otherwise -> go k v ary (i+1) n
-{-# INLINABLE updateOrSnocWith #-}
+{-# INLINABLE updateOrSnocWithKey #-}
 
 updateOrConcatWith :: Eq k => (v -> v -> v) -> A.Array (Leaf k v) -> A.Array 
(Leaf k v) -> A.Array (Leaf k v)
-updateOrConcatWith f ary1 ary2 = A.run $ do
+updateOrConcatWith f = updateOrConcatWithKey (const f)
+{-# INLINABLE updateOrConcatWith #-}
+
+updateOrConcatWithKey :: Eq k => (k -> v -> v -> v) -> A.Array (Leaf k v) -> 
A.Array (Leaf k v) -> A.Array (Leaf k v)
+updateOrConcatWithKey f ary1 ary2 = A.run $ do
     -- first: look up the position of each element of ary2 in ary1
     let indices = A.map (\(L k _) -> indexOf k ary1) ary2
     -- that tells us how large the overlap is:
@@ -1019,14 +1151,14 @@
                Just i1 -> do -- key occurs in both arrays, store combination 
in position i1
                              L k v1 <- A.indexM ary1 i1
                              L _ v2 <- A.indexM ary2 i2
-                             A.write mary i1 (L k (f v1 v2))
+                             A.write mary i1 (L k (f k v1 v2))
                              go iEnd (i2+1)
                Nothing -> do -- key is only in ary2, append to end
                              A.write mary iEnd =<< A.indexM ary2 i2
                              go (iEnd+1) (i2+1)
     go n1 0
     return mary
-{-# INLINABLE updateOrConcatWith #-}
+{-# INLINABLE updateOrConcatWithKey #-}
 
 ------------------------------------------------------------------------
 -- Manually unrolled loops
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/Data/HashMap/Lazy.hs 
new/unordered-containers-0.2.7.1/Data/HashMap/Lazy.hs
--- old/unordered-containers-0.2.5.1/Data/HashMap/Lazy.hs       2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/Data/HashMap/Lazy.hs       2016-06-09 
02:00:11.000000000 +0200
@@ -47,11 +47,14 @@
     , insertWith
     , delete
     , adjust
+    , update
+    , alter
 
       -- * Combine
       -- ** Union
     , union
     , unionWith
+    , unionWithKey
     , unions
 
       -- * Transformations
@@ -63,6 +66,7 @@
     , difference
     , intersection
     , intersectionWith
+    , intersectionWithKey
 
       -- * Folds
     , foldl'
@@ -73,6 +77,8 @@
       -- * Filter
     , HM.filter
     , filterWithKey
+    , mapMaybe
+    , mapMaybeWithKey
 
       -- * Conversions
     , keys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/Data/HashMap/Strict.hs 
new/unordered-containers-0.2.7.1/Data/HashMap/Strict.hs
--- old/unordered-containers-0.2.5.1/Data/HashMap/Strict.hs     2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/Data/HashMap/Strict.hs     2016-06-09 
02:00:11.000000000 +0200
@@ -1,4 +1,4 @@
-{-# LANGUAGE BangPatterns, CPP #-}
+{-# LANGUAGE BangPatterns, CPP, PatternGuards #-}
 
 #if __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE Trustworthy #-}
@@ -47,11 +47,14 @@
     , insertWith
     , delete
     , adjust
+    , update
+    , alter
 
       -- * Combine
       -- ** Union
     , union
     , unionWith
+    , unionWithKey
     , unions
 
       -- * Transformations
@@ -63,6 +66,7 @@
     , difference
     , intersection
     , intersectionWith
+    , intersectionWithKey
 
       -- * Folds
     , foldl'
@@ -73,6 +77,8 @@
       -- * Filter
     , HM.filter
     , filterWithKey
+    , mapMaybe
+    , mapMaybeWithKey
 
       -- * Conversions
     , keys
@@ -92,8 +98,9 @@
 import qualified Data.HashMap.Array as A
 import qualified Data.HashMap.Base as HM
 import Data.HashMap.Base hiding (
-    adjust, fromList, fromListWith, insert, insertWith, intersectionWith,
-    map, mapWithKey, singleton, unionWith)
+    alter, adjust, fromList, fromListWith, insert, insertWith, 
intersectionWith,
+    intersectionWithKey, map, mapWithKey, mapMaybe, mapMaybeWithKey, singleton,
+    update, unionWith, unionWithKey)
 import Data.HashMap.Unsafe (runST)
 
 -- $strictness
@@ -227,6 +234,23 @@
         | otherwise = t
 {-# INLINABLE adjust #-}
 
+-- | /O(log n)/  The expression (@'update' f k map@) updates the value @x@ at 
@k@,
+-- (if it is in the map). If (f k x) is @'Nothing', the element is deleted.
+-- If it is (@'Just' y), the key k is bound to the new value y.
+update :: (Eq k, Hashable k) => (a -> Maybe a) -> k -> HashMap k a -> HashMap 
k a
+update f = alter (>>= f)
+{-# INLINABLE update #-}
+
+-- | /O(log n)/  The expression (@'alter' f k map@) alters the value @x@ at 
@k@, or
+-- absence thereof. @alter@ can be used to insert, delete, or update a value 
in a
+-- map. In short : @'lookup' k ('alter' f k m) = f ('lookup' k m)@.
+alter :: (Eq k, Hashable k) => (Maybe v -> Maybe v) -> k -> HashMap k v -> 
HashMap k v
+alter f k m =
+  case f (HM.lookup k m) of
+    Nothing -> delete k m
+    Just v  -> insert k v m
+{-# INLINABLE alter #-}
+
 ------------------------------------------------------------------------
 -- * Combine
 
@@ -234,7 +258,14 @@
 -- the provided function (first argument) will be used to compute the result.
 unionWith :: (Eq k, Hashable k) => (v -> v -> v) -> HashMap k v -> HashMap k v
           -> HashMap k v
-unionWith f = go 0
+unionWith f = unionWithKey (const f)
+{-# INLINE unionWith #-}
+
+-- | /O(n+m)/ The union of two maps.  If a key occurs in both maps,
+-- the provided function (first argument) will be used to compute the result.
+unionWithKey :: (Eq k, Hashable k) => (k -> v -> v -> v) -> HashMap k v -> 
HashMap k v
+          -> HashMap k v
+unionWithKey f = go 0
   where
     -- empty vs. anything
     go !_ t1 Empty = t1
@@ -242,17 +273,17 @@
     -- leaf vs. leaf
     go s t1@(Leaf h1 l1@(L k1 v1)) t2@(Leaf h2 l2@(L k2 v2))
         | h1 == h2  = if k1 == k2
-                      then leaf h1 k1 (f v1 v2)
+                      then leaf h1 k1 (f k1 v1 v2)
                       else collision h1 l1 l2
         | otherwise = goDifferentHash s h1 h2 t1 t2
     go s t1@(Leaf h1 (L k1 v1)) t2@(Collision h2 ls2)
-        | h1 == h2  = Collision h1 (updateOrSnocWith f k1 v1 ls2)
+        | h1 == h2  = Collision h1 (updateOrSnocWithKey f k1 v1 ls2)
         | otherwise = goDifferentHash s h1 h2 t1 t2
     go s t1@(Collision h1 ls1) t2@(Leaf h2 (L k2 v2))
-        | h1 == h2  = Collision h1 (updateOrSnocWith (flip f) k2 v2 ls1)
+        | h1 == h2  = Collision h1 (updateOrSnocWithKey (flip . f) k2 v2 ls1)
         | otherwise = goDifferentHash s h1 h2 t1 t2
     go s t1@(Collision h1 ls1) t2@(Collision h2 ls2)
-        | h1 == h2  = Collision h1 (updateOrConcatWith f ls1 ls2)
+        | h1 == h2  = Collision h1 (updateOrConcatWithKey f ls1 ls2)
         | otherwise = goDifferentHash s h1 h2 t1 t2
     -- branch vs. branch
     go s (BitmapIndexed b1 ary1) (BitmapIndexed b2 ary2) =
@@ -314,7 +345,7 @@
       where
         m1 = mask h1 s
         m2 = mask h2 s
-{-# INLINE unionWith #-}
+{-# INLINE unionWithKey #-}
 
 ------------------------------------------------------------------------
 -- * Transformations
@@ -336,6 +367,28 @@
 map f = mapWithKey (const f)
 {-# INLINE map #-}
 
+
+------------------------------------------------------------------------
+-- * Filter
+
+-- | /O(n)/ Transform this map by applying a function to every value
+--   and retaining only some of them.
+mapMaybeWithKey :: (k -> v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
+mapMaybeWithKey f = filterMapAux onLeaf onColl
+  where onLeaf (Leaf h (L k v)) | Just v' <- f k v = Just (leaf h k v')
+        onLeaf _ = Nothing
+
+        onColl (L k v) | Just v' <- f k v = Just (L k v')
+                       | otherwise = Nothing
+{-# INLINE mapMaybeWithKey #-}
+
+-- | /O(n)/ Transform this map by applying a function to every value
+--   and retaining only some of them.
+mapMaybe :: (v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
+mapMaybe f = mapMaybeWithKey (const f)
+{-# INLINE mapMaybe #-}
+
+
 -- TODO: Should we add a strict traverseWithKey?
 
 ------------------------------------------------------------------------
@@ -353,6 +406,18 @@
                  _      -> m
 {-# INLINABLE intersectionWith #-}
 
+-- | /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.
+intersectionWithKey :: (Eq k, Hashable k) => (k -> v1 -> v2 -> v3)
+                    -> HashMap k v1 -> HashMap k v2 -> HashMap k v3
+intersectionWithKey f a b = foldlWithKey' go empty a
+  where
+    go m k v = case HM.lookup k b of
+                 Just w -> insert k (f k v w) m
+                 _      -> m
+{-# INLINABLE intersectionWithKey #-}
+
 ------------------------------------------------------------------------
 -- ** Lists
 
@@ -364,7 +429,18 @@
 {-# INLINABLE fromList #-}
 
 -- | /O(n*log n)/ Construct a map from a list of elements.  Uses
--- the provided function to merge duplicate entries.
+-- the provided function f to merge duplicate entries (f newVal oldVal).
+--
+-- For example:
+--
+-- > fromListWith (+) [ (x, 1) | x <- xs ]
+--
+-- will create a map with number of occurrences of each element in xs.
+--
+-- > fromListWith (++) [ (k, [v]) | (k, v) <- xs ]
+--
+-- will group all values by their keys in a list 'xs :: [(k, v)]' and
+-- return a 'HashMap k [v]'.
 fromListWith :: (Eq k, Hashable k) => (v -> v -> v) -> [(k, v)] -> HashMap k v
 fromListWith f = L.foldl' (\ m (k, v) -> unsafeInsertWith f k v m) empty
 {-# INLINE fromListWith #-}
@@ -389,7 +465,17 @@
 -- array.
 updateOrSnocWith :: Eq k => (v -> v -> v) -> k -> v -> A.Array (Leaf k v)
                  -> A.Array (Leaf k v)
-updateOrSnocWith f k0 v0 ary0 = go k0 v0 ary0 0 (A.length ary0)
+updateOrSnocWith f = updateOrSnocWithKey (const f)
+{-# INLINABLE updateOrSnocWith #-}
+
+-- | Append the given key and value to the array. If the key is
+-- already present, instead update the value of the key by applying
+-- the given function to the new and old value (in that order). The
+-- value is always evaluated to WHNF before being inserted into the
+-- array.
+updateOrSnocWithKey :: Eq k => (k -> v -> v -> v) -> k -> v -> A.Array (Leaf k 
v)
+                 -> A.Array (Leaf k v)
+updateOrSnocWithKey f k0 v0 ary0 = go k0 v0 ary0 0 (A.length ary0)
   where
     go !k v !ary !i !n
         | i >= n = A.run $ do
@@ -400,9 +486,9 @@
             A.write mary n l
             return mary
         | otherwise = case A.index ary i of
-            (L kx y) | k == kx   -> let !v' = f v y in A.update ary i (L k v')
+            (L kx y) | k == kx   -> let !v' = f k v y in A.update ary i (L k 
v')
                      | otherwise -> go k v ary (i+1) n
-{-# INLINABLE updateOrSnocWith #-}
+{-# INLINABLE updateOrSnocWithKey #-}
 
 ------------------------------------------------------------------------
 -- Smart constructors
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/Data/HashMap/Unsafe.hs 
new/unordered-containers-0.2.7.1/Data/HashMap/Unsafe.hs
--- old/unordered-containers-0.2.5.1/Data/HashMap/Unsafe.hs     2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/Data/HashMap/Unsafe.hs     2016-06-09 
02:00:11.000000000 +0200
@@ -13,16 +13,16 @@
     ) where
 
 import GHC.Base (realWorld#)
-import GHC.ST hiding (runST, runSTRep)
+import qualified GHC.ST as ST
 
 -- | 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 })
+runST :: (forall s. ST.ST s a) -> a
+runST st = runSTRep (case st of { ST.ST st_rep -> st_rep })
 {-# INLINE runST #-}
 
-runSTRep :: (forall s. STRep s a) -> a
+runSTRep :: (forall s. ST.STRep s a) -> a
 runSTRep st_rep = case st_rep realWorld# of
                         (# _, r #) -> r
 {-# INLINE [0] runSTRep #-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/Data/HashSet.hs 
new/unordered-containers-0.2.7.1/Data/HashSet.hs
--- old/unordered-containers-0.2.5.1/Data/HashSet.hs    2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/Data/HashSet.hs    2016-06-09 
02:00:11.000000000 +0200
@@ -1,7 +1,11 @@
 {-# LANGUAGE CPP, DeriveDataTypeable #-}
 #if __GLASGOW_HASKELL__ >= 708
+{-# LANGUAGE RoleAnnotations #-}
 {-# LANGUAGE TypeFamilies #-}
 #endif
+#if __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
 
 ------------------------------------------------------------------------
 -- |
@@ -57,16 +61,24 @@
     -- * Filter
     , filter
 
+    -- * Conversions
+
     -- ** Lists
     , toList
     , fromList
+
+    -- * HashMaps
+    , toMap
+    , fromMap
     ) where
 
 import Control.DeepSeq (NFData(..))
 import Data.Data hiding (Typeable)
 import Data.HashMap.Base (HashMap, foldrWithKey)
-import Data.Hashable (Hashable)
-#if __GLASGOW_HASKELL__ < 709
+import Data.Hashable (Hashable(hashWithSalt))
+#if __GLASGOW_HASKELL__ >= 711
+import Data.Semigroup (Semigroup(..), Monoid(..))
+#elif __GLASGOW_HASKELL__ < 709
 import Data.Monoid (Monoid(..))
 #endif
 import GHC.Exts (build)
@@ -86,6 +98,10 @@
       asMap :: HashMap a ()
     } deriving (Typeable)
 
+#if __GLASGOW_HASKELL__ >= 708
+type role HashSet nominal
+#endif
+
 instance (NFData a) => NFData (HashSet a) where
     rnf = rnf . asMap
     {-# INLINE rnf #-}
@@ -100,10 +116,20 @@
     foldr = Data.HashSet.foldr
     {-# INLINE foldr #-}
 
+#if __GLASGOW_HASKELL__ >= 711
+instance (Hashable a, Eq a) => Semigroup (HashSet a) where
+    (<>) = union
+    {-# INLINE (<>) #-}
+#endif
+
 instance (Hashable a, Eq a) => Monoid (HashSet a) where
     mempty = empty
     {-# INLINE mempty #-}
+#if __GLASGOW_HASKELL__ >= 711
+    mappend = (<>)
+#else
     mappend = union
+#endif
     {-# INLINE mappend #-}
 
 instance (Eq a, Hashable a, Read a) => Read (HashSet a) where
@@ -127,6 +153,9 @@
     dataTypeOf _   = hashSetDataType
     dataCast1 f    = gcast1 f
 
+instance (Hashable a) => Hashable (HashSet a) where
+    hashWithSalt salt = hashWithSalt salt . asMap
+
 fromListConstr :: Constr
 fromListConstr = mkConstr hashSetDataType "fromList" [] Prefix
 
@@ -142,6 +171,14 @@
 singleton a = HashSet (H.singleton a ())
 {-# INLINABLE singleton #-}
 
+-- | /O(1)/ Convert to the equivalent 'HashMap'.
+toMap :: HashSet a -> HashMap a ()
+toMap = asMap
+
+-- | /O(1)/ Convert from the equivalent 'HashMap'.
+fromMap :: HashMap a () -> HashSet a
+fromMap = HashSet
+
 -- | /O(n+m)/ Construct a set containing all elements from both sets.
 --
 -- To obtain good performance, the smaller set must be presented as
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unordered-containers-0.2.5.1/benchmarks/Benchmarks.hs 
new/unordered-containers-0.2.7.1/benchmarks/Benchmarks.hs
--- old/unordered-containers-0.2.5.1/benchmarks/Benchmarks.hs   2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/benchmarks/Benchmarks.hs   2016-06-09 
02:00:11.000000000 +0200
@@ -1,12 +1,10 @@
-{-# LANGUAGE CPP, GADTs, PackageImports #-}
+{-# LANGUAGE CPP, DeriveGeneric, GADTs, PackageImports, RecordWildCards #-}
 
 module Main where
 
 import Control.DeepSeq
-import Control.Exception (evaluate)
-import Control.Monad.Trans (liftIO)
-import Criterion.Config
-import Criterion.Main
+import Control.DeepSeq.Generics (genericRnf)
+import Criterion.Main (bench, bgroup, defaultMain, env, nf, whnf)
 import Data.Bits ((.&.))
 import Data.Hashable (Hashable)
 import qualified Data.ByteString as BS
@@ -16,6 +14,7 @@
 import qualified Data.Map as M
 import Data.List (foldl')
 import Data.Maybe (fromMaybe)
+import GHC.Generics (Generic)
 import Prelude hiding (lookup)
 
 import qualified Util.ByteString as UBS
@@ -32,20 +31,82 @@
 instance NFData B where
     rnf (B b) = rnf b
 
+-- TODO: This a stopgap measure to keep the benchmark work with
+-- Criterion 1.0.
+data Env = Env {
+    n :: !Int,
+
+    elems   :: ![(String, Int)],
+    keys    :: ![String],
+    elemsBS :: ![(BS.ByteString, Int)],
+    keysBS  :: ![BS.ByteString],
+    elemsI  :: ![(Int, Int)],
+    keysI   :: ![Int],
+    elemsI2 :: ![(Int, Int)],  -- for union
+
+    keys'    :: ![String],
+    keysBS'  :: ![BS.ByteString],
+    keysI'   :: ![Int],
+
+    keysDup    :: ![String],
+    keysDupBS  :: ![BS.ByteString],
+    keysDupI   :: ![Int],
+    elemsDup   :: ![(String, Int)],
+    elemsDupBS :: ![(BS.ByteString, Int)],
+    elemsDupI  :: ![(Int, Int)],
+
+    hm    :: !(HM.HashMap String Int),
+    hmbs  :: !(HM.HashMap BS.ByteString Int),
+    hmi   :: !(HM.HashMap Int Int),
+    hmi2  :: !(HM.HashMap Int Int),
+    m     :: !(M.Map String Int),
+    mbs   :: !(M.Map BS.ByteString Int),
+    im    :: !(IM.IntMap Int),
+    ihm   :: !(IHM.Map String Int),
+    ihmbs :: !(IHM.Map BS.ByteString Int)
+    } deriving Generic
+
+instance NFData Env where rnf = genericRnf
+
+setupEnv :: IO Env
+setupEnv = do
+    let n = 2^(12 :: Int)
+
+        elems   = zip keys [1..n]
+        keys    = US.rnd 8 n
+        elemsBS = zip keysBS [1..n]
+        keysBS  = UBS.rnd 8 n
+        elemsI  = zip keysI [1..n]
+        keysI   = UI.rnd (n+n) n
+        elemsI2 = zip [n `div` 2..n + (n `div` 2)] [1..n]  -- for union
+
+        keys'    = US.rnd' 8 n
+        keysBS'  = UBS.rnd' 8 n
+        keysI'   = UI.rnd' (n+n) n
+
+        keysDup    = US.rnd 2 n
+        keysDupBS  = UBS.rnd 2 n
+        keysDupI   = UI.rnd (n`div`4) n
+        elemsDup   = zip keysDup [1..n]
+        elemsDupBS = zip keysDupBS [1..n]
+        elemsDupI  = zip keysDupI [1..n]
+
+        hm   = HM.fromList elems
+        hmbs = HM.fromList elemsBS
+        hmi  = HM.fromList elemsI
+        hmi2 = HM.fromList elemsI2
+        m    = M.fromList elems
+        mbs  = M.fromList elemsBS
+        im   = IM.fromList elemsI
+        ihm  = IHM.fromList elems
+        ihmbs = IHM.fromList elemsBS
+    return Env{..}
+
 main :: IO ()
 main = do
-    let hm   = HM.fromList elems :: HM.HashMap String Int
-        hmbs = HM.fromList elemsBS :: HM.HashMap BS.ByteString Int
-        hmi  = HM.fromList elemsI :: HM.HashMap Int Int
-        hmi2 = HM.fromList elemsI2 :: HM.HashMap Int Int
-        m    = M.fromList elems :: M.Map String Int
-        mbs  = M.fromList elemsBS :: M.Map BS.ByteString Int
-        im   = IM.fromList elemsI :: IM.IntMap Int
-        ihm  = IHM.fromList elems :: IHM.Map String Int
-        ihmbs = IHM.fromList elemsBS :: IHM.Map BS.ByteString Int
-    defaultMainWith defaultConfig
-        (liftIO . evaluate $ rnf [B m, B mbs, B hm, B hmbs, B hmi, B im])
+    defaultMain
         [
+          env setupEnv $ \ ~(Env{..}) ->
           -- * Comparison to other data structures
           -- ** Map
           bgroup "Map"
@@ -84,7 +145,8 @@
           ]
 
           -- ** Map from the hashmap package
-        , bgroup "hashmap/Map"
+        , env setupEnv $ \ ~(Env{..}) ->
+          bgroup "hashmap/Map"
           [ bgroup "lookup"
             [ bench "String" $ whnf (lookupIHM keys) ihm
             , bench "ByteString" $ whnf (lookupIHM keysBS) ihmbs
@@ -120,7 +182,8 @@
           ]
 
           -- ** IntMap
-        , bgroup "IntMap"
+        , env setupEnv $ \ ~(Env{..}) ->
+          bgroup "IntMap"
           [ bench "lookup" $ whnf (lookupIM keysI) im
           , bench "lookup-miss" $ whnf (lookupIM keysI') im
           , bench "insert" $ whnf (insertIM elemsI) IM.empty
@@ -131,7 +194,8 @@
           , bench "fromList" $ whnf IM.fromList elemsI
           ]
 
-        , bgroup "HashMap"
+        , env setupEnv $ \ ~(Env{..}) ->
+          bgroup "HashMap"
           [ -- * Basic interface
             bgroup "lookup"
             [ bench "String" $ whnf (lookup keys) hm
@@ -217,28 +281,6 @@
             ]
           ]
         ]
-  where
-    n :: Int
-    n = 2^(12 :: Int)
-
-    elems   = zip keys [1..n]
-    keys    = US.rnd 8 n
-    elemsBS = zip keysBS [1..n]
-    keysBS  = UBS.rnd 8 n
-    elemsI  = zip keysI [1..n]
-    keysI   = UI.rnd (n+n) n
-    elemsI2 = zip [n `div` 2..n + (n `div` 2)] [1..n]  -- for union
-
-    keys'    = US.rnd' 8 n
-    keysBS'  = UBS.rnd' 8 n
-    keysI'   = UI.rnd' (n+n) n
-
-    keysDup    = US.rnd 2 n
-    keysDupBS  = UBS.rnd 2 n
-    keysDupI   = UI.rnd (n`div`4) n
-    elemsDup   = zip keysDup [1..n]
-    elemsDupBS = zip keysDupBS [1..n]
-    elemsDupI  = zip keysDupI [1..n]
 
 ------------------------------------------------------------------------
 -- * HashMap
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unordered-containers-0.2.5.1/benchmarks/Util/ByteString.hs 
new/unordered-containers-0.2.7.1/benchmarks/Util/ByteString.hs
--- old/unordered-containers-0.2.5.1/benchmarks/Util/ByteString.hs      
1970-01-01 01:00:00.000000000 +0100
+++ new/unordered-containers-0.2.7.1/benchmarks/Util/ByteString.hs      
2016-06-09 02:00:11.000000000 +0200
@@ -0,0 +1,29 @@
+-- | Benchmarking utilities.  For example, functions for generating
+-- random 'ByteString's.
+module Util.ByteString where
+
+import qualified Data.ByteString as S
+import qualified Data.ByteString.Char8 as C
+
+import Util.String as String
+
+-- | Generate a number of fixed length 'ByteString's where the content
+-- of the strings are letters in ascending order.
+asc :: Int  -- ^ Length of each string
+    -> Int  -- ^ Number of strings
+    -> [S.ByteString]
+asc strlen num = map C.pack $ String.asc strlen num
+
+-- | Generate a number of fixed length 'ByteString's where the content
+-- of the strings are letters in random order.
+rnd :: Int  -- ^ Length of each string
+    -> Int  -- ^ Number of strings
+    -> [S.ByteString]
+rnd strlen num = map C.pack $ String.rnd strlen num
+
+-- | Generate a number of fixed length 'ByteString's where the content
+-- of the strings are letters in random order, different from @rnd@.
+rnd' :: Int  -- ^ Length of each string
+     -> Int  -- ^ Number of strings
+     -> [S.ByteString]
+rnd' strlen num = map C.pack $ String.rnd' strlen num
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/benchmarks/Util/Int.hs 
new/unordered-containers-0.2.7.1/benchmarks/Util/Int.hs
--- old/unordered-containers-0.2.5.1/benchmarks/Util/Int.hs     1970-01-01 
01:00:00.000000000 +0100
+++ new/unordered-containers-0.2.7.1/benchmarks/Util/Int.hs     2016-06-09 
02:00:11.000000000 +0200
@@ -0,0 +1,19 @@
+-- | Benchmarking utilities.  For example, functions for generating
+-- random integers.
+module Util.Int where
+
+import System.Random (mkStdGen, randomRs)
+
+-- | Generate a number of uniform random integers in the interval
+-- @[0..upper]@.
+rnd :: Int  -- ^ Upper bound (inclusive)
+    -> Int  -- ^ Number of integers
+    -> [Int]
+rnd upper num = take num $ randomRs (0, upper) $ mkStdGen 1234
+
+-- | Generate a number of uniform random integers in the interval
+-- @[0..upper]@ different from @rnd@.
+rnd' :: Int  -- ^ Upper bound (inclusive)
+     -> Int  -- ^ Number of integers
+     -> [Int]
+rnd' upper num = take num $ randomRs (0, upper) $ mkStdGen 5678
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unordered-containers-0.2.5.1/benchmarks/Util/String.hs 
new/unordered-containers-0.2.7.1/benchmarks/Util/String.hs
--- old/unordered-containers-0.2.5.1/benchmarks/Util/String.hs  1970-01-01 
01:00:00.000000000 +0100
+++ new/unordered-containers-0.2.7.1/benchmarks/Util/String.hs  2016-06-09 
02:00:11.000000000 +0200
@@ -0,0 +1,34 @@
+-- | Benchmarking utilities.  For example, functions for generating
+-- random strings.
+module Util.String where
+
+import System.Random (mkStdGen, randomRs)
+
+-- | Generate a number of fixed length strings where the content of
+-- the strings are letters in ascending order.
+asc :: Int  -- ^ Length of each string
+    -> Int  -- ^ Number of strings
+    -> [String]
+asc strlen num = take num $ iterate (snd . inc) $ replicate strlen 'a'
+  where inc [] = (True, [])
+        inc (c:cs) = case inc cs of (True, cs') | c == 'z'  -> (True, 'a' : 
cs')
+                                                | otherwise -> (False, succ c 
: cs')
+                                    (False, cs')            -> (False, c : cs')
+
+-- | Generate a number of fixed length strings where the content of
+-- the strings are letters in random order.
+rnd :: Int  -- ^ Length of each string
+    -> Int  -- ^ Number of strings
+    -> [String]
+rnd strlen num = take num $ split $ randomRs ('a', 'z') $ mkStdGen 1234
+  where
+    split cs = case splitAt strlen cs of (str, cs') -> str : split cs'
+
+-- | Generate a number of fixed length strings where the content of
+-- the strings are letters in random order, different from rnd
+rnd' :: Int  -- ^ Length of each string
+     -> Int  -- ^ Number of strings
+     -> [String]
+rnd' strlen num = take num $ split $ randomRs ('a', 'z') $ mkStdGen 5678
+  where
+    split cs = case splitAt strlen cs of (str, cs') -> str : split cs'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unordered-containers-0.2.5.1/cbits/popc.c 
new/unordered-containers-0.2.7.1/cbits/popc.c
--- old/unordered-containers-0.2.5.1/cbits/popc.c       2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/cbits/popc.c       2016-06-09 
02:00:11.000000000 +0200
@@ -261,7 +261,7 @@
 };
 /* Table-driven popcount, with 8-bit tables */
 /* 6 ops plus 4 casts and 4 lookups, 0 long immediates, 4 stages */
-inline uint32_t
+uint32_t
 popcount(uint32_t x)
 {
     return popcount_table_8[(uint8_t)x] +
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unordered-containers-0.2.5.1/tests/HashMapProperties.hs 
new/unordered-containers-0.2.7.1/tests/HashMapProperties.hs
--- old/unordered-containers-0.2.5.1/tests/HashMapProperties.hs 2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/tests/HashMapProperties.hs 2016-06-09 
02:00:11.000000000 +0200
@@ -5,17 +5,19 @@
 
 module Main (main) where
 
+import Control.Monad ( guard )
 import qualified Data.Foldable as Foldable
 import Data.Function (on)
 import Data.Hashable (Hashable(hashWithSalt))
 import qualified Data.List as L
+import Data.Ord (comparing)
 #if defined(STRICT)
 import qualified Data.HashMap.Strict as HM
 #else
 import qualified Data.HashMap.Lazy as HM
 #endif
 import qualified Data.Map as M
-import Test.QuickCheck (Arbitrary, Property, (==>))
+import Test.QuickCheck (Arbitrary, Property, (==>), (===))
 import Test.Framework (Test, defaultMain, testGroup)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
 
@@ -48,6 +50,19 @@
 pFoldable = (L.sort . Foldable.foldr (:) []) `eq`
             (L.sort . Foldable.foldr (:) [])
 
+pHashable :: [(Key, Int)] -> [Int] -> Int -> Property
+pHashable xs is salt =
+    x == y ==> hashWithSalt salt x === hashWithSalt salt y
+  where
+    ys = shuffle is xs
+    x = HM.fromList xs
+    y = HM.fromList ys
+    -- Shuffle the list using indexes in the second
+    shuffle :: [Int] -> [a] -> [a]
+    shuffle idxs = L.map snd
+                 . L.sortBy (comparing fst)
+                 . L.zip (idxs ++ [L.maximum (0:is) + 1 ..])
+
 ------------------------------------------------------------------------
 -- ** Basic interface
 
@@ -98,6 +113,21 @@
 pAdjust :: Key -> [(Key, Int)] -> Bool
 pAdjust k = M.adjust succ k `eq_` HM.adjust succ k
 
+pUpdateAdjust :: Key -> [(Key, Int)] -> Bool
+pUpdateAdjust k = M.update (Just . succ) k `eq_` HM.update (Just . succ) k
+
+pUpdateDelete :: Key -> [(Key, Int)] -> Bool
+pUpdateDelete k = M.update (const Nothing) k `eq_` HM.update (const Nothing) k
+
+pAlterAdjust :: Key -> [(Key, Int)] -> Bool
+pAlterAdjust k = M.alter (fmap succ) k `eq_` HM.alter (fmap succ) k
+
+pAlterInsert :: Key -> [(Key, Int)] -> Bool
+pAlterInsert k = M.alter (const $ Just 3) k `eq_` HM.alter (const $ Just 3) k
+
+pAlterDelete :: Key -> [(Key, Int)] -> Bool
+pAlterDelete k = M.alter (const Nothing) k `eq_` HM.alter (const Nothing) k
+
 ------------------------------------------------------------------------
 -- ** Combine
 
@@ -108,6 +138,13 @@
 pUnionWith xs ys = M.unionWith (-) (M.fromList xs) `eq_`
                    HM.unionWith (-) (HM.fromList xs) $ ys
 
+pUnionWithKey :: [(Key, Int)] -> [(Key, Int)] -> Bool
+pUnionWithKey xs ys = M.unionWithKey go (M.fromList xs) `eq_`
+                             HM.unionWithKey go (HM.fromList xs) $ ys
+  where
+    go :: Key -> Int -> Int -> Int
+    go (K k) i1 i2 = k - i1 + i2
+
 pUnions :: [[(Key, Int)]] -> Bool
 pUnions xss = M.toAscList (M.unions (map M.fromList xss)) ==
               toAscList (HM.unions (map HM.fromList xss))
@@ -133,6 +170,13 @@
 pIntersectionWith xs ys = M.intersectionWith (-) (M.fromList xs) `eq_`
                           HM.intersectionWith (-) (HM.fromList xs) $ ys
 
+pIntersectionWithKey :: [(Key, Int)] -> [(Key, Int)] -> Bool
+pIntersectionWithKey xs ys = M.intersectionWithKey go (M.fromList xs) `eq_`
+                             HM.intersectionWithKey go (HM.fromList xs) $ ys
+  where
+    go :: Key -> Int -> Int -> Int
+    go (K k) i1 i2 = k - i1 - i2
+
 ------------------------------------------------------------------------
 -- ** Folds
 
@@ -158,6 +202,14 @@
 ------------------------------------------------------------------------
 -- ** Filter
 
+pMapMaybeWithKey :: [(Key, Int)] -> Bool
+pMapMaybeWithKey = M.mapMaybeWithKey f `eq_` HM.mapMaybeWithKey f
+  where f k v = guard (odd (unK k + v)) >> Just (v + 1)
+
+pMapMaybe :: [(Key, Int)] -> Bool
+pMapMaybe = M.mapMaybe f `eq_` HM.mapMaybe f
+  where f v = guard (odd v) >> Just (v + 1)
+
 pFilter :: [(Key, Int)] -> Bool
 pFilter = M.filter odd `eq_` HM.filter odd
 
@@ -198,6 +250,7 @@
       , testProperty "Read/Show" pReadShow
       , testProperty "Functor" pFunctor
       , testProperty "Foldable" pFoldable
+      , testProperty "Hashable" pHashable
       ]
     -- Basic interface
     , testGroup "basic interface"
@@ -209,10 +262,16 @@
       , testProperty "deleteCollision" pDeleteCollision
       , testProperty "insertWith" pInsertWith
       , testProperty "adjust" pAdjust
+      , testProperty "updateAdjust" pUpdateAdjust
+      , testProperty "updateDelete" pUpdateDelete
+      , testProperty "alterAdjust" pAlterAdjust
+      , testProperty "alterInsert" pAlterInsert
+      , testProperty "alterDelete" pAlterDelete
       ]
     -- Combine
     , testProperty "union" pUnion
     , testProperty "unionWith" pUnionWith
+    , testProperty "unionWithKey" pUnionWithKey
     , testProperty "unions" pUnions
     -- Transformations
     , testProperty "map" pMap
@@ -226,11 +285,14 @@
       [ testProperty "difference" pDifference
       , testProperty "intersection" pIntersection
       , testProperty "intersectionWith" pIntersectionWith
+      , testProperty "intersectionWithKey" pIntersectionWithKey
       ]
     -- Filter
     , testGroup "filter"
       [ testProperty "filter" pFilter
       , testProperty "filterWithKey" pFilterWithKey
+      , testProperty "mapMaybe" pMapMaybe
+      , testProperty "mapMaybeWithKey" pMapMaybeWithKey
       ]
     -- Conversions
     , testGroup "conversions"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unordered-containers-0.2.5.1/tests/HashSetProperties.hs 
new/unordered-containers-0.2.7.1/tests/HashSetProperties.hs
--- old/unordered-containers-0.2.5.1/tests/HashSetProperties.hs 2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/tests/HashSetProperties.hs 2016-06-09 
02:00:11.000000000 +0200
@@ -10,7 +10,8 @@
 import qualified Data.List as L
 import qualified Data.HashSet as S
 import qualified Data.Set as Set
-import Test.QuickCheck (Arbitrary)
+import Data.Ord (comparing)
+import Test.QuickCheck (Arbitrary, Property, (==>), (===))
 import Test.Framework (Test, defaultMain, testGroup)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
 
@@ -40,6 +41,25 @@
 pFoldable = (L.sort . Foldable.foldr (:) []) `eq`
             (L.sort . Foldable.foldr (:) [])
 
+pPermutationEq :: [Key] -> [Int] -> Bool
+pPermutationEq xs is = S.fromList xs == S.fromList ys
+  where
+    ys = shuffle is xs
+    shuffle idxs = L.map snd
+                 . L.sortBy (comparing fst)
+                 . L.zip (idxs ++ [L.maximum (0:is) + 1 ..])
+
+pHashable :: [Key] -> [Int] -> Int -> Property
+pHashable xs is salt =
+    x == y ==> hashWithSalt salt x === hashWithSalt salt y
+  where
+    ys = shuffle is xs
+    x = S.fromList xs
+    y = S.fromList ys
+    shuffle idxs = L.map snd
+                 . L.sortBy (comparing fst)
+                 . L.zip (idxs ++ [L.maximum (0:is) + 1 ..])
+
 ------------------------------------------------------------------------
 -- ** Basic interface
 
@@ -113,9 +133,11 @@
     -- Instances
       testGroup "instances"
       [ testProperty "==" pEq
+      , testProperty "Permutation ==" pPermutationEq
       , testProperty "/=" pNeq
       , testProperty "Read/Show" pReadShow
       , testProperty "Foldable" pFoldable
+      , testProperty "Hashable" pHashable
       ]
     -- Basic interface
     , testGroup "basic interface"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/unordered-containers-0.2.5.1/unordered-containers.cabal 
new/unordered-containers-0.2.7.1/unordered-containers.cabal
--- old/unordered-containers-0.2.5.1/unordered-containers.cabal 2014-10-11 
15:04:46.000000000 +0200
+++ new/unordered-containers-0.2.7.1/unordered-containers.cabal 2016-06-09 
02:00:11.000000000 +0200
@@ -1,5 +1,5 @@
 name:           unordered-containers
-version:        0.2.5.1
+version:        0.2.7.1
 synopsis:       Efficient hashing-based container types
 description:
   Efficient hashing-based container types.  The containers have been
@@ -19,6 +19,8 @@
 category:       Data
 build-type:     Simple
 cabal-version:  >=1.8
+extra-source-files: CHANGES.md
+tested-with:    GHC==8.0.1, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2
 
 flag debug
   description:  Enable debug support
@@ -39,7 +41,7 @@
   build-depends:
     base >= 4 && < 5,
     deepseq >= 1.1,
-    hashable >= 1.0.1.1
+    hashable >= 1.0.1.1 && < 1.3
 
   if impl(ghc < 7.4)
     c-sources: cbits/popc.c
@@ -147,12 +149,18 @@
   main-is: Benchmarks.hs
   type: exitcode-stdio-1.0
 
+  other-modules:
+    Util.ByteString
+    Util.Int
+    Util.String
+
   build-depends:
     base,
     bytestring,
     containers,
-    criterion,
+    criterion >= 1.0 && < 1.2,
     deepseq >= 1.1,
+    deepseq-generics,
     hashable >= 1.0.1.1,
     hashmap,
     mtl,


Reply via email to