diff --git a/bifunctors.cabal b/bifunctors.cabal
--- a/bifunctors.cabal
+++ b/bifunctors.cabal
@@ -1,6 +1,6 @@
 name:          bifunctors
 category:      Data, Functors
-version:       3.0.3
+version:       3.0.4
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -29,6 +29,8 @@
   exposed-modules:
     Data.Bifunctor
     Data.Bifunctor.Apply
+    Data.Bifunctor.Flip
+    Data.Bifunctor.Wrapped
     Data.Bifoldable
     Data.Bitraversable
     Data.Semigroup.Bifoldable
diff --git a/src/Data/Bifunctor.hs b/src/Data/Bifunctor.hs
--- a/src/Data/Bifunctor.hs
+++ b/src/Data/Bifunctor.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Bifunctor
--- Copyright   :  (C) 2008-2011 Edward Kmett,
+-- Copyright   :  (C) 2008-2013 Edward Kmett,
 -- License     :  BSD-style (see the file LICENSE)
 --
 -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
@@ -9,20 +9,62 @@
 -- Portability :  portable
 --
 ----------------------------------------------------------------------------
-module Data.Bifunctor (Bifunctor(..)) where
+module Data.Bifunctor
+  ( Bifunctor(..)
+  ) where
 
 import Control.Applicative
 
 -- | 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 #-}
diff --git a/src/Data/Bifunctor/Apply.hs b/src/Data/Bifunctor/Apply.hs
--- a/src/Data/Bifunctor/Apply.hs
+++ b/src/Data/Bifunctor/Apply.hs
@@ -10,8 +10,7 @@
 --
 ----------------------------------------------------------------------------
 module Data.Bifunctor.Apply (
-  -- * Functors
-  -- * BiAppliable bifunctors
+  -- * Biappliable bifunctors
     Biapply(..)
   , (<<$>>)
   , (<<..>>)
@@ -31,12 +30,18 @@
 class Bifunctor p => Biapply p where
   (<<.>>) :: p (a -> b) (c -> d) -> p a c -> p b d
 
-  -- | a .> b = const id <$> a <.> b
+  -- |
+  -- @
+  -- a '.>' b ≡ 'const' 'id' '<$>' a '<.>' b
+  -- @
   (.>>) :: p a b -> p c d -> p c d
   a .>> b = bimap (const id) (const id) <<$>> a <<.>> b
   {-# INLINE (.>>) #-}
 
-  -- | a <. b = const <$> a <.> b
+  -- |
+  -- @
+  -- a '<.' b ≡ 'const' '<$>' a '<.>' b
+  -- @
   (<<.) :: p a b -> p c d -> p a b
   a <<. b = bimap const const <<$>> a <<.>> b
   {-# INLINE (<<.) #-}
diff --git a/src/Data/Bifunctor/Flip.hs b/src/Data/Bifunctor/Flip.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bifunctor/Flip.hs
@@ -0,0 +1,69 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Bifunctor.Flip
+-- 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.Flip
+  ( Flip(..)
+  ) where
+
+import Control.Applicative
+import Data.Bifunctor
+import Data.Bifunctor.Apply
+import Data.Bifoldable
+import Data.Bitraversable
+import Data.Foldable
+import Data.Monoid
+import Data.Semigroup.Bifoldable
+import Data.Semigroup.Bitraversable
+import Data.Traversable
+
+-- | Make a 'Functor' over the first argument of a 'Bifunctor'.
+newtype Flip p a b = Flip { runFlip :: p b a }
+  deriving (Eq,Ord,Show,Read)
+
+instance Bifunctor p => Bifunctor (Flip p) where
+  first f = Flip . second f . runFlip
+  {-# INLINE first #-}
+  second f = Flip . first f . runFlip
+  {-# INLINE second #-}
+  bimap f g = Flip . bimap g f . runFlip
+  {-# INLINE bimap #-}
+
+instance Bifunctor p => Functor (Flip p a) where
+  fmap f = Flip . first f . runFlip
+  {-# INLINE fmap #-}
+
+instance Biapply p => Biapply (Flip p) where
+  Flip fg <<.>> Flip xy = Flip (fg <<.>> xy)
+  {-# INLINE (<<.>>) #-}
+
+instance Bifoldable p => Bifoldable (Flip p) where
+  bifoldMap f g = bifoldMap g f . runFlip
+  {-# INLINE bifoldMap #-}
+
+instance Bifoldable p => Foldable (Flip p a) where
+  foldMap f = bifoldMap f (const mempty) . runFlip
+  {-# INLINE foldMap #-}
+
+instance Bitraversable p => Bitraversable (Flip p) where
+  bitraverse f g = fmap Flip . bitraverse g f . runFlip
+  {-# INLINE bitraverse #-}
+
+instance Bitraversable p => Traversable (Flip p a) where
+  traverse f = fmap Flip . bitraverse f pure . runFlip
+  {-# INLINE traverse #-}
+
+instance Bifoldable1 p => Bifoldable1 (Flip p) where
+  bifoldMap1 f g = bifoldMap1 g f . runFlip
+  {-# INLINE bifoldMap1 #-}
+
+instance Bitraversable1 p => Bitraversable1 (Flip p) where
+  bitraverse1 f g = fmap Flip . bitraverse1 g f . runFlip
+  {-# INLINE bitraverse1 #-}
diff --git a/src/Data/Bifunctor/Wrapped.hs b/src/Data/Bifunctor/Wrapped.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bifunctor/Wrapped.hs
@@ -0,0 +1,68 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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.Wrapped
+  ( WrappedBifunctor(..)
+  ) where
+
+import Control.Applicative
+import Data.Bifoldable
+import Data.Bifunctor
+import Data.Bifunctor.Apply
+import Data.Bitraversable
+import Data.Foldable
+import Data.Monoid
+import Data.Semigroup.Bifoldable
+import Data.Semigroup.Bitraversable
+import Data.Traversable
+
+-- | Make a 'Functor' over the second argument of a 'Bifunctor'.
+newtype WrappedBifunctor p a b = WrapBifunctor { unwrapBifunctor :: p a b }
+  deriving (Eq,Ord,Show,Read)
+
+instance Bifunctor p => Bifunctor (WrappedBifunctor p) where
+  first f = WrapBifunctor . first f . unwrapBifunctor
+  {-# INLINE first #-}
+  second f = WrapBifunctor . second f . unwrapBifunctor
+  {-# INLINE second #-}
+  bimap f g = WrapBifunctor . bimap f g . unwrapBifunctor
+  {-# INLINE bimap #-}
+
+instance Bifunctor p => Functor (WrappedBifunctor p a) where
+  fmap f = WrapBifunctor . second f . unwrapBifunctor
+  {-# INLINE fmap #-}
+
+instance Biapply p => Biapply (WrappedBifunctor p) where
+  WrapBifunctor fg <<.>> WrapBifunctor xy = WrapBifunctor (fg <<.>> xy)
+
+instance Bifoldable p => Foldable (WrappedBifunctor p a) where
+  foldMap f = bifoldMap (const mempty) f . unwrapBifunctor
+  {-# INLINE foldMap #-}
+
+instance Bifoldable p => Bifoldable (WrappedBifunctor p) where
+  bifoldMap f g = bifoldMap f g . unwrapBifunctor
+  {-# INLINE bifoldMap #-}
+
+instance Bitraversable p => Traversable (WrappedBifunctor p a) where
+  traverse f = fmap WrapBifunctor . bitraverse pure f . unwrapBifunctor
+  {-# INLINE traverse #-}
+
+instance Bitraversable p => Bitraversable (WrappedBifunctor p) where
+  bitraverse f g = fmap WrapBifunctor . bitraverse f g . unwrapBifunctor
+  {-# INLINE bitraverse #-}
+
+instance Bifoldable1 p => Bifoldable1 (WrappedBifunctor p) where
+  bifoldMap1 f g = bifoldMap1 f g . unwrapBifunctor
+  {-# INLINE bifoldMap1 #-}
+
+instance Bitraversable1 p => Bitraversable1 (WrappedBifunctor p) where
+  bitraverse1 f g = fmap WrapBifunctor . bitraverse1 f g . unwrapBifunctor
+  {-# INLINE bitraverse1 #-}
