diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,49 +1,110 @@
+# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
 language: c
 sudo: false
 
+cache:
+  directories:
+    - $HOME/.cabsnap
+    - $HOME/.cabal/packages
+
+before_cache:
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
+
 matrix:
   include:
-    - env: CABALVER=1.16 GHCVER=7.4.2
-      addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2], sources: [hvr-ghc]}}
-    - env: CABALVER=1.16 GHCVER=7.6.3
-      addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}}
-    - env: CABALVER=1.18 GHCVER=7.8.4
-      addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
-    - env: CABALVER=1.22 GHCVER=7.10.1
-      addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.1],sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=7.0.4
+      compiler: ": #GHC 7.0.4"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-7.0.4], sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=7.2.2
+      compiler: ": #GHC 7.2.2"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-7.2.2], sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=7.4.2
+      compiler: ": #GHC 7.4.2"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-7.4.2], sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=7.6.3
+      compiler: ": #GHC 7.6.3"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-7.6.3], sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=7.8.4
+      compiler: ": #GHC 7.8.4"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-7.8.4], sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=7.10.3
+      compiler: ": #GHC 7.10.3"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-7.10.3], sources: [hvr-ghc]}}
+    - env: CABALVER=1.24 GHCVER=8.0.2
+      compiler: ": #GHC 8.0.2"
+      addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2], sources: [hvr-ghc]}}
+    - env: CABALVER=2.0 GHCVER=8.2.1
+      compiler: ": #GHC 8.2.1"
+      addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.1], sources: [hvr-ghc]}}
     - env: CABALVER=head GHCVER=head
-      addons: {apt: {packages: [cabal-install-head,ghc-head],  sources: [hvr-ghc]}}
+      compiler: ": #GHC head"
+      addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
 
   allow_failures:
-   - env: CABALVER=head GHCVER=head
+    - env: CABALVER=head GHCVER=head
 
 before_install:
+ - unset CC
  - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
- - export CABAL=cabal-$CABALVER
- - $CABAL --version
 
 install:
- - travis_retry $CABAL update
- - $CABAL install --enable-tests --only-dependencies
+ - cabal --version
+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
+ - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
+   then
+     zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
+          $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
+   fi
+ - travis_retry cabal update -v
+ - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
+ - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
+ - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
 
-script:
- - $CABAL configure -v2 --enable-tests
- - $CABAL build
- - $CABAL test
- - $CABAL sdist
- - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}') ;
-   cd dist/;
-   if [ -f "$SRC_TGZ" ]; then
-      $CABAL install "$SRC_TGZ";
+# check whether current requested install-plan matches cached package-db snapshot
+ - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
+   then
+     echo "cabal build-cache HIT";
+     rm -rfv .ghc;
+     cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
+     cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
    else
-      echo "expected '$SRC_TGZ' not found";
-      exit 1;
+     echo "cabal build-cache MISS";
+     rm -rf $HOME/.cabsnap;
+     mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
+     cabal install -j --only-dependencies --enable-tests --enable-benchmarks;
    fi
 
+# snapshot package-db on cache miss
+ - if [ ! -d $HOME/.cabsnap ];
+   then
+      echo "snapshotting package-db to build-cache";
+      mkdir $HOME/.cabsnap;
+      cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
+      cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
+   fi
+
+# Here starts the actual work to be performed for the package under test;
+# any command which exits with a non-zero exit code causes the build to fail.
+script:
+ - if [ -f configure.ac ]; then autoreconf -i; fi
+ - cabal configure --enable-tests --enable-benchmarks -v2  # -v2 provides useful information for debugging
+ - cabal build   # this builds all libraries and executables (including tests/benchmarks)
+ - cabal test
+ - cabal sdist   # tests that a source-distribution can be generated
+
+# Check that the resulting source distribution can be built & installed.
+# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
+# `cabal install --force-reinstalls dist/*-*.tar.gz`
+ - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
+   (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
+
 notifications:
   irc:
     channels:
       - "irc.freenode.org#haskell-lens"
     skip_join: true
     template:
-      - "\x0313reducers\x0f/\x0306%{branch}\x0f \x0314%{commit}\x0f %{message} \x0302\x1f%{build_url}\x0f"
+      - "\x0313reducers\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"
+
+# EOF
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2008-2011 Edward Kmett
+Copyright 2008-2016 Edward Kmett
 
 All rights reserved.
 
diff --git a/reducers.cabal b/reducers.cabal
--- a/reducers.cabal
+++ b/reducers.cabal
@@ -1,6 +1,6 @@
 name:          reducers
 category:      Data, Math, Numerical, Semigroups
-version:       3.12.1
+version:       3.12.2
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -9,7 +9,7 @@
 stability:     provisional
 homepage:      http://github.com/ekmett/reducers/
 bug-reports:   http://github.com/ekmett/reducers/issues
-copyright:     Copyright (C) 2008-2013 Edward A. Kmett
+copyright:     Copyright (C) 2008-2016 Edward A. Kmett
 synopsis:      Semigroups, specialized containers and a general map/reduce framework
 description:   Semigroups, specialized containers and a general map/reduce framework
 build-type:    Simple
@@ -25,13 +25,13 @@
   build-depends:
     base                   >= 4        && < 5,
     array                  >= 0.3      && < 0.6,
-    transformers           >= 0.2      && < 0.5,
+    transformers           >= 0.2      && < 0.6,
     bytestring             >= 0.9.1    && < 0.11,
     containers             >= 0.3      && < 0.6,
     fingertree             >= 0.1      && < 0.2,
     hashable               >= 1.1.2.1  && < 1.3,
     text                   >= 0.11.1.5 && < 1.3,
-    unordered-containers   >= 0.1.4    && < 0.3,
+    unordered-containers   >= 0.2      && < 0.3,
     semigroups             >= 0.9      && < 1,
     semigroupoids          >= 4        && < 6
 
@@ -56,3 +56,8 @@
     cpp-options: -DLANGUAGE_DeriveDataTypeable
 
   ghc-options: -Wall
+
+  -- hack around the buggy unused matches check for class associated types in ghc 8 rc1
+  if impl(ghc >= 8)
+    ghc-options: -fno-warn-unused-matches
+
diff --git a/src/Data/Generator.hs b/src/Data/Generator.hs
--- a/src/Data/Generator.hs
+++ b/src/Data/Generator.hs
@@ -1,12 +1,13 @@
 {-# LANGUAGE UndecidableInstances, FlexibleContexts, MultiParamTypeClasses, FlexibleInstances, TypeFamilies, CPP #-}
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
-{-# LANGUAGE Trustworthy #-}
+
+#ifndef MIN_VERSION_base
+#define MIN_VERSION_base(x,y,z) 1
 #endif
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Generator
--- Copyright   :  (c) Edward Kmett 2009
+-- Copyright   :  (c) Edward Kmett 2009-2016
 -- License     :  BSD-style
 -- Maintainer  :  ekmett@gmail.com
 -- Stability   :  experimental
@@ -47,7 +48,7 @@
 import qualified Data.ByteString.Lazy as Lazy (ByteString, toChunks)
 import qualified Data.ByteString.Lazy.Char8 as Lazy8 (toChunks)
 import Data.Word (Word8)
-import Data.FingerTree (Measured, FingerTree)
+import Data.FingerTree (FingerTree)
 import Data.Sequence (Seq)
 import qualified Data.Set as Set
 import Data.Set (Set)
@@ -104,7 +105,7 @@
   type Elem (NonEmpty c) = c
   mapReduce f = mapReduce f . NonEmpty.toList
 
-instance Measured v e => Generator (FingerTree v e) where
+instance Generator (FingerTree v e) where
   type Elem (FingerTree v e) = e
   mapReduce f = foldMap (unit . f)
 
@@ -166,7 +167,11 @@
   type Elem (Values (Map k v)) = v
   mapReduce f = mapReduce f . Map.elems . getValues
 
+#if MIN_VERSION_base(4,9,0)
+instance Generator (Values (Array i e)) where
+#else
 instance Ix i => Generator (Values (Array i e)) where
+#endif
   type Elem (Values (Array i e)) = e
   mapReduce f = mapReduce f . elems . getValues
 
diff --git a/src/Data/Semigroup/Instances.hs b/src/Data/Semigroup/Instances.hs
--- a/src/Data/Semigroup/Instances.hs
+++ b/src/Data/Semigroup/Instances.hs
@@ -5,8 +5,10 @@
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Data.Semigroup.Instances where
 
+#if !(MIN_VERSION_fingertree(0,1,2) && MIN_VERSION_base(4,9,0))
 import Data.FingerTree
 import Data.Semigroup
 
 instance Measured v a => Semigroup (FingerTree v a) where
   (<>) = mappend
+#endif
diff --git a/src/Data/Semigroup/Reducer.hs b/src/Data/Semigroup/Reducer.hs
--- a/src/Data/Semigroup/Reducer.hs
+++ b/src/Data/Semigroup/Reducer.hs
@@ -55,6 +55,8 @@
 import Data.IntMap (IntMap)
 import qualified Data.Map as Map
 import Data.Map (Map)
+import qualified Data.HashMap.Lazy as HashMap
+import Data.HashMap.Lazy (HashMap)
 
 #ifdef LANGUAGE_DeriveDataTypeable
 import Data.Data
@@ -232,6 +234,12 @@
   unit = uncurry Map.singleton
   cons = uncurry Map.insert
   snoc = flip . uncurry . Map.insertWith $ const id
+
+
+instance (Eq k, Hashable k) => Reducer (k, v) (HashMap k v) where
+  unit = uncurry HashMap.singleton
+  cons = uncurry HashMap.insert
+  snoc = flip . uncurry . HashMap.insertWith $ const id
 
 instance Monoid m => Reducer m (WrappedMonoid m) where
   unit = WrapMonoid
diff --git a/src/Data/Semigroup/Union.hs b/src/Data/Semigroup/Union.hs
--- a/src/Data/Semigroup/Union.hs
+++ b/src/Data/Semigroup/Union.hs
@@ -157,13 +157,11 @@
 instance Ord k => HasUnionWith0 (Map k) where
   emptyWith = Map.empty
 
--- TODO: add unionWith to unordered-containers
-
---instance Eq k => HasUnionWith (HashMap k) where
---  unionWith = HashMap.unionWith
+instance (Eq k, Hashable k) => HasUnionWith (HashMap k) where
+  unionWith = HashMap.unionWith
 
---instance Ord k => HasUnionWith0 (Map k) where
---  emptyWith = Map.empty
+instance (Eq k, Hashable k) => HasUnionWith0 (HashMap k) where
+  emptyWith = HashMap.empty
 
 -- | The 'Monoid' @('unionWith mappend','empty')@ for containers full of monoids.
 newtype UnionWith f m = UnionWith { getUnionWith :: f m }
