diff --git a/.ghci b/.ghci
new file mode 100644
--- /dev/null
+++ b/.ghci
@@ -0,0 +1,1 @@
+:set -isrc -idist/build/autogen -optP-include -optPdist/build/autogen/cabal_macros.h
diff --git a/.gitignore b/.gitignore
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+_darcs
+dist
diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,1 +1,8 @@
 language: haskell
+notifications:
+  irc:
+    channels:
+      - "irc.freenode.org#haskell-lens"
+    skip_join: true
+    template:
+      - "\x0313comonad-transformers\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"
diff --git a/.vim.custom b/.vim.custom
new file mode 100644
--- /dev/null
+++ b/.vim.custom
@@ -0,0 +1,31 @@
+" Add the following to your .vimrc to automatically load this on startup
+
+" if filereadable(".vim.custom")
+"     so .vim.custom
+" endif
+
+function StripTrailingWhitespace()
+  let myline=line(".")
+  let mycolumn = col(".")
+  silent %s/  *$//
+  call cursor(myline, mycolumn)
+endfunction
+
+" enable syntax highlighting
+syntax on
+
+" search for the tags file anywhere between here and /
+set tags=TAGS;/
+
+" highlight tabs and trailing spaces
+set listchars=tab:‗‗,trail:‗
+set list
+
+" f2 runs hasktags
+map <F2> :exec ":!hasktags -x -c --ignore src"<CR><CR>
+
+" strip trailing whitespace before saving
+" au BufWritePre *.hs,*.markdown silent! cal StripTrailingWhitespace()
+
+" rebuild hasktags after saving
+au BufWritePost *.hs silent! :exec ":!hasktags -x -c --ignore src"
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
--- a/CHANGELOG
+++ /dev/null
@@ -1,4 +0,0 @@
-2.1:
- * Removed Discont
- * Switched to mkTyCon3
- * Upgraded to transformers 0.3
diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.markdown
@@ -0,0 +1,12 @@
+3.0.1
+-----
+* Removed upper bounds on my other dependencies
+* Directory layout change
+* Added support files
+* Travis build notification to IRC
+
+2.1
+---
+* Removed Discont
+* Switched to mkTyCon3
+* Upgraded to transformers 0.3
diff --git a/Control/Comonad/Hoist/Class.hs b/Control/Comonad/Hoist/Class.hs
deleted file mode 100644
--- a/Control/Comonad/Hoist/Class.hs
+++ /dev/null
@@ -1,29 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Comonad.Hoist.Class
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
-----------------------------------------------------------------------------
-module Control.Comonad.Hoist.Class (ComonadHoist(..)) where
-
-import Control.Comonad
-import Control.Monad.Trans.Identity
-import Data.Functor.Identity
-
-class ComonadHoist t where
-  -- | Ideally we would offer a way to lift comonad homomorphisms
-  -- but this isn't Haskell 98, so we settle for the most common case
-  -- here.
-  --
-  -- > liftTrans :: (forall a. w a -> v a) -> t w a -> t v a 
-  -- > cohoist = liftTrans (Identity . extract)
-  cohoist :: Comonad w => t w a -> t Identity a
-
--- avoiding orphans
-
-instance ComonadHoist IdentityT where
-  cohoist = IdentityT . Identity . extract . runIdentityT
diff --git a/Control/Comonad/Trans/Class.hs b/Control/Comonad/Trans/Class.hs
deleted file mode 100644
--- a/Control/Comonad/Trans/Class.hs
+++ /dev/null
@@ -1,22 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Comonad.Trans.Class
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
-----------------------------------------------------------------------------
-module Control.Comonad.Trans.Class
-  ( ComonadTrans(..) ) where
-
-import Control.Comonad
-import Control.Monad.Trans.Identity
-
-class ComonadTrans t where
-  lower :: Comonad w => t w a -> w a
-
--- avoiding orphans
-instance ComonadTrans IdentityT where
-  lower = runIdentityT
diff --git a/Control/Comonad/Trans/Env.hs b/Control/Comonad/Trans/Env.hs
deleted file mode 100644
--- a/Control/Comonad/Trans/Env.hs
+++ /dev/null
@@ -1,140 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE FlexibleContexts #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Comonad.Trans.Env
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
---
--- The environment comonad transformer (aka coreader).
--- This adds an extra value that can be accessed in the environment.
---
--- Left adjoint to the reader comonad.
-----------------------------------------------------------------------------
-module Control.Comonad.Trans.Env
-  (
-  -- * The strict environment comonad
-    Env
-  , env
-  , runEnv
-  -- * The strict environment comonad transformer
-  , EnvT(..)
-  , runEnvT
-  , lowerEnvT
-  -- * Combinators
-  , ask
-  , asks
-  , local
-  ) where
-
-import Control.Comonad
-import Control.Comonad.Hoist.Class
-import Control.Comonad.Trans.Class
-import Data.Foldable
-import Data.Traversable
-import Data.Functor.Apply
-import Data.Functor.Identity
-import Data.Functor.Extend
-import Data.Semigroup
-
-#ifdef __GLASGOW_HASKELL__
-import Data.Data
-
-instance (Typeable s, Typeable1 w) => Typeable1 (EnvT s w) where
-  typeOf1 dswa = mkTyConApp envTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
-    where
-      s :: EnvT s w a -> s
-      s = undefined
-      w :: EnvT s w a -> w a
-      w = undefined
-
-envTTyCon :: TyCon
-#if __GLASGOW_HASKELL__ < 704
-envTTyCon = mkTyCon "Control.Comonad.Trans.Env.EnvT"
-#else
-envTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Env" "EnvT"
-#endif
-{-# NOINLINE envTTyCon #-}
-
-instance (Typeable s, Typeable1 w, Typeable a) => Typeable (EnvT s w a) where
-  typeOf = typeOfDefault
-
-instance
-  ( Data e
-  , Typeable1 w, Data (w a)
-  , Data a
-  ) => Data (EnvT e w a) where
-    gfoldl f z (EnvT e wa) = z EnvT `f` e `f` wa
-    toConstr _ = envTConstr
-    gunfold k z c = case constrIndex c of
-        1 -> k (k (z EnvT))
-        _ -> error "gunfold"
-    dataTypeOf _ = envTDataType
-    dataCast1 f = gcast1 f
-
-envTConstr :: Constr
-envTConstr = mkConstr envTDataType "EnvT" [] Prefix
-{-# NOINLINE envTConstr #-}
-
-envTDataType :: DataType
-envTDataType = mkDataType "Control.Comonad.Trans.Env.EnvT" [envTConstr]
-{-# NOINLINE envTDataType #-}
-
-#endif
-
-type Env e = EnvT e Identity
-data EnvT e w a = EnvT e (w a)
-
-env :: e -> a -> Env e a
-env e a = EnvT e (Identity a)
-
-runEnv :: Env e a -> (e, a)
-runEnv (EnvT e (Identity a)) = (e, a)
-
-runEnvT :: EnvT e w a -> (e, w a)
-runEnvT (EnvT e wa) = (e, wa)
-
-instance Functor w => Functor (EnvT e w) where
-  fmap g (EnvT e wa) = EnvT e (fmap g wa)
-
-instance Extend w => Extend (EnvT e w) where
-  duplicated (EnvT e wa) = EnvT e (extended (EnvT e) wa)
-
-instance Comonad w => Comonad (EnvT e w) where
-  duplicate (EnvT e wa) = EnvT e (extend (EnvT e) wa)
-  extract (EnvT _ wa) = extract wa
-
-instance ComonadTrans (EnvT e) where
-  lower (EnvT _ wa) = wa
-
-lowerEnvT :: EnvT e w a -> w a
-lowerEnvT (EnvT _ wa) = wa
-
-instance ComonadHoist (EnvT e) where
-  cohoist (EnvT e wa) = EnvT e (Identity (extract wa))
-
-instance (Semigroup e, Apply w) => Apply (EnvT e w) where
-  EnvT ef wf <.> EnvT ea wa = EnvT (ef <> ea) (wf <.> wa)
-
-instance (Semigroup e, ComonadApply w) => ComonadApply (EnvT e w) where
-  EnvT ef wf <@> EnvT ea wa = EnvT (ef <> ea) (wf <@> wa)
-
-instance Foldable w => Foldable (EnvT e w) where
-  foldMap f (EnvT _ w) = foldMap f w
-
-instance Traversable w => Traversable (EnvT e w) where
-  traverse f (EnvT e w) = EnvT e <$> traverse f w
-
-ask :: EnvT e w a -> e
-ask (EnvT e _) = e
-
-asks :: (e -> f) -> EnvT e w a -> f
-asks f (EnvT e _) = f e
-
-local :: (e -> e) -> EnvT e w a -> EnvT e w a
-local f (EnvT e wa) = EnvT (f e) wa
-
diff --git a/Control/Comonad/Trans/Identity.hs b/Control/Comonad/Trans/Identity.hs
deleted file mode 100644
--- a/Control/Comonad/Trans/Identity.hs
+++ /dev/null
@@ -1,16 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Comonad.Trans.Identity
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
---
-----------------------------------------------------------------------------
-module Control.Comonad.Trans.Identity
-  ( IdentityT(..)
-  ) where
-
-import Control.Monad.Trans.Identity
diff --git a/Control/Comonad/Trans/Store.hs b/Control/Comonad/Trans/Store.hs
deleted file mode 100644
--- a/Control/Comonad/Trans/Store.hs
+++ /dev/null
@@ -1,134 +0,0 @@
-{-# LANGUAGE CPP #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Comonad.Trans.Store
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
---
--- The strict store (state-in-context/costate) comonad transformer is subject to the laws:
---
--- > x = seek (pos x) x
--- > y = pos (seek y x)
--- > seek y x = seek y (seek z x)
---
--- Thanks go to Russell O'Connor and Daniel Peebles for their help formulating
--- and proving the laws for this comonad transformer.
-----------------------------------------------------------------------------
-module Control.Comonad.Trans.Store
-  (
-  -- * The Store comonad
-    Store, store, runStore
-  -- * The Store comonad transformer
-  , StoreT(..), runStoreT
-  -- * Operations
-  , pos
-  , seek, seeks
-  , peek, peeks
-  , experiment
-  ) where
-
-import Control.Applicative
-import Control.Comonad
-import Control.Comonad.Hoist.Class
-import Control.Comonad.Trans.Class
-import Data.Functor.Identity
-import Data.Functor.Apply
-import Data.Functor.Extend
-import Data.Semigroup
-
-#ifdef __GLASGOW_HASKELL__
-import Data.Typeable
-instance (Typeable s, Typeable1 w) => Typeable1 (StoreT s w) where
-  typeOf1 dswa = mkTyConApp storeTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
-    where
-      s :: StoreT s w a -> s
-      s = undefined
-      w :: StoreT s w a -> w a
-      w = undefined
-
-instance (Typeable s, Typeable1 w, Typeable a) => Typeable (StoreT s w a) where
-  typeOf = typeOfDefault
-
-storeTTyCon :: TyCon
-#if __GLASGOW_HASKELL__ < 704
-storeTTyCon = mkTyCon "Control.Comonad.Trans.Store.StoreT"
-#else
-storeTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Store" "StoreT"
-#endif
-{-# NOINLINE storeTTyCon #-}
-#endif
-
-type Store s = StoreT s Identity
-
-store :: (s -> a) -> s -> Store s a
-store f s = StoreT (Identity f) s
-
-runStore :: Store s a -> (s -> a, s)
-runStore (StoreT (Identity f) s) = (f, s)
-
-data StoreT s w a = StoreT (w (s -> a)) s
-
-runStoreT :: StoreT s w a -> (w (s -> a), s)
-runStoreT (StoreT wf s) = (wf, s)
-
-experiment :: (Comonad w, Functor f) => (s -> f s) -> StoreT s w a -> f a
-experiment f (StoreT wf s) = extract wf <$> f s
-
-instance Functor w => Functor (StoreT s w) where
-  fmap f (StoreT wf s) = StoreT (fmap (f .) wf) s
-
-instance (Apply w, Semigroup s) => Apply (StoreT s w) where
-  StoreT ff m <.> StoreT fa n = StoreT ((<*>) <$> ff <.> fa) (m <> n)
-
-instance (ComonadApply w, Semigroup s) => ComonadApply (StoreT s w) where
-  StoreT ff m <@> StoreT fa n = StoreT ((<*>) <$> ff <@> fa) (m <> n)
-
-instance (Applicative w, Monoid s) => Applicative (StoreT s w) where
-  pure a = StoreT (pure (const a)) mempty
-  StoreT ff m <*> StoreT fa n = StoreT ((<*>) <$> ff <*> fa) (mappend m n)
-
-instance Extend w => Extend (StoreT s w) where
-  duplicated (StoreT wf s) = StoreT (extended StoreT wf) s
-  extended f (StoreT wf s) = StoreT (extended (\wf' s' -> f (StoreT wf' s')) wf) s
-
-instance Comonad w => Comonad (StoreT s w) where
-  duplicate (StoreT wf s) = StoreT (extend StoreT wf) s
-  extend f (StoreT wf s) = StoreT (extend (\wf' s' -> f (StoreT wf' s')) wf) s
-  extract (StoreT wf s) = extract wf s
-
-instance ComonadTrans (StoreT s) where
-  lower (StoreT f s) = fmap ($s) f
-
-instance ComonadHoist (StoreT s) where
-  cohoist (StoreT f s) = StoreT (Identity (extract f)) s
-
--- | Read the current position
-pos :: StoreT s w a -> s
-pos (StoreT _ s) = s
-
--- | Seek to an absolute location
---
--- > seek s = peek s . duplicate
-seek :: Comonad w => s -> StoreT s w a -> StoreT s w a
-seek s ~(StoreT f _) = StoreT f s
-
--- | Seek to a relative location
---
--- > seeks f = peeks f . duplicate
-seeks :: Comonad w => (s -> s) -> StoreT s w a -> StoreT s w a
-seeks f ~(StoreT g s) = StoreT g (f s)
-
--- | Peek at a value at a given absolute location
---
--- > peek x . extend (peek y) = peek y
-peek :: Comonad w => s -> StoreT s w a -> a
-peek s (StoreT g _) = extract g s
-
--- | Peek at a value at a given relative location
-peeks :: Comonad w => (s -> s) -> StoreT s w a -> a
-peeks f ~(StoreT g s) = extract g (f s)
-
diff --git a/Control/Comonad/Trans/Traced.hs b/Control/Comonad/Trans/Traced.hs
deleted file mode 100644
--- a/Control/Comonad/Trans/Traced.hs
+++ /dev/null
@@ -1,111 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Comonad.Trans.Traced
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
---
--- The trace comonad transformer (aka the cowriter or exponential comonad transformer).
---
-----------------------------------------------------------------------------
-module Control.Comonad.Trans.Traced
-  (
-  -- * Traced comonad
-    Traced
-  , traced
-  , runTraced
-  -- * Traced comonad transformer
-  , TracedT(..)
-  -- * Operations
-  , trace
-  , listen
-  , listens
-  , censor
-  ) where
-
-import Control.Applicative
-import Control.Monad.Instances ()
-import Control.Monad (ap)
-import Control.Comonad
-import Control.Comonad.Hoist.Class
-import Control.Comonad.Trans.Class
-import Data.Distributive
-import Data.Functor.Apply
-import Data.Functor.Extend
-import Data.Functor.Identity
-import Data.Semigroup
-import Data.Typeable
-
-type Traced m = TracedT m Identity
-
-traced :: (m -> a) -> Traced m a
-traced f = TracedT (Identity f)
-
-runTraced :: Traced m a -> m -> a
-runTraced (TracedT (Identity f)) = f
-
-newtype TracedT m w a = TracedT { runTracedT :: w (m -> a) }
-
-instance Functor w => Functor (TracedT m w) where
-  fmap g = TracedT . fmap (g .) . runTracedT
-
-instance Apply w => Apply (TracedT m w) where
-  TracedT wf <.> TracedT wa = TracedT (ap <$> wf <.> wa)
-
-instance (ComonadApply w, Monoid m) => ComonadApply (TracedT m w) where
-  TracedT wf <@> TracedT wa = TracedT (ap <$> wf <@> wa)
-
-instance Applicative w => Applicative (TracedT m w) where
-  pure = TracedT . pure . const
-  TracedT wf <*> TracedT wa = TracedT (ap <$> wf <*> wa)
-
-instance (Extend w, Semigroup m) => Extend (TracedT m w) where
-  extended f = TracedT . extended (\wf m -> f (TracedT (fmap (. (<>) m) wf))) . runTracedT
-
-instance (Comonad w, Monoid m) => Comonad (TracedT m w) where
-  extend f = TracedT . extend (\wf m -> f (TracedT (fmap (. mappend m) wf))) . runTracedT
-  extract (TracedT wf) = extract wf mempty
-
-instance Monoid m => ComonadTrans (TracedT m) where
-  lower = fmap ($mempty) . runTracedT
-
-instance Monoid m => ComonadHoist (TracedT m) where
-  cohoist = traced . extract . runTracedT
-
-instance Distributive w => Distributive (TracedT m w) where
-  distribute = TracedT . fmap (\tma m -> fmap ($m) tma) . collect runTracedT
-
-trace :: Comonad w => m -> TracedT m w a -> a
-trace m (TracedT wf) = extract wf m
-
-listen :: Functor w => TracedT m w a -> TracedT m w (a, m)
-listen = TracedT . fmap (\f m -> (f m, m)) . runTracedT
-
-listens :: Functor w => (m -> b) -> TracedT m w a -> TracedT m w (a, b)
-listens g = TracedT . fmap (\f m -> (f m, g m)) . runTracedT
-
-censor :: Functor w => (m -> m) -> TracedT m w a -> TracedT m w a
-censor g = TracedT . fmap (. g) . runTracedT
-
-#ifdef __GLASGOW_HASKELL__
-
-instance (Typeable s, Typeable1 w) => Typeable1 (TracedT s w) where
-  typeOf1 dswa = mkTyConApp tracedTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
-    where
-      s :: TracedT s w a -> s
-      s = undefined
-      w :: TracedT s w a -> w a
-      w = undefined
-
-tracedTTyCon :: TyCon
-#if __GLASGOW_HASKELL__ < 704
-tracedTTyCon = mkTyCon "Control.Comonad.Trans.Traced.TracedT"
-#else
-tracedTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Traced" "TracedT"
-#endif
-{-# NOINLINE tracedTTyCon #-}
-
-#endif
diff --git a/Data/Functor/Composition.hs b/Data/Functor/Composition.hs
deleted file mode 100644
--- a/Data/Functor/Composition.hs
+++ /dev/null
@@ -1,14 +0,0 @@
-module Data.Functor.Composition
-  ( Composition(..) ) where
-
-import Data.Functor.Compose
-
--- | We often need to distinguish between various forms of Functor-like composition in Haskell in order to please the type system.
--- This lets us work with these representations uniformly.
-class Composition o where
-  decompose :: o f g x -> f (g x)
-  compose :: f (g x) -> o f g x
-
-instance Composition Compose where
-  decompose = getCompose
-  compose = Compose
diff --git a/Data/Functor/Coproduct.hs b/Data/Functor/Coproduct.hs
deleted file mode 100644
--- a/Data/Functor/Coproduct.hs
+++ /dev/null
@@ -1,68 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.Functor.Coproduct
--- Copyright   :  (C) 2008-2011 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
---
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  provisional
--- Portability :  portable
-----------------------------------------------------------------------------
-module Data.Functor.Coproduct
-  ( Coproduct(..)
-  , left
-  , right
-  , coproduct
-  ) where
-
-import Control.Comonad
-import Data.Functor.Contravariant
-import Data.Functor.Extend
-import Data.Foldable
-import Data.Traversable
-import Data.Semigroup.Foldable
-import Data.Semigroup.Traversable
-
-newtype Coproduct f g a = Coproduct { getCoproduct :: Either (f a) (g a) }
-
-left :: f a -> Coproduct f g a
-left = Coproduct . Left
-
-right :: g a -> Coproduct f g a
-right = Coproduct . Right
-
-coproduct :: (f a -> b) -> (g a -> b) -> Coproduct f g a -> b
-coproduct f g = either f g . getCoproduct
-
-instance (Functor f, Functor g) => Functor (Coproduct f g) where
-  fmap f = Coproduct . coproduct (Left . fmap f) (Right . fmap f)
-
-instance (Foldable f, Foldable g) => Foldable (Coproduct f g) where
-  foldMap f = coproduct (foldMap f) (foldMap f)
-
-instance (Foldable1 f, Foldable1 g) => Foldable1 (Coproduct f g) where
-  foldMap1 f = coproduct (foldMap1 f) (foldMap1 f)
-
-instance (Traversable f, Traversable g) => Traversable (Coproduct f g) where
-  traverse f = coproduct
-    (fmap (Coproduct . Left) . traverse f)
-    (fmap (Coproduct . Right) . traverse f)
-
-instance (Traversable1 f, Traversable1 g) => Traversable1 (Coproduct f g) where
-  traverse1 f = coproduct
-    (fmap (Coproduct . Left) . traverse1 f)
-    (fmap (Coproduct . Right) . traverse1 f)
-
-instance (Extend f, Extend g) => Extend (Coproduct f g) where
-  extended f = Coproduct . coproduct
-    (Left . extended (f . Coproduct . Left))
-    (Right . extended (f . Coproduct . Right))
-
-instance (Comonad f, Comonad g) => Comonad (Coproduct f g) where
-  extend f = Coproduct . coproduct
-    (Left . extend (f . Coproduct . Left))
-    (Right . extend (f . Coproduct . Right))
-  extract = coproduct extract extract
-
-instance (Contravariant f, Contravariant g) => Contravariant (Coproduct f g) where
-  contramap f = Coproduct . coproduct (Left . contramap f) (Right . contramap f)
diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,19 @@
+comonad-transformers
+==========
+
+[![Build Status](https://secure.travis-ci.org/ekmett/comonad-transformers.png?branch=master)](http://travis-ci.org/ekmett/comonad-transformers)
+
+This package provides a standard set of comonad transformers for Haskell.
+
+Like the `transformers` package this package is `Haskell 98`.
+
+Clases for these types are provided by the [`comonads-fd`](/ekmett/comonads-fd) package.
+
+Contact Information
+-------------------
+
+Contributions and bug reports are welcome!
+
+Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.
+
+-Edward Kmett
diff --git a/comonad-transformers.cabal b/comonad-transformers.cabal
--- a/comonad-transformers.cabal
+++ b/comonad-transformers.cabal
@@ -1,6 +1,6 @@
 name:          comonad-transformers
 category:      Control, Comonads
-version:       3.0.0.1
+version:       3.0.1
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -13,7 +13,14 @@
 synopsis:      Comonad transformers
 description:   Comonad transformers
 build-type:    Simple
-extra-source-files: coq/Store.v CHANGELOG .travis.yml
+extra-source-files:
+  coq/Store.v
+  CHANGELOG.markdown
+  README.markdown
+  .travis.yml
+  .ghci
+  .gitignore
+  .vim.custom
 
 source-repository head
   type: git
@@ -22,12 +29,12 @@
 library
   build-depends:
     base          >= 4       && < 5,
-    comonad       >= 3.0     && < 3.1,
+    comonad       >= 3.0,
     containers    >= 0.3     && < 0.6,
-    contravariant >= 0.2.0.1 && < 0.3,
-    distributive  >= 0.2.2   && < 0.4,
-    semigroupoids >= 3.0     && < 3.1,
-    semigroups    >= 0.8.3.1 && < 0.9,
+    contravariant >= 0.2.0.1,
+    distributive  >= 0.2.2,
+    semigroupoids >= 3.0,
+    semigroups    >= 0.8.3.1,
     transformers  >= 0.2     && < 0.4
 
   extensions: CPP
@@ -42,4 +49,5 @@
     Data.Functor.Coproduct
     Data.Functor.Composition
 
-  ghc-options:      -Wall
+  ghc-options: -Wall
+  hs-source-dirs: src
diff --git a/src/Control/Comonad/Hoist/Class.hs b/src/Control/Comonad/Hoist/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Hoist/Class.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Hoist.Class
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+----------------------------------------------------------------------------
+module Control.Comonad.Hoist.Class (ComonadHoist(..)) where
+
+import Control.Comonad
+import Control.Monad.Trans.Identity
+import Data.Functor.Identity
+
+class ComonadHoist t where
+  -- | Ideally we would offer a way to lift comonad homomorphisms
+  -- but this isn't Haskell 98, so we settle for the most common case
+  -- here.
+  --
+  -- > liftTrans :: (forall a. w a -> v a) -> t w a -> t v a 
+  -- > cohoist = liftTrans (Identity . extract)
+  cohoist :: Comonad w => t w a -> t Identity a
+
+-- avoiding orphans
+
+instance ComonadHoist IdentityT where
+  cohoist = IdentityT . Identity . extract . runIdentityT
diff --git a/src/Control/Comonad/Trans/Class.hs b/src/Control/Comonad/Trans/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Trans/Class.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Class
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+----------------------------------------------------------------------------
+module Control.Comonad.Trans.Class
+  ( ComonadTrans(..) ) where
+
+import Control.Comonad
+import Control.Monad.Trans.Identity
+
+class ComonadTrans t where
+  lower :: Comonad w => t w a -> w a
+
+-- avoiding orphans
+instance ComonadTrans IdentityT where
+  lower = runIdentityT
diff --git a/src/Control/Comonad/Trans/Env.hs b/src/Control/Comonad/Trans/Env.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Trans/Env.hs
@@ -0,0 +1,140 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Env
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- The environment comonad transformer (aka coreader).
+-- This adds an extra value that can be accessed in the environment.
+--
+-- Left adjoint to the reader comonad.
+----------------------------------------------------------------------------
+module Control.Comonad.Trans.Env
+  (
+  -- * The strict environment comonad
+    Env
+  , env
+  , runEnv
+  -- * The strict environment comonad transformer
+  , EnvT(..)
+  , runEnvT
+  , lowerEnvT
+  -- * Combinators
+  , ask
+  , asks
+  , local
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Hoist.Class
+import Control.Comonad.Trans.Class
+import Data.Foldable
+import Data.Traversable
+import Data.Functor.Apply
+import Data.Functor.Identity
+import Data.Functor.Extend
+import Data.Semigroup
+
+#ifdef __GLASGOW_HASKELL__
+import Data.Data
+
+instance (Typeable s, Typeable1 w) => Typeable1 (EnvT s w) where
+  typeOf1 dswa = mkTyConApp envTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
+    where
+      s :: EnvT s w a -> s
+      s = undefined
+      w :: EnvT s w a -> w a
+      w = undefined
+
+envTTyCon :: TyCon
+#if __GLASGOW_HASKELL__ < 704
+envTTyCon = mkTyCon "Control.Comonad.Trans.Env.EnvT"
+#else
+envTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Env" "EnvT"
+#endif
+{-# NOINLINE envTTyCon #-}
+
+instance (Typeable s, Typeable1 w, Typeable a) => Typeable (EnvT s w a) where
+  typeOf = typeOfDefault
+
+instance
+  ( Data e
+  , Typeable1 w, Data (w a)
+  , Data a
+  ) => Data (EnvT e w a) where
+    gfoldl f z (EnvT e wa) = z EnvT `f` e `f` wa
+    toConstr _ = envTConstr
+    gunfold k z c = case constrIndex c of
+        1 -> k (k (z EnvT))
+        _ -> error "gunfold"
+    dataTypeOf _ = envTDataType
+    dataCast1 f = gcast1 f
+
+envTConstr :: Constr
+envTConstr = mkConstr envTDataType "EnvT" [] Prefix
+{-# NOINLINE envTConstr #-}
+
+envTDataType :: DataType
+envTDataType = mkDataType "Control.Comonad.Trans.Env.EnvT" [envTConstr]
+{-# NOINLINE envTDataType #-}
+
+#endif
+
+type Env e = EnvT e Identity
+data EnvT e w a = EnvT e (w a)
+
+env :: e -> a -> Env e a
+env e a = EnvT e (Identity a)
+
+runEnv :: Env e a -> (e, a)
+runEnv (EnvT e (Identity a)) = (e, a)
+
+runEnvT :: EnvT e w a -> (e, w a)
+runEnvT (EnvT e wa) = (e, wa)
+
+instance Functor w => Functor (EnvT e w) where
+  fmap g (EnvT e wa) = EnvT e (fmap g wa)
+
+instance Extend w => Extend (EnvT e w) where
+  duplicated (EnvT e wa) = EnvT e (extended (EnvT e) wa)
+
+instance Comonad w => Comonad (EnvT e w) where
+  duplicate (EnvT e wa) = EnvT e (extend (EnvT e) wa)
+  extract (EnvT _ wa) = extract wa
+
+instance ComonadTrans (EnvT e) where
+  lower (EnvT _ wa) = wa
+
+lowerEnvT :: EnvT e w a -> w a
+lowerEnvT (EnvT _ wa) = wa
+
+instance ComonadHoist (EnvT e) where
+  cohoist (EnvT e wa) = EnvT e (Identity (extract wa))
+
+instance (Semigroup e, Apply w) => Apply (EnvT e w) where
+  EnvT ef wf <.> EnvT ea wa = EnvT (ef <> ea) (wf <.> wa)
+
+instance (Semigroup e, ComonadApply w) => ComonadApply (EnvT e w) where
+  EnvT ef wf <@> EnvT ea wa = EnvT (ef <> ea) (wf <@> wa)
+
+instance Foldable w => Foldable (EnvT e w) where
+  foldMap f (EnvT _ w) = foldMap f w
+
+instance Traversable w => Traversable (EnvT e w) where
+  traverse f (EnvT e w) = EnvT e <$> traverse f w
+
+ask :: EnvT e w a -> e
+ask (EnvT e _) = e
+
+asks :: (e -> f) -> EnvT e w a -> f
+asks f (EnvT e _) = f e
+
+local :: (e -> e) -> EnvT e w a -> EnvT e w a
+local f (EnvT e wa) = EnvT (f e) wa
+
diff --git a/src/Control/Comonad/Trans/Identity.hs b/src/Control/Comonad/Trans/Identity.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Trans/Identity.hs
@@ -0,0 +1,16 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Identity
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+----------------------------------------------------------------------------
+module Control.Comonad.Trans.Identity
+  ( IdentityT(..)
+  ) where
+
+import Control.Monad.Trans.Identity
diff --git a/src/Control/Comonad/Trans/Store.hs b/src/Control/Comonad/Trans/Store.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Trans/Store.hs
@@ -0,0 +1,134 @@
+{-# LANGUAGE CPP #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Store
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- The strict store (state-in-context/costate) comonad transformer is subject to the laws:
+--
+-- > x = seek (pos x) x
+-- > y = pos (seek y x)
+-- > seek y x = seek y (seek z x)
+--
+-- Thanks go to Russell O'Connor and Daniel Peebles for their help formulating
+-- and proving the laws for this comonad transformer.
+----------------------------------------------------------------------------
+module Control.Comonad.Trans.Store
+  (
+  -- * The Store comonad
+    Store, store, runStore
+  -- * The Store comonad transformer
+  , StoreT(..), runStoreT
+  -- * Operations
+  , pos
+  , seek, seeks
+  , peek, peeks
+  , experiment
+  ) where
+
+import Control.Applicative
+import Control.Comonad
+import Control.Comonad.Hoist.Class
+import Control.Comonad.Trans.Class
+import Data.Functor.Identity
+import Data.Functor.Apply
+import Data.Functor.Extend
+import Data.Semigroup
+
+#ifdef __GLASGOW_HASKELL__
+import Data.Typeable
+instance (Typeable s, Typeable1 w) => Typeable1 (StoreT s w) where
+  typeOf1 dswa = mkTyConApp storeTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
+    where
+      s :: StoreT s w a -> s
+      s = undefined
+      w :: StoreT s w a -> w a
+      w = undefined
+
+instance (Typeable s, Typeable1 w, Typeable a) => Typeable (StoreT s w a) where
+  typeOf = typeOfDefault
+
+storeTTyCon :: TyCon
+#if __GLASGOW_HASKELL__ < 704
+storeTTyCon = mkTyCon "Control.Comonad.Trans.Store.StoreT"
+#else
+storeTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Store" "StoreT"
+#endif
+{-# NOINLINE storeTTyCon #-}
+#endif
+
+type Store s = StoreT s Identity
+
+store :: (s -> a) -> s -> Store s a
+store f s = StoreT (Identity f) s
+
+runStore :: Store s a -> (s -> a, s)
+runStore (StoreT (Identity f) s) = (f, s)
+
+data StoreT s w a = StoreT (w (s -> a)) s
+
+runStoreT :: StoreT s w a -> (w (s -> a), s)
+runStoreT (StoreT wf s) = (wf, s)
+
+experiment :: (Comonad w, Functor f) => (s -> f s) -> StoreT s w a -> f a
+experiment f (StoreT wf s) = extract wf <$> f s
+
+instance Functor w => Functor (StoreT s w) where
+  fmap f (StoreT wf s) = StoreT (fmap (f .) wf) s
+
+instance (Apply w, Semigroup s) => Apply (StoreT s w) where
+  StoreT ff m <.> StoreT fa n = StoreT ((<*>) <$> ff <.> fa) (m <> n)
+
+instance (ComonadApply w, Semigroup s) => ComonadApply (StoreT s w) where
+  StoreT ff m <@> StoreT fa n = StoreT ((<*>) <$> ff <@> fa) (m <> n)
+
+instance (Applicative w, Monoid s) => Applicative (StoreT s w) where
+  pure a = StoreT (pure (const a)) mempty
+  StoreT ff m <*> StoreT fa n = StoreT ((<*>) <$> ff <*> fa) (mappend m n)
+
+instance Extend w => Extend (StoreT s w) where
+  duplicated (StoreT wf s) = StoreT (extended StoreT wf) s
+  extended f (StoreT wf s) = StoreT (extended (\wf' s' -> f (StoreT wf' s')) wf) s
+
+instance Comonad w => Comonad (StoreT s w) where
+  duplicate (StoreT wf s) = StoreT (extend StoreT wf) s
+  extend f (StoreT wf s) = StoreT (extend (\wf' s' -> f (StoreT wf' s')) wf) s
+  extract (StoreT wf s) = extract wf s
+
+instance ComonadTrans (StoreT s) where
+  lower (StoreT f s) = fmap ($s) f
+
+instance ComonadHoist (StoreT s) where
+  cohoist (StoreT f s) = StoreT (Identity (extract f)) s
+
+-- | Read the current position
+pos :: StoreT s w a -> s
+pos (StoreT _ s) = s
+
+-- | Seek to an absolute location
+--
+-- > seek s = peek s . duplicate
+seek :: Comonad w => s -> StoreT s w a -> StoreT s w a
+seek s ~(StoreT f _) = StoreT f s
+
+-- | Seek to a relative location
+--
+-- > seeks f = peeks f . duplicate
+seeks :: Comonad w => (s -> s) -> StoreT s w a -> StoreT s w a
+seeks f ~(StoreT g s) = StoreT g (f s)
+
+-- | Peek at a value at a given absolute location
+--
+-- > peek x . extend (peek y) = peek y
+peek :: Comonad w => s -> StoreT s w a -> a
+peek s (StoreT g _) = extract g s
+
+-- | Peek at a value at a given relative location
+peeks :: Comonad w => (s -> s) -> StoreT s w a -> a
+peeks f ~(StoreT g s) = extract g (f s)
+
diff --git a/src/Control/Comonad/Trans/Traced.hs b/src/Control/Comonad/Trans/Traced.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Trans/Traced.hs
@@ -0,0 +1,111 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Traced
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- The trace comonad transformer (aka the cowriter or exponential comonad transformer).
+--
+----------------------------------------------------------------------------
+module Control.Comonad.Trans.Traced
+  (
+  -- * Traced comonad
+    Traced
+  , traced
+  , runTraced
+  -- * Traced comonad transformer
+  , TracedT(..)
+  -- * Operations
+  , trace
+  , listen
+  , listens
+  , censor
+  ) where
+
+import Control.Applicative
+import Control.Monad.Instances ()
+import Control.Monad (ap)
+import Control.Comonad
+import Control.Comonad.Hoist.Class
+import Control.Comonad.Trans.Class
+import Data.Distributive
+import Data.Functor.Apply
+import Data.Functor.Extend
+import Data.Functor.Identity
+import Data.Semigroup
+import Data.Typeable
+
+type Traced m = TracedT m Identity
+
+traced :: (m -> a) -> Traced m a
+traced f = TracedT (Identity f)
+
+runTraced :: Traced m a -> m -> a
+runTraced (TracedT (Identity f)) = f
+
+newtype TracedT m w a = TracedT { runTracedT :: w (m -> a) }
+
+instance Functor w => Functor (TracedT m w) where
+  fmap g = TracedT . fmap (g .) . runTracedT
+
+instance Apply w => Apply (TracedT m w) where
+  TracedT wf <.> TracedT wa = TracedT (ap <$> wf <.> wa)
+
+instance (ComonadApply w, Monoid m) => ComonadApply (TracedT m w) where
+  TracedT wf <@> TracedT wa = TracedT (ap <$> wf <@> wa)
+
+instance Applicative w => Applicative (TracedT m w) where
+  pure = TracedT . pure . const
+  TracedT wf <*> TracedT wa = TracedT (ap <$> wf <*> wa)
+
+instance (Extend w, Semigroup m) => Extend (TracedT m w) where
+  extended f = TracedT . extended (\wf m -> f (TracedT (fmap (. (<>) m) wf))) . runTracedT
+
+instance (Comonad w, Monoid m) => Comonad (TracedT m w) where
+  extend f = TracedT . extend (\wf m -> f (TracedT (fmap (. mappend m) wf))) . runTracedT
+  extract (TracedT wf) = extract wf mempty
+
+instance Monoid m => ComonadTrans (TracedT m) where
+  lower = fmap ($mempty) . runTracedT
+
+instance Monoid m => ComonadHoist (TracedT m) where
+  cohoist = traced . extract . runTracedT
+
+instance Distributive w => Distributive (TracedT m w) where
+  distribute = TracedT . fmap (\tma m -> fmap ($m) tma) . collect runTracedT
+
+trace :: Comonad w => m -> TracedT m w a -> a
+trace m (TracedT wf) = extract wf m
+
+listen :: Functor w => TracedT m w a -> TracedT m w (a, m)
+listen = TracedT . fmap (\f m -> (f m, m)) . runTracedT
+
+listens :: Functor w => (m -> b) -> TracedT m w a -> TracedT m w (a, b)
+listens g = TracedT . fmap (\f m -> (f m, g m)) . runTracedT
+
+censor :: Functor w => (m -> m) -> TracedT m w a -> TracedT m w a
+censor g = TracedT . fmap (. g) . runTracedT
+
+#ifdef __GLASGOW_HASKELL__
+
+instance (Typeable s, Typeable1 w) => Typeable1 (TracedT s w) where
+  typeOf1 dswa = mkTyConApp tracedTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
+    where
+      s :: TracedT s w a -> s
+      s = undefined
+      w :: TracedT s w a -> w a
+      w = undefined
+
+tracedTTyCon :: TyCon
+#if __GLASGOW_HASKELL__ < 704
+tracedTTyCon = mkTyCon "Control.Comonad.Trans.Traced.TracedT"
+#else
+tracedTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Traced" "TracedT"
+#endif
+{-# NOINLINE tracedTTyCon #-}
+
+#endif
diff --git a/src/Data/Functor/Composition.hs b/src/Data/Functor/Composition.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Functor/Composition.hs
@@ -0,0 +1,14 @@
+module Data.Functor.Composition
+  ( Composition(..) ) where
+
+import Data.Functor.Compose
+
+-- | We often need to distinguish between various forms of Functor-like composition in Haskell in order to please the type system.
+-- This lets us work with these representations uniformly.
+class Composition o where
+  decompose :: o f g x -> f (g x)
+  compose :: f (g x) -> o f g x
+
+instance Composition Compose where
+  decompose = getCompose
+  compose = Compose
diff --git a/src/Data/Functor/Coproduct.hs b/src/Data/Functor/Coproduct.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Functor/Coproduct.hs
@@ -0,0 +1,68 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Functor.Coproduct
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+----------------------------------------------------------------------------
+module Data.Functor.Coproduct
+  ( Coproduct(..)
+  , left
+  , right
+  , coproduct
+  ) where
+
+import Control.Comonad
+import Data.Functor.Contravariant
+import Data.Functor.Extend
+import Data.Foldable
+import Data.Traversable
+import Data.Semigroup.Foldable
+import Data.Semigroup.Traversable
+
+newtype Coproduct f g a = Coproduct { getCoproduct :: Either (f a) (g a) }
+
+left :: f a -> Coproduct f g a
+left = Coproduct . Left
+
+right :: g a -> Coproduct f g a
+right = Coproduct . Right
+
+coproduct :: (f a -> b) -> (g a -> b) -> Coproduct f g a -> b
+coproduct f g = either f g . getCoproduct
+
+instance (Functor f, Functor g) => Functor (Coproduct f g) where
+  fmap f = Coproduct . coproduct (Left . fmap f) (Right . fmap f)
+
+instance (Foldable f, Foldable g) => Foldable (Coproduct f g) where
+  foldMap f = coproduct (foldMap f) (foldMap f)
+
+instance (Foldable1 f, Foldable1 g) => Foldable1 (Coproduct f g) where
+  foldMap1 f = coproduct (foldMap1 f) (foldMap1 f)
+
+instance (Traversable f, Traversable g) => Traversable (Coproduct f g) where
+  traverse f = coproduct
+    (fmap (Coproduct . Left) . traverse f)
+    (fmap (Coproduct . Right) . traverse f)
+
+instance (Traversable1 f, Traversable1 g) => Traversable1 (Coproduct f g) where
+  traverse1 f = coproduct
+    (fmap (Coproduct . Left) . traverse1 f)
+    (fmap (Coproduct . Right) . traverse1 f)
+
+instance (Extend f, Extend g) => Extend (Coproduct f g) where
+  extended f = Coproduct . coproduct
+    (Left . extended (f . Coproduct . Left))
+    (Right . extended (f . Coproduct . Right))
+
+instance (Comonad f, Comonad g) => Comonad (Coproduct f g) where
+  extend f = Coproduct . coproduct
+    (Left . extend (f . Coproduct . Left))
+    (Right . extend (f . Coproduct . Right))
+  extract = coproduct extract extract
+
+instance (Contravariant f, Contravariant g) => Contravariant (Coproduct f g) where
+  contramap f = Coproduct . coproduct (Left . contramap f) (Right . contramap f)
