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/.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.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,7 @@
+4.0
+---
+* Merged the contents of `comonad-transformers` and `comonads-fd` into this package.
+
 3.1
 ---
 * Added `instance Comonad (Tagged s)`.
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -14,10 +14,6 @@
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
 
-3. Neither the name of the author nor the names of his contributors
-   may be used to endorse or promote products derived from this software
-   without specific prior written permission.
-
 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
diff --git a/comonad.cabal b/comonad.cabal
--- a/comonad.cabal
+++ b/comonad.cabal
@@ -1,6 +1,6 @@
 name:          comonad
 category:      Control, Comonads
-version:       3.1
+version:       4.0
 license:       BSD3
 cabal-version: >= 1.10
 license-file:  LICENSE
@@ -11,12 +11,15 @@
 bug-reports:   http://github.com/ekmett/comonad/issues
 copyright:     Copyright (C) 2008-2013 Edward A. Kmett,
                Copyright (C) 2004-2008 Dave Menendez
-synopsis:      Haskell 98 compatible comonads
-description:   Haskell 98 compatible comonads
+synopsis:      Comonads
+description:   Comonads
 build-type:    Custom
 extra-source-files:
+  .ghci
   .gitignore
   .travis.yml
+  .vim.custom
+  coq/Store.v
   README.markdown
   CHANGELOG.markdown
   examples/History.hs
@@ -34,18 +37,43 @@
   hs-source-dirs: src
   default-language: Haskell2010
   other-extensions: CPP
+  ghc-options: -Wall
 
   build-depends:
-    base         >= 4       && < 5,
-    transformers >= 0.2     && < 0.4,
-    containers   >= 0.3     && < 0.6,
-    semigroups   >= 0.8.3   && < 1,
-    tagged       >= 0.1     && < 1
+    base          >= 4       && < 5,
+    containers    >= 0.3     && < 0.6,
+    contravariant >= 0.2.0.1 && < 1,
+    distributive  >= 0.2.2   && < 1,
+    mtl           >= 2.0     && < 2.2,
+    semigroups    >= 0.8.3.1 && < 1,
+    tagged        >= 0.1     && < 1,
+    transformers  >= 0.2     && < 0.4
 
   exposed-modules:
     Control.Comonad
+    Control.Comonad.Env
+    Control.Comonad.Env.Class
+    Control.Comonad.Hoist.Class
+    Control.Comonad.Identity
+    Control.Comonad.Store
+    Control.Comonad.Store.Class
+    Control.Comonad.Traced
+    Control.Comonad.Traced.Class
+    Control.Comonad.Trans.Class
+    Control.Comonad.Trans.Env
+    Control.Comonad.Trans.Identity
+    Control.Comonad.Trans.Store
+    Control.Comonad.Trans.Traced
+    Data.Functor.Composition
+    Data.Functor.Coproduct
 
-  ghc-options: -Wall
+  default-extensions: CPP
+  other-extensions:
+    RankNTypes
+    MultiParamTypeClasses
+    FunctionalDependencies
+    FlexibleInstances
+    UndecidableInstances
 
 test-suite doctests
   type:           exitcode-stdio-1.0
@@ -65,4 +93,3 @@
 
   if impl(ghc<7.6.1)
     ghc-options: -Werror
-
diff --git a/coq/Store.v b/coq/Store.v
new file mode 100644
--- /dev/null
+++ b/coq/Store.v
@@ -0,0 +1,96 @@
+(* Proof StoreT forms a comonad -- Russell O'Connor *)
+
+Set Implict Arguments.
+Unset Strict Implicit.
+
+Require Import FunctionalExtensionality.
+
+Record Comonad (w : Type -> Type) : Type :=
+ { extract : forall a, w a -> a
+ ; extend : forall a b, (w a -> b) -> w a -> w b
+ ; law1 : forall a x, extend _ _ (extract a) x = x
+ ; law2 : forall a b f x, extract b (extend a _ f x) = f x
+ ; law3 : forall a b c f g x, extend b c f (extend a b g x) = extend a c (fun y => f (extend a b g y)) x
+ }.
+
+Section StoreT.
+
+Variables (s : Type) (w:Type -> Type).
+Hypothesis wH : Comonad w.
+
+Definition map a b f x := extend _ wH a b (fun y => f (extract _ wH _ y)) x.
+
+Lemma map_extend : forall a b c f g x, map b c f (extend _ wH a b g x) = extend _ wH _ _ (fun y => f (g y)) x.
+Proof.
+intros a b c f g x.
+unfold map.
+rewrite law3.
+apply equal_f.
+apply f_equal.
+extensionality y.
+rewrite law2.
+reflexivity.
+Qed.
+
+Record StoreT (a:Type): Type := mkStoreT
+  {store : w (s -> a)
+  ;loc   : s}.
+
+Definition extractST a (x:StoreT a) : a := 
+ extract _ wH _ (store _ x) (loc _ x).
+
+Definition mapST a b (f:a -> b) (x:StoreT a) : StoreT b :=
+ mkStoreT _ (map _ _ (fun g x => f (g x)) (store _ x)) (loc _ x).
+
+Definition duplicateST a (x:StoreT a) : StoreT (StoreT a) :=
+ mkStoreT _ (extend _ wH _ _ (mkStoreT _) (store _ x)) (loc _ x).
+
+Let extendST := fun a b f x => mapST _ b f (duplicateST a x).
+
+Lemma law1ST : forall a x, extendST _ _ (extractST a) x = x.
+Proof.
+intros a [v b].
+unfold extractST, extendST, duplicateST, mapST.
+simpl.
+rewrite map_extend.
+simpl.
+replace (fun (y : w (s -> a)) (x : s) => extract w wH (s -> a) y x)
+ with (extract w wH (s -> a)).
+ rewrite law1.
+ reflexivity.
+extensionality y.
+extensionality x.
+reflexivity.
+Qed.
+
+Lemma law2ST : forall a b f x, extractST b (extendST a _ f x) = f x.
+Proof.
+intros a b f [v c].
+unfold extendST, mapST, extractST.
+simpl.
+rewrite map_extend.
+rewrite law2.
+reflexivity.
+Qed.
+
+Lemma law3ST : forall a b c f g x, extendST b c f (extendST a b g x) = extendST a c (fun y => f (extendST a b g y)) x.
+Proof.
+intros a b c f g [v d].
+unfold extendST, mapST, extractST.
+simpl.
+repeat rewrite map_extend.
+rewrite law3.
+repeat (apply equal_f||apply f_equal).
+extensionality y.
+extensionality x.
+rewrite map_extend.
+reflexivity.
+Qed.
+
+Definition StoreTComonad : Comonad StoreT :=
+ Build_Comonad _ _ _ law1ST law2ST law3ST.
+
+End StoreT.
+
+Check StoreTComonad.
+
diff --git a/src/Control/Comonad/Env.hs b/src/Control/Comonad/Env.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Env.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Env
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+--
+-- The Env comonad (aka the Coreader, Environment, or Product comonad)
+--
+-- A co-Kleisli arrow in the Env comonad is isomorphic to a Kleisli arrow
+-- in the reader monad.
+--
+-- (a -> e -> m) ~ (a, e) -> m ~ Env e a -> m
+----------------------------------------------------------------------------
+module Control.Comonad.Env (
+  -- * ComonadEnv class
+    ComonadEnv(..)
+  , asks
+  , local
+  -- * The Env comonad
+  , Env
+  , env
+  , runEnv
+  -- * The EnvT comonad transformer
+  , EnvT(..)
+  , runEnvT
+  -- * Re-exported modules
+  , module Control.Comonad
+  , module Control.Comonad.Trans.Class
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Env.Class (ComonadEnv(..), asks)
+import Control.Comonad.Trans.Class
+import Control.Comonad.Trans.Env (Env, env, runEnv, EnvT(..), runEnvT, local)
diff --git a/src/Control/Comonad/Env/Class.hs b/src/Control/Comonad/Env/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Env/Class.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Env.Class
+-- Copyright   :  (C) 2008-2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Comonad.Env.Class
+  ( ComonadEnv(..)
+  , asks
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Trans.Class
+import qualified Control.Comonad.Trans.Env as Env
+import Control.Comonad.Trans.Store
+import Control.Comonad.Trans.Traced
+import Control.Comonad.Trans.Identity
+import Data.Semigroup
+
+class Comonad w => ComonadEnv e w | w -> e where
+  ask :: w a -> e
+
+asks :: ComonadEnv e w => (e -> e') -> w a -> e'
+asks f wa = f (ask wa)
+{-# INLINE asks #-}
+
+instance Comonad w => ComonadEnv e (Env.EnvT e w) where
+  ask = Env.ask
+
+instance ComonadEnv e ((,)e) where
+  ask = fst
+
+lowerAsk :: (ComonadEnv e w, ComonadTrans t) => t w a -> e
+lowerAsk = ask . lower
+{-# INLINE lowerAsk #-}
+
+instance ComonadEnv e w => ComonadEnv e (StoreT t w) where
+  ask = lowerAsk
+
+instance ComonadEnv e w => ComonadEnv e (IdentityT w) where
+  ask = lowerAsk
+
+instance (ComonadEnv e w, Monoid m) => ComonadEnv e (TracedT m w) where
+  ask = lowerAsk
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,26 @@
+{-# LANGUAGE RankNTypes #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Hoist.Class
+-- Copyright   :  (C) 2008-2013 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(cohoist)
+  ) where
+
+import Control.Comonad
+import Control.Monad.Trans.Identity
+
+class ComonadHoist t where
+  -- | Given any comonad-homomorphism from @w@ to @v@ this yields a comonad
+  -- homomorphism from @t w@ to @t v@.
+  cohoist :: (Comonad w, Comonad v) => (forall x. w x -> v x) -> t w a -> t v a
+
+instance ComonadHoist IdentityT where
+  cohoist l = IdentityT . l . runIdentityT
+  {-# INLINE cohoist #-}
diff --git a/src/Control/Comonad/Identity.hs b/src/Control/Comonad/Identity.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Identity.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Identity
+-- Copyright   :  (C) 2008-2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Comonad.Identity (
+    module Control.Comonad
+  , module Data.Functor.Identity
+  , module Control.Comonad.Trans.Identity
+  ) where
+
+import Control.Comonad
+import Data.Functor.Identity
+import Control.Comonad.Trans.Identity
diff --git a/src/Control/Comonad/Store.hs b/src/Control/Comonad/Store.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Store.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Store
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Comonad.Store (
+  -- * ComonadStore class
+    ComonadStore(..)
+  -- * The Store comonad
+  , Store
+  , store
+  , runStore
+  -- * The StoreT comonad transformer
+  , StoreT(..)
+  , runStoreT
+  -- * Re-exported modules
+  , module Control.Comonad
+  , module Control.Comonad.Trans.Class
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Store.Class (ComonadStore(..))
+import Control.Comonad.Trans.Class
+import Control.Comonad.Trans.Store (Store, store, runStore, StoreT(..), runStoreT)
diff --git a/src/Control/Comonad/Store/Class.hs b/src/Control/Comonad/Store/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Store/Class.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Store.Class
+-- Copyright   :  (C) 2008-2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Comonad.Store.Class
+  ( ComonadStore(..)
+  , lowerPos
+  , lowerPeek
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Trans.Class
+import Control.Comonad.Trans.Env
+import qualified Control.Comonad.Trans.Store as Store
+import Control.Comonad.Trans.Traced
+import Control.Comonad.Trans.Identity
+import Data.Semigroup
+
+class Comonad w => ComonadStore s w | w -> s where
+  pos :: w a -> s
+  peek :: s -> w a -> a
+
+  peeks :: (s -> s) -> w a -> a
+  peeks f w = peek (f (pos w)) w
+
+  seek :: s -> w a -> w a
+  seek s = peek s . duplicate
+
+  seeks :: (s -> s) -> w a -> w a
+  seeks f = peeks f . duplicate
+
+  experiment :: Functor f => (s -> f s) -> w a -> f a
+  experiment f w = fmap (`peek` w) (f (pos w))
+
+instance Comonad w => ComonadStore s (Store.StoreT s w) where
+  pos = Store.pos
+  peek = Store.peek
+  peeks = Store.peeks
+  seek = Store.seek
+  seeks = Store.seeks
+  experiment = Store.experiment
+
+lowerPos :: (ComonadTrans t, ComonadStore s w) => t w a -> s
+lowerPos = pos . lower
+{-# INLINE lowerPos #-}
+
+lowerPeek :: (ComonadTrans t, ComonadStore s w) => s -> t w a -> a
+lowerPeek s = peek s . lower
+{-# INLINE lowerPeek #-}
+
+lowerExperiment :: (ComonadTrans t, ComonadStore s w, Functor f) => (s -> f s) -> t w a -> f a
+lowerExperiment f = experiment f . lower
+{-# INLINE lowerExperiment #-}
+
+instance ComonadStore s w => ComonadStore s (IdentityT w) where
+  pos = lowerPos
+  peek = lowerPeek
+  experiment = lowerExperiment
+
+instance ComonadStore s w => ComonadStore s (EnvT e w) where
+  pos = lowerPos
+  peek = lowerPeek
+  experiment = lowerExperiment
+
+instance (ComonadStore s w, Monoid m) => ComonadStore s (TracedT m w) where
+  pos = lowerPos
+  peek = lowerPeek
+  experiment = lowerExperiment
diff --git a/src/Control/Comonad/Traced.hs b/src/Control/Comonad/Traced.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Traced.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Traced
+-- Copyright   :  (C) 2008-2011 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Comonad.Traced (
+  -- * ComonadTraced class
+    ComonadTraced(..)
+  , traces
+  -- * The Traced comonad
+  , Traced
+  , traced
+  , runTraced
+  -- * The TracedT comonad transformer
+  , TracedT(..)
+  -- * Re-exported modules
+  , module Control.Comonad
+  , module Control.Comonad.Trans.Class
+  , module Data.Monoid
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Traced.Class (ComonadTraced(..), traces)
+import Control.Comonad.Trans.Class
+import Control.Comonad.Trans.Traced (Traced, traced, runTraced, TracedT(..), runTracedT)
+import Data.Monoid
diff --git a/src/Control/Comonad/Traced/Class.hs b/src/Control/Comonad/Traced/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Comonad/Traced/Class.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Traced.Class
+-- Copyright   :  (C) 2008-2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable (fundeps, MPTCs)
+----------------------------------------------------------------------------
+module Control.Comonad.Traced.Class
+  ( ComonadTraced(..)
+  , traces
+  ) where
+
+import Control.Comonad
+import Control.Comonad.Trans.Class
+import Control.Comonad.Trans.Env
+import Control.Comonad.Trans.Store
+import qualified Control.Comonad.Trans.Traced as Traced
+import Control.Comonad.Trans.Identity
+import Data.Semigroup
+
+class Comonad w => ComonadTraced m w | w -> m where
+  trace :: m -> w a -> a
+
+traces :: ComonadTraced m w => (a -> m) -> w a -> a
+traces f wa = trace (f (extract wa)) wa
+{-# INLINE traces #-}
+
+instance (Comonad w, Monoid m) => ComonadTraced m (Traced.TracedT m w) where
+  trace = Traced.trace
+
+lowerTrace :: (ComonadTrans t, ComonadTraced m w) => m -> t w a -> a
+lowerTrace m = trace m . lower
+{-# INLINE lowerTrace #-}
+
+-- All of these require UndecidableInstances because they do not satisfy the coverage condition
+
+instance ComonadTraced m w => ComonadTraced m (IdentityT w) where
+  trace = lowerTrace
+
+instance ComonadTraced m w => ComonadTraced m (EnvT e w) where
+  trace = lowerTrace
+
+instance ComonadTraced m w => ComonadTraced m (StoreT s w) where
+  trace = lowerTrace
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,26 @@
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- 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,177 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+#if __GLASGOW_HASKELL__ >= 707
+{-# LANGUAGE StandaloneDeriving, DeriveDataTypeable #-}
+#endif
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Env
+-- Copyright   :  (C) 2008-2013 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- The environment comonad holds a value along with some retrievable context.
+--
+-- This module specifies the environment comonad transformer (aka coreader),
+-- which is left adjoint to the reader comonad.
+--
+-- The following sets up an experiment that retains its initial value in the
+-- background:
+--
+-- >>> let initial = env 0 0
+--
+-- Extract simply retrieves the value:
+--
+-- >>> extract initial
+-- 0
+--
+-- Play around with the value, in our case producing a negative value:
+--
+-- >>> let experiment = fmap (+ 10) initial
+-- >>> extract experiment
+-- 10
+--
+-- Oh noes, something went wrong, 10 isn't very negative! Better restore the
+-- initial value using the default:
+--
+-- >>> let initialRestored = experiment =>> ask
+-- >>> extract initialRestored
+-- 0
+----------------------------------------------------------------------------
+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.Identity
+import Data.Semigroup
+
+#ifdef __GLASGOW_HASKELL__
+#if __GLASGOW_HASKELL__ >= 707
+#define Typeable1 Typeable
+#endif
+import Data.Data
+
+#if __GLASGOW_HASKELL__ >= 707
+deriving instance Typeable EnvT
+#else
+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
+#endif
+
+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 #-}
+
+#if __GLASGOW_HASKELL__ < 707
+instance (Typeable s, Typeable1 w, Typeable a) => Typeable (EnvT s w a) where
+  typeOf = typeOfDefault
+#endif
+
+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)
+
+-- | Create an Env using an environment and a value
+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 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
+
+-- | Gets rid of the environment. This differs from 'extract' in that it will
+--   not continue extracting the value from the contained comonad.
+lowerEnvT :: EnvT e w a -> w a
+lowerEnvT (EnvT _ wa) = wa
+
+instance ComonadHoist (EnvT e) where
+  cohoist l (EnvT e wa) = EnvT e (l 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
+
+-- | Retrieves the environment.
+ask :: EnvT e w a -> e
+ask (EnvT e _) = e
+
+-- | Like 'ask', but modifies the resulting value with a function.
+--
+--   > asks = f . ask
+asks :: (e -> f) -> EnvT e w a -> f
+asks f (EnvT e _) = f e
+
+-- | Modifies the environment using the specified function.
+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,193 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 707
+{-# LANGUAGE StandaloneDeriving, DeriveDataTypeable #-}
+#endif
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Store
+-- Copyright   :  (C) 2008-2013 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+--
+-- The store comonad holds a constant value along with a modifiable /accessor/
+-- function, which maps the /stored value/ to the /focus/.
+--
+-- This module defines the strict store (aka state-in-context/costate) comonad
+-- transformer.
+--
+-- @stored value = (1, 5)@, @accessor = fst@, @resulting focus = 1@:
+--
+-- > storeTuple :: Store (Int, Int) Int
+-- > storeTuple = store fst (1, 5)
+--
+-- Add something to the focus:
+--
+-- > addToFocus :: Int -> Store (Int, Int) Int -> Int
+-- > addToFocus x wa = x + extract wa
+-- >
+-- > added3 :: Store (Int, Int) Int
+-- > added3 = extend (addToFocus 3) storeTuple
+--
+-- The focus of added3 is now @1 + 3 = 4@. However, this action changed only
+-- the accessor function and therefore the focus but not the stored value:
+--
+-- > pos added3
+-- (1, 5)
+--
+-- > extract added3
+-- 4
+--
+-- 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.Semigroup
+
+#ifdef __GLASGOW_HASKELL__
+import Data.Typeable
+
+#if __GLASGOW_HASKELL__ >= 707
+deriving instance Typeable StoreT
+#else
+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
+
+#endif
+
+type Store s = StoreT s Identity
+
+-- | Create a Store using an accessor function and a stored value
+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)
+
+instance Functor w => Functor (StoreT s w) where
+  fmap f (StoreT wf s) = StoreT (fmap (f .) wf) s
+
+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 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 l (StoreT f s) = StoreT (l f) s
+
+-- | Read the stored value
+--
+-- >>> pos $ store fst (1,5)
+-- (1,5)
+--
+pos :: StoreT s w a -> s
+pos (StoreT _ s) = s
+
+-- | Set the stored value
+--
+-- > pos . seek (3,7) $ store fst (1,5)
+-- > (3,7)
+--
+-- Seek satisfies the law
+--
+-- > seek s = peek s . duplicate
+seek :: s -> StoreT s w a -> StoreT s w a
+seek s ~(StoreT f _) = StoreT f s
+
+-- | Modify the stored value
+--
+-- > pos . seeks swap $ store fst (1,5)
+-- (5,1)
+--
+-- Seeks satisfies the law
+--
+-- > seeks f = peeks f . duplicate
+seeks :: (s -> s) -> StoreT s w a -> StoreT s w a
+seeks f ~(StoreT g s) = StoreT g (f s)
+
+-- | Peek at what the current focus would be for a different stored value
+--
+-- Peek satisfies the law
+--
+-- > 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 what the current focus would be if the stored value was
+--   modified by some function
+peeks :: Comonad w => (s -> s) -> StoreT s w a -> a
+peeks f ~(StoreT g s) = extract g (f s)
+
+-- | Applies a functor-valued function to the stored value, and then uses the
+--   new accessor to read the resulting focus.
+--
+--   >>> let f x = if x > 0 then Just (x^2) else Nothing
+--   >>> experiment f $ store (+1) 2
+--   Just 5
+--   >>> experiment f $ store (+1) (-2)
+--   Nothing
+experiment :: (Comonad w, Functor f) => (s -> f s) -> StoreT s w a -> f a
+experiment f (StoreT wf s) = extract wf <$> 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,119 @@
+{-# LANGUAGE CPP #-}
+#if __GLASGOW_HASKELL__ >= 707
+{-# LANGUAGE StandaloneDeriving, DeriveDataTypeable #-}
+#endif
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Comonad.Trans.Traced
+-- Copyright   :  (C) 2008-2013 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+--
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- The trace comonad builds up a result by prepending monoidal values to each
+-- other.
+--
+-- This module specifies the traced 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.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 (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 (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 l = TracedT . l . 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__
+
+#if __GLASGOW_HASKELL__ >= 707
+deriving instance Typeable TracedT
+#else
+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
+
+#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,57 @@
+{-# LANGUAGE CPP #-}
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Trustworthy #-}
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- 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.Foldable
+import Data.Traversable
+
+newtype Coproduct f g a = Coproduct { getCoproduct :: Either (f a) (g a) }
+  deriving (Eq, Ord, Read, Show)
+
+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 (Traversable f, Traversable g) => Traversable (Coproduct f g) where
+  traverse f = coproduct
+    (fmap (Coproduct . Left) . traverse f)
+    (fmap (Coproduct . Right) . traverse f)
+
+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)
