diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,6 +20,7 @@
  - GHCVER=7.6.1
  - GHCVER=7.6.2
  - GHCVER=7.6.3
+ - GHCVER=7.8.2
  - GHCVER=head
 
 matrix:
@@ -30,15 +31,18 @@
  - sudo add-apt-repository -y ppa:hvr/ghc
  - sudo apt-get update
  - sudo apt-get install cabal-install-1.18 ghc-$GHCVER
- - export PATH=/opt/ghc/$GHCVER/bin:$PATH
+ - export PATH=/opt/ghc/$GHCVER/bin:~/.cabal/bin:$PATH
 
 install:
  - cabal-1.18 update
  - cabal-1.18 install --only-dependencies --enable-tests
+ - cabal-1.18 install happy packunused packdeps
 
 script:
  - cabal-1.18 configure --enable-tests -v2
- - cabal-1.18 build
+ - cabal-1.18 build --ghc-options=-ddump-minimal-imports
+ - packunused
+ - packdeps bifunctors.cabal
  - cabal-1.18 test
  - cabal-1.18 check
  - cabal-1.18 sdist
diff --git a/bifunctors.cabal b/bifunctors.cabal
--- a/bifunctors.cabal
+++ b/bifunctors.cabal
@@ -1,6 +1,6 @@
 name:          bifunctors
 category:      Data, Functors
-version:       4.1.1.1
+version:       4.2
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -25,17 +25,22 @@
     base          >= 4.5 && < 5,
     semigroups    >= 0.8.3.1,
     semigroupoids == 4.*,
-    tagged        >= 0.4.4 && < 1
+    tagged        >= 0.7.3 && < 1
 
+  if impl(ghc<7.9)
+    hs-source-dirs: old-src
+    exposed-modules: Data.Bifunctor
+
   exposed-modules:
     Data.Biapplicative
-    Data.Bifunctor
     Data.Bifunctor.Apply
+    Data.Bifunctor.Biff
     Data.Bifunctor.Clown
     Data.Bifunctor.Flip
     Data.Bifunctor.Join
     Data.Bifunctor.Joker
     Data.Bifunctor.Product
+    Data.Bifunctor.Tannen
     Data.Bifunctor.Wrapped
     Data.Bifoldable
     Data.Bitraversable
diff --git a/old-src/Data/Bifunctor.hs b/old-src/Data/Bifunctor.hs
new file mode 100644
--- /dev/null
+++ b/old-src/Data/Bifunctor.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE CPP #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Bifunctor
+-- Copyright   :  (C) 2008-2013 Edward Kmett,
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+----------------------------------------------------------------------------
+module Data.Bifunctor
+  ( Bifunctor(..)
+  ) where
+
+import Control.Applicative
+import Data.Tagged
+
+-- | Minimal definition either 'bimap' or 'first' and 'second'
+
+-- | Formally, the class 'Bifunctor' represents a bifunctor
+-- from @Hask@ -> @Hask@.
+--
+-- Intuitively it is a bifunctor where both the first and second arguments are covariant.
+--
+-- You can define a 'Bifunctor' by either defining 'bimap' or by defining both
+-- 'first' and 'second'.
+--
+-- If you supply 'bimap', you should ensure that:
+--
+-- @'bimap' 'id' 'id' ≡ 'id'@
+--
+-- If you supply 'first' and 'second', ensure:
+--
+-- @
+-- 'first' 'id' ≡ 'id'
+-- 'second' 'id' ≡ 'id'
+-- @
+--
+-- If you supply both, you should also ensure:
+--
+-- @'bimap' f g ≡ 'first' f '.' 'second' g@
+--
+-- These ensure by parametricity:
+--
+-- @
+-- 'bimap'  (f '.' g) (h '.' i) ≡ 'bimap' f h '.' 'bimap' g i
+-- 'first'  (f '.' g) ≡ 'first'  f '.' 'first'  g
+-- 'second' (f '.' g) ≡ 'second' f '.' 'second' g
+-- @
+class Bifunctor p where
+  -- | Map over both arguments at the same time.
+  --
+  -- @'bimap' f g ≡ 'first' f '.' 'second' g@
+  bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
+  bimap f g = first f . second g
+  {-# INLINE bimap #-}
+
+  -- | Map covariantly over the first argument.
+  --
+  -- @'first' f ≡ 'bimap' f 'id'@
+  first :: (a -> b) -> p a c -> p b c
+  first f = bimap f id
+  {-# INLINE first #-}
+
+  -- | Map covariantly over the second argument.
+  --
+  -- @'second' ≡ 'bimap' 'id'@
+  second :: (b -> c) -> p a b -> p a c
+  second = bimap id
+  {-# INLINE second #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
+  {-# MINIMAL bimap | first, second #-}
+#endif
+
+instance Bifunctor (,) where
+  bimap f g ~(a, b) = (f a, g b)
+  {-# INLINE bimap #-}
+
+instance Bifunctor ((,,) x) where
+  bimap f g ~(x, a, b) = (x, f a, g b)
+  {-# INLINE bimap #-}
+
+instance Bifunctor ((,,,) x y) where
+  bimap f g ~(x, y, a, b) = (x, y, f a, g b)
+  {-# INLINE bimap #-}
+
+instance Bifunctor ((,,,,) x y z) where
+  bimap f g ~(x, y, z, a, b) = (x, y, z, f a, g b)
+  {-# INLINE bimap #-}
+
+instance Bifunctor Either where
+  bimap f _ (Left a) = Left (f a)
+  bimap _ g (Right b) = Right (g b)
+  {-# INLINE bimap #-}
+
+instance Bifunctor Const where
+  bimap f _ (Const a) = Const (f a)
+  {-# INLINE bimap #-}
+
+instance Bifunctor Tagged where
+  bimap _ g (Tagged b) = Tagged (g b)
+  {-# INLINE bimap #-}
diff --git a/src/Data/Bifoldable.hs b/src/Data/Bifoldable.hs
--- a/src/Data/Bifoldable.hs
+++ b/src/Data/Bifoldable.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Bifoldable
@@ -85,6 +86,10 @@
   bifoldl :: (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c
   bifoldl f g z t = appEndo (getDual (bifoldMap (Dual . Endo . flip f) (Dual . Endo . flip g) t)) z
   {-# INLINE bifoldl #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
+  {-# MINIMAL bifoldr | bifoldMap #-}
+#endif
 
 instance Bifoldable (,) where
   bifoldMap f g ~(a, b) = f a `mappend` g b
diff --git a/src/Data/Bifunctor.hs b/src/Data/Bifunctor.hs
deleted file mode 100644
--- a/src/Data/Bifunctor.hs
+++ /dev/null
@@ -1,100 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.Bifunctor
--- Copyright   :  (C) 2008-2013 Edward Kmett,
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
---
-----------------------------------------------------------------------------
-module Data.Bifunctor
-  ( Bifunctor(..)
-  ) where
-
-import Control.Applicative
-import Data.Tagged
-
--- | Minimal definition either 'bimap' or 'first' and 'second'
-
--- | Formally, the class 'Bifunctor' represents a bifunctor
--- from @Hask@ -> @Hask@.
---
--- Intuitively it is a bifunctor where both the first and second arguments are covariant.
---
--- You can define a 'Bifunctor' by either defining 'bimap' or by defining both
--- 'first' and 'second'.
---
--- If you supply 'bimap', you should ensure that:
---
--- @'bimap' 'id' 'id' ≡ 'id'@
---
--- If you supply 'first' and 'second', ensure:
---
--- @
--- 'first' 'id' ≡ 'id'
--- 'second' 'id' ≡ 'id'
--- @
---
--- If you supply both, you should also ensure:
---
--- @'bimap' f g ≡ 'first' f '.' 'second' g@
---
--- These ensure by parametricity:
---
--- @
--- 'bimap'  (f '.' g) (h '.' i) ≡ 'bimap' f h '.' 'bimap' g i
--- 'first'  (f '.' g) ≡ 'first'  f '.' 'first'  g
--- 'second' (f '.' g) ≡ 'second' f '.' 'second' g
--- @
-class Bifunctor p where
-  -- | Map over both arguments at the same time.
-  --
-  -- @'bimap' f g ≡ 'first' f '.' 'second' g@
-  bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
-  bimap f g = first f . second g
-  {-# INLINE bimap #-}
-
-  -- | Map covariantly over the first argument.
-  --
-  -- @'first' f ≡ 'bimap' f 'id'@
-  first :: (a -> b) -> p a c -> p b c
-  first f = bimap f id
-  {-# INLINE first #-}
-
-  -- | Map covariantly over the second argument.
-  --
-  -- @'second' ≡ 'bimap' 'id'@
-  second :: (b -> c) -> p a b -> p a c
-  second = bimap id
-  {-# INLINE second #-}
-
-instance Bifunctor (,) where
-  bimap f g ~(a, b) = (f a, g b)
-  {-# INLINE bimap #-}
-
-instance Bifunctor ((,,) x) where
-  bimap f g ~(x, a, b) = (x, f a, g b)
-  {-# INLINE bimap #-}
-
-instance Bifunctor ((,,,) x y) where
-  bimap f g ~(x, y, a, b) = (x, y, f a, g b)
-  {-# INLINE bimap #-}
-
-instance Bifunctor ((,,,,) x y z) where
-  bimap f g ~(x, y, z, a, b) = (x, y, z, f a, g b)
-  {-# INLINE bimap #-}
-
-instance Bifunctor Either where
-  bimap f _ (Left a) = Left (f a)
-  bimap _ g (Right b) = Right (g b)
-  {-# INLINE bimap #-}
-
-instance Bifunctor Const where
-  bimap f _ (Const a) = Const (f a)
-  {-# INLINE bimap #-}
-
-instance Bifunctor Tagged where
-  bimap _ g (Tagged b) = Tagged (g b)
-  {-# INLINE bimap #-}
diff --git a/src/Data/Bifunctor/Biff.hs b/src/Data/Bifunctor/Biff.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bifunctor/Biff.hs
@@ -0,0 +1,79 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Bifunctor.Biff
+-- Copyright   :  (C) 2008-2013 Edward Kmett,
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+----------------------------------------------------------------------------
+module Data.Bifunctor.Biff
+  ( Biff(..)
+  ) where
+
+import Control.Applicative
+import Data.Biapplicative
+import Data.Bifunctor.Apply
+import Data.Bifoldable
+import Data.Bitraversable
+import Data.Foldable
+import Data.Functor.Apply
+import Data.Monoid
+import Data.Semigroup.Bifoldable
+import Data.Semigroup.Bitraversable
+import Data.Semigroup.Foldable
+import Data.Semigroup.Traversable
+import Data.Traversable
+
+-- | Compose two 'Functor's on the inside of a 'Bifunctor'.
+newtype Biff p f g a b = Biff { runBiff :: p (f a) (g b) }
+  deriving (Eq,Ord,Show,Read)
+
+instance (Bifunctor p, Functor f, Functor g) => Bifunctor (Biff p f g) where
+  first f = Biff . first (fmap f) . runBiff
+  {-# INLINE first #-}
+  second f = Biff . second (fmap f) . runBiff
+  {-# INLINE second #-}
+  bimap f g = Biff . bimap (fmap f) (fmap g) . runBiff
+  {-# INLINE bimap #-}
+
+instance (Bifunctor p, Functor g) => Functor (Biff p f g a) where
+  fmap f = Biff . second (fmap f) . runBiff
+  {-# INLINE fmap #-}
+
+instance (Biapply p, Apply f, Apply g) => Biapply (Biff p f g) where
+  Biff fg <<.>> Biff xy = Biff (bimap (<.>) (<.>) fg <<.>> xy)
+  {-# INLINE (<<.>>) #-}
+
+instance (Biapplicative p, Applicative f, Applicative g) => Biapplicative (Biff p f g) where
+  bipure a b = Biff (bipure (pure a) (pure b))
+  {-# INLINE bipure #-}
+
+  Biff fg <<*>> Biff xy = Biff (bimap (<*>) (<*>) fg <<*>> xy)
+  {-# INLINE (<<*>>) #-}
+
+instance (Bifoldable p, Foldable g) => Foldable (Biff p f g a) where
+  foldMap f = bifoldMap (const mempty) (foldMap f) . runBiff
+  {-# INLINE foldMap #-}
+
+instance (Bifoldable p, Foldable f, Foldable g) => Bifoldable (Biff p f g) where
+  bifoldMap f g = bifoldMap (foldMap f) (foldMap g) . runBiff
+  {-# INLINE bifoldMap #-}
+
+instance (Bitraversable p, Traversable g) => Traversable (Biff p f g a) where
+  traverse f = fmap Biff . bitraverse pure (traverse f) . runBiff
+  {-# INLINE traverse #-}
+
+instance (Bitraversable p, Traversable f, Traversable g) => Bitraversable (Biff p f g) where
+  bitraverse f g = fmap Biff . bitraverse (traverse f) (traverse g) . runBiff
+  {-# INLINE bitraverse #-}
+
+instance (Bifoldable1 p, Foldable1 f, Foldable1 g) => Bifoldable1 (Biff p f g) where
+  bifoldMap1 f g = bifoldMap1 (foldMap1 f) (foldMap1 g) . runBiff
+  {-# INLINE bifoldMap1 #-}
+
+instance (Bitraversable1 p, Traversable1 f, Traversable1 g) => Bitraversable1 (Biff p f g) where
+  bitraverse1 f g = fmap Biff . bitraverse1 (traverse1 f) (traverse1 g) . runBiff
+  {-# INLINE bitraverse1 #-}
diff --git a/src/Data/Bifunctor/Tannen.hs b/src/Data/Bifunctor/Tannen.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bifunctor/Tannen.hs
@@ -0,0 +1,79 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Bifunctor.Tannen
+-- Copyright   :  (C) 2008-2013 Edward Kmett,
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+----------------------------------------------------------------------------
+module Data.Bifunctor.Tannen
+  ( Tannen(..)
+  ) where
+
+import Control.Applicative
+import Data.Biapplicative
+import Data.Bifunctor.Apply
+import Data.Bifoldable
+import Data.Bitraversable
+import Data.Foldable
+import Data.Functor.Apply
+import Data.Monoid
+import Data.Semigroup.Bifoldable
+import Data.Semigroup.Bitraversable
+import Data.Semigroup.Foldable
+import Data.Semigroup.Traversable
+import Data.Traversable
+
+-- | Compose a 'Functor' on the outside of a 'Bifunctor'.
+newtype Tannen f p a b = Tannen { runTannen :: f (p a b) }
+  deriving (Eq,Ord,Show,Read)
+
+instance (Functor f, Bifunctor p) => Bifunctor (Tannen f p) where
+  first f = Tannen . fmap (first f) . runTannen
+  {-# INLINE first #-}
+  second f = Tannen . fmap (second f) . runTannen
+  {-# INLINE second #-}
+  bimap f g = Tannen . fmap (bimap f g) . runTannen
+  {-# INLINE bimap #-}
+
+instance (Functor f, Bifunctor p) => Functor (Tannen f p a) where
+  fmap f = Tannen . fmap (second f) . runTannen
+  {-# INLINE fmap #-}
+
+instance (Apply f, Biapply p) => Biapply (Tannen f p) where
+  Tannen fg <<.>> Tannen xy = Tannen ((<<.>>) <$> fg <.> xy)
+  {-# INLINE (<<.>>) #-}
+
+instance (Applicative f, Biapplicative p) => Biapplicative (Tannen f p) where
+  bipure a b = Tannen (pure (bipure a b))
+  {-# INLINE bipure #-}
+
+  Tannen fg <<*>> Tannen xy = Tannen ((<<*>>) <$> fg <*> xy)
+  {-# INLINE (<<*>>) #-}
+
+instance (Foldable f, Bifoldable p) => Foldable (Tannen f p a) where
+  foldMap f = foldMap (bifoldMap (const mempty) f) . runTannen
+  {-# INLINE foldMap #-}
+
+instance (Foldable f, Bifoldable p) => Bifoldable (Tannen f p) where
+  bifoldMap f g = foldMap (bifoldMap f g) . runTannen
+  {-# INLINE bifoldMap #-}
+
+instance (Traversable f, Bitraversable p) => Traversable (Tannen f p a) where
+  traverse f = fmap Tannen . traverse (bitraverse pure f) . runTannen
+  {-# INLINE traverse #-}
+
+instance (Traversable f, Bitraversable p) => Bitraversable (Tannen f p) where
+  bitraverse f g = fmap Tannen . traverse (bitraverse f g) . runTannen
+  {-# INLINE bitraverse #-}
+
+instance (Foldable1 f, Bifoldable1 p) => Bifoldable1 (Tannen f p) where
+  bifoldMap1 f g = foldMap1 (bifoldMap1 f g) . runTannen
+  {-# INLINE bifoldMap1 #-}
+
+instance (Traversable1 f, Bitraversable1 p) => Bitraversable1 (Tannen f p) where
+  bitraverse1 f g = fmap Tannen . traverse1 (bitraverse1 f g) . runTannen
+  {-# INLINE bitraverse1 #-}
diff --git a/src/Data/Bitraversable.hs b/src/Data/Bitraversable.hs
--- a/src/Data/Bitraversable.hs
+++ b/src/Data/Bitraversable.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Bitraversable
@@ -145,6 +146,10 @@
   bisequence :: Monad m => t (m a) (m b) -> m (t a b)
   bisequence = bimapM id id
   {-# INLINE bisequence #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
+  {-# MINIMAL bitraverse | bisequenceA #-}
+#endif
 
 instance Bitraversable (,) where
   bitraverse f g ~(a, b) = (,) <$> f a <*> g b
diff --git a/src/Data/Semigroup/Bitraversable.hs b/src/Data/Semigroup/Bitraversable.hs
--- a/src/Data/Semigroup/Bitraversable.hs
+++ b/src/Data/Semigroup/Bitraversable.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Semigroup.Bitraversable
@@ -30,6 +31,10 @@
   bisequence1 :: Apply f => t (f a) (f b) -> f (t a b)
   bisequence1 = bitraverse1 id id
   {-# INLINE bisequence1 #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
+  {-# MINIMAL bitraverse1 | bisequence1 #-}
+#endif
 
 bifoldMap1Default :: (Bitraversable1 t, Semigroup m) => (a -> m) -> (b -> m) -> t a b -> m
 bifoldMap1Default f g = getConst . bitraverse1 (Const . f) (Const . g)
