diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,14 @@
+2.4
+-----
+* Added the indexed `Kleene` store to `Control.Lens.Internal`
+* Moved `Gettable`, `Accessor`, `Settable` and `Mutator` to `Control.Lens.Internal`
+* Added `cloneTraversal` to `Control.Lens.Traversal`
+* Renamed `clone` to `cloneLens` in `Control.Lens.Type`
+* Generalized the type of `zoom` to subsume `focus`.
+* Removed `Focus(..)` from `Control.Lens.Type`.
+* Factored out `Control.Lens.Isomorphic`.
+* Moved many private types to `Control.Lens.Internal`
+
 2.3
 ---
 * Added missing `{-# INLINE #-}` pragmas
diff --git a/lens.cabal b/lens.cabal
--- a/lens.cabal
+++ b/lens.cabal
@@ -1,6 +1,6 @@
 name:          lens
 category:      Data, Lenses
-version:       2.3
+version:       2.4
 license:       BSD3
 cabal-version: >= 1.8
 license-file:  LICENSE
@@ -33,7 +33,7 @@
   .
   The core of this hierarchy looks like:
   .
-  <<https://github.com/ekmett/lens/wiki/images/Hierarchy-2.3.png>>
+  <<https://github.com/ekmett/lens/wiki/images/Hierarchy-2.4.png>>
   .
   You can compose any two elements of the hierarchy above using (.) from the Prelude, and you can
   use any element of the hierarchy as any type it links to above it.
@@ -100,7 +100,7 @@
     base             >= 4.3   && < 5,
     containers       >= 0.4.2 && < 0.6,
     mtl              >= 2.1.1 && < 2.2,
-    template-haskell >= 2.4   && < 2.8,
+    template-haskell >= 2.4   && < 2.9,
     transformers     >= 0.3   && < 0.4
 
   exposed-modules: Control.Exception.Lens
@@ -116,11 +116,14 @@
                    Control.Lens.IndexedTraversal
                    Control.Lens.Internal
                    Control.Lens.Iso
+                   Control.Lens.Isomorphic
                    Control.Lens.Representable
                    Control.Lens.Setter
                    Control.Lens.TH
                    Control.Lens.Traversal
+                   Control.Lens.Tuple
                    Control.Lens.Type
+                   Control.Lens.Zoom
                    Data.Bits.Lens
                    Data.Complex.Lens
                    Data.Dynamic.Lens
@@ -140,7 +143,10 @@
   build-depends:   array >= 0.3.0.2 && < 0.5
   exposed-modules: Data.Array.Lens
 
-  build-depends:   bytestring >= 0.9.1.10 && < 0.10
+  build-depends:   filepath >= 1.2.0.0 && < 1.4
+  exposed-modules: System.FilePath.Lens
+
+  build-depends:   bytestring >= 0.9.1.10 && < 0.11
   exposed-modules: Data.ByteString.Lens Data.ByteString.Lazy.Lens
 
   build-depends:   text >= 0.11.1.5 && < 0.12
diff --git a/src/Control/Lens.hs b/src/Control/Lens.hs
--- a/src/Control/Lens.hs
+++ b/src/Control/Lens.hs
@@ -41,7 +41,7 @@
 --
 -- <http://github.com/ekmett/lens/wiki>
 --
--- <<http://github.com/ekmett/lens/wiki/images/Hierarchy-2.3.png>>
+-- <<http://github.com/ekmett/lens/wiki/images/Hierarchy-2.4.png>>
 ----------------------------------------------------------------------------
 module Control.Lens
   ( module Control.Lens.Type
@@ -59,6 +59,8 @@
   , module Control.Lens.IndexedSetter
   , module Control.Lens.Representable
   , module Control.Lens.TH
+  , module Control.Lens.Tuple
+  , module Control.Lens.Zoom
   ) where
 
 import Control.Lens.Type
@@ -76,3 +78,5 @@
 import Control.Lens.IndexedSetter
 import Control.Lens.Representable
 import Control.Lens.TH
+import Control.Lens.Zoom
+import Control.Lens.Tuple
diff --git a/src/Control/Lens/Action.hs b/src/Control/Lens/Action.hs
--- a/src/Control/Lens/Action.hs
+++ b/src/Control/Lens/Action.hs
@@ -1,8 +1,5 @@
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE UndecidableInstances #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Lens.Action
@@ -28,19 +25,11 @@
 
   -- * Implementation Details
   , Acting
-  , Effective(..)
-  , ineffective
-  , Effect(..)
   ) where
 
 import Control.Applicative
-import Control.Applicative.Backwards
-import Control.Lens.Getter
-import Control.Lens.Iso
-import Control.Monad
+import Control.Lens.Internal
 import Control.Monad.Trans.Class
-import Data.Functor.Identity
-import Data.Monoid
 
 infixr 8 ^!
 
@@ -58,48 +47,6 @@
 -- You can compose a 'MonadicFold' with another 'MonadicFold' using ('Prelude..') from the @Prelude@.
 type MonadicFold m a c = forall f r. (Effective m r f, Applicative f) => (c -> f c) -> a -> f a
 
--- | An 'Effective' 'Functor' ignores its argument and is isomorphic to a monad wrapped around a value.
---
--- That said, the monad is possibly rather unrelated to any 'Applicative' structure.
-class (Monad m, Gettable f) => Effective m r f | f -> m r where
-  effective :: Isomorphic k => k (m r) (f a)
-
--- | A convenient antonym that is used internally.
-ineffective :: Effective m r f => Isomorphic k => k (f a) (m r)
-ineffective = from effective
-{-# INLINE ineffective #-}
-
-instance Effective Identity r (Accessor r) where
-  effective = isomorphic (Accessor . runIdentity) (Identity . runAccessor)
-  {-# INLINE effective #-}
-  {-# SPECIALIZE effective :: Identity r -> Accessor r a #-}
-  {-# SPECIALIZE effective :: Isomorphism (Identity r) (Accessor r a) #-}
-
-instance Effective m r f => Effective m (Dual r) (Backwards f) where
-  effective = isomorphic (Backwards . effective . liftM getDual) (liftM Dual . ineffective . forwards)
-
--- | Wrap a monadic effect with a phantom type argument.
-newtype Effect m r a = Effect { getEffect :: m r }
-
-instance Monad m => Functor (Effect m r) where
-  fmap _ (Effect m) = Effect m
-
-instance (Monad m, Monoid r) => Monoid (Effect m r a) where
-  mempty = Effect (return mempty)
-  Effect ma `mappend` Effect mb = Effect (liftM2 mappend ma mb)
-
-instance (Monad m, Monoid r) => Applicative (Effect m r) where
-  pure _ = Effect (return mempty)
-  Effect ma <*> Effect mb = Effect (liftM2 mappend ma mb)
-
-instance Monad m => Gettable (Effect m r) where
-  coerce (Effect m) = Effect m
-
-instance Monad m => Effective m r (Effect m r) where
-  effective = isomorphic Effect getEffect
-  {-# SPECIALIZE effective :: Monad m => m r -> Effect m r a #-}
-  {-# SPECIALIZE effective :: Monad m => Isomorphism (m r) (Effect m r a) #-}
-
 -- | Used to evaluate an 'Action'.
 type Acting m r a c = (c -> Effect m r c) -> a -> Effect m r a
 
@@ -125,7 +72,7 @@
 
 -- | Construct an 'Action' from a monadic side-effect
 act :: Monad m => (a -> m c) -> Action m a c
-act amc cfd a = effective (amc a >>= from effective . cfd)
+act amc cfd a = effective (amc a >>= ineffective . cfd)
 {-# INLINE act #-}
 
 -- | A self-running 'Action', analogous to 'Control.Monad.join'.
diff --git a/src/Control/Lens/Fold.hs b/src/Control/Lens/Fold.hs
--- a/src/Control/Lens/Fold.hs
+++ b/src/Control/Lens/Fold.hs
@@ -27,7 +27,7 @@
 -- it is passed.
 --
 -- In practice the type we use is slightly more complicated to allow for
--- better error messages and for it to be transformed by certain 
+-- better error messages and for it to be transformed by certain
 -- 'Applicative' transformers.
 --
 -- Everything you can do with a 'Foldable' container, you can with with a 'Fold' and there are
@@ -575,6 +575,7 @@
 --
 -- @'length' = 'lengthOf' 'folded'@
 --
+-- >>> import Control.Lens
 -- >>> lengthOf _1 ("hello",())
 -- 1
 --
@@ -630,6 +631,7 @@
 --
 -- This may be rather inefficient compared to the 'null' check of many containers.
 --
+-- >>> import Control.Lens
 -- >>> nullOf _1 (1,2)
 -- False
 --
diff --git a/src/Control/Lens/Getter.hs b/src/Control/Lens/Getter.hs
--- a/src/Control/Lens/Getter.hs
+++ b/src/Control/Lens/Getter.hs
@@ -43,8 +43,6 @@
   -- * Getters
     Getter
   , Getting
-  , Gettable(..)
-  , Accessor(..)
   -- * Building Getters
   , to
   -- * Combinators for Getters and Folds
@@ -55,28 +53,11 @@
   , uses
   , query
   , queries
-  , Magnify(..)
   ) where
 
-import Control.Applicative
-import Control.Applicative.Backwards
 import Control.Lens.Internal
 import Control.Monad.Reader.Class       as Reader
 import Control.Monad.State.Class        as State
-import Control.Monad.Trans.State.Lazy   as Lazy
-import Control.Monad.Trans.State.Strict as Strict
-import Control.Monad.Trans.Writer.Lazy   as Lazy
-import Control.Monad.Trans.Writer.Strict as Strict
-import Control.Monad.Trans.RWS.Lazy   as Lazy
-import Control.Monad.Trans.RWS.Strict as Strict
-import Control.Monad.Trans.Reader
-import Control.Monad.Trans.Error
-import Control.Monad.Trans.List
-import Control.Monad.Trans.Identity
-import Control.Monad.Trans.Cont
-import Control.Monad.Trans.Maybe
-import Data.Functor.Compose
-import Data.Monoid
 
 infixl 8 ^.
 infixr 0 ^$
@@ -124,57 +105,6 @@
 type Getting r a c = (c -> Accessor r c) -> a -> Accessor r a
 
 -------------------------------------------------------------------------------
--- Gettables & Accessors
--------------------------------------------------------------------------------
-
--- | Generalizing 'Const' so we can apply simple 'Applicative'
--- transformations to it and so we can get nicer error messages
---
--- A 'Gettable' 'Functor' ignores its argument, which it carries solely as a
--- phantom type parameter.
---
--- To ensure this, an instance of 'Gettable' is required to satisfy:
---
--- @'id' = 'fmap' f = 'coerce'@
-class Functor f => Gettable f where
-  -- | Replace the phantom type argument.
-  coerce :: f a -> f b
-
-instance Gettable (Const r) where
-  coerce (Const m) = Const m
-
-instance Gettable f => Gettable (Backwards f) where
-  coerce = Backwards . coerce . forwards
-
-instance (Functor f, Gettable g) => Gettable (Compose f g) where
-  coerce = Compose . fmap coerce . getCompose
-
--- | This instance is a lie, but it is a useful lie.
-instance Gettable f => Gettable (ElementOf f) where
-  coerce (ElementOf m) = ElementOf $ \i -> case m i of
-    Searching _ _ -> NotFound "coerced while searching" -- er...
-    Found j as    -> Found j (coerce as)
-    NotFound s    -> NotFound s
-
--- | Used instead of 'Const' to report
---
--- @No instance of ('Control.Lens.Setter.Settable' 'Accessor')@
---
--- when the user attempts to misuse a 'Control.Lens.Setter.Setter' as a
--- 'Getter', rather than a monolithic unification error.
-newtype Accessor r a = Accessor { runAccessor :: r }
-
-instance Functor (Accessor r) where
-  fmap _ (Accessor m) = Accessor m
-
-instance Gettable (Accessor r) where
-  coerce (Accessor m) = Accessor m
-
-instance Monoid r => Applicative (Accessor r) where
-  pure _ = Accessor mempty
-  Accessor a <*> Accessor b = Accessor (mappend a b)
-
--------------------------------------------------------------------------------
 -- Getting Values
 -------------------------------------------------------------------------------
 
@@ -349,78 +279,3 @@
 {-# INLINE queries #-}
 
 
--- | This class allows us to use 'magnify' part of the environment, changing the environment supplied by
--- many different monad transformers. Unlike 'focus' this can change the environment of a deeply nested monad transformer.
---
--- Also, unlike 'focus', this can be used with any valid 'Getter', but cannot be used with a 'Traversal' or 'Fold'.
-class (MonadReader b m, MonadReader a n) => Magnify m n b a | m -> b, n -> a, m a -> n, n b -> m where
-  -- | Run a monadic action in a larger environment than it was defined in, using a 'Getter'.
-  --
-  -- This acts like 'Control.Monad.Reader.Class.local', but can in many cases change the type of the environment as well.
-  --
-  -- This is commonly used to lift actions in a simpler Reader monad into a monad with a larger environment type.
-  --
-  -- This can be used to edit pretty much any monad transformer stack with an environment in it:
-  --
-  -- @
-  -- magnify :: 'Getter' a b -> (b -> c) -> a -> c
-  -- magnify :: 'Getter' a b -> RWS a w s c -> RWST b w s c
-  -- magnify :: 'Getter' a b -> ErrorT e (Reader b) c -> ErrorT e (Reader a) c
-  -- magnify :: 'Getter' a b -> ListT (ReaderT b (StateT s)) c -> ListT (ReaderT a (StateT s)) c
-  -- ...
-  -- @
-  magnify :: Getter a b -> m c -> n c
-
-instance Monad m => Magnify (ReaderT b m) (ReaderT a m) b a where
-  magnify l (ReaderT m) = ReaderT $ \e -> m (e^.l)
-  {-# INLINE magnify #-}
-
-instance Magnify ((->) b) ((->) a) b a where
-  magnify l bc a = bc (view l a)
-  {-# INLINE magnify #-}
-
-instance (Monad m, Monoid w) => Magnify (Strict.RWST b w s m) (Strict.RWST a w s m) b a where
-  magnify l (Strict.RWST m) = Strict.RWST $ \a w -> m (a^.l) w
-  {-# INLINE magnify #-}
-
-instance (Monad m, Monoid w) => Magnify (Lazy.RWST b w s m) (Lazy.RWST a w s m) b a where
-  magnify l (Lazy.RWST m) = Lazy.RWST $ \a w -> m (a^.l) w
-  {-# INLINE magnify #-}
-
-instance Magnify m n b a => Magnify (Strict.StateT s m) (Strict.StateT s n) b a where
-  magnify l (Strict.StateT m) = Strict.StateT $ magnify l . m
-  {-# INLINE magnify #-}
-
-instance Magnify m n b a => Magnify (Lazy.StateT s m) (Lazy.StateT s n) b a where
-  magnify l (Lazy.StateT m) = Lazy.StateT $ magnify l . m
-  {-# INLINE magnify #-}
-
-instance (Monoid w, Magnify m n b a) => Magnify (Strict.WriterT w m) (Strict.WriterT w n) b a where
-  magnify l (Strict.WriterT m) = Strict.WriterT (magnify l m)
-  {-# INLINE magnify #-}
-
-instance (Monoid w, Magnify m n b a) => Magnify (Lazy.WriterT w m) (Lazy.WriterT w n) b a where
-  magnify l (Lazy.WriterT m) = Lazy.WriterT (magnify l m)
-  {-# INLINE magnify #-}
-
-instance Magnify m n b a => Magnify (ListT m) (ListT n) b a where
-  magnify l (ListT m) = ListT (magnify l m)
-  {-# INLINE magnify #-}
-
-instance Magnify m n b a => Magnify (MaybeT m) (MaybeT n) b a where
-  magnify l (MaybeT m) = MaybeT (magnify l m)
-  {-# INLINE magnify #-}
-
-instance Magnify m n b a => Magnify (IdentityT m) (IdentityT n) b a where
-  magnify l (IdentityT m) = IdentityT (magnify l m)
-  {-# INLINE magnify #-}
-
-instance (Error e, Magnify m n b a) => Magnify (ErrorT e m) (ErrorT e n) b a where
-  magnify l (ErrorT m) = ErrorT (magnify l m)
-  {-# INLINE magnify #-}
-
-instance Magnify m m a a => Magnify (ContT r m) (ContT r m) a a where
-  magnify l (ContT m) = ContT $ \k -> do
-    r <- Reader.ask
-    magnify l (m (magnify (to (const r)) . k))
-  {-# INLINE magnify #-}
diff --git a/src/Control/Lens/IndexedFold.hs b/src/Control/Lens/IndexedFold.hs
--- a/src/Control/Lens/IndexedFold.hs
+++ b/src/Control/Lens/IndexedFold.hs
@@ -43,7 +43,6 @@
   ) where
 
 import Control.Applicative
-import Control.Lens.Getter
 import Control.Lens.Indexed
 import Control.Lens.IndexedGetter
 import Control.Lens.Internal
@@ -112,7 +111,7 @@
 {-# INLINE ifoldlOf #-}
 
 -- |
--- Return whether or not any element viewed through an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal' 
+-- Return whether or not any element viewed through an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal'
 -- satisfy a predicate, with access to the index @i@.
 --
 -- When you don't need access to the index then 'Control.Lens.Fold.anyOf' is more flexible in what it accepts.
@@ -130,7 +129,7 @@
 {-# INLINE ianyOf #-}
 
 -- |
--- Return whether or not all elements viewed through an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal' 
+-- Return whether or not all elements viewed through an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal'
 -- satisfy a predicate, with access to the index @i@.
 --
 -- When you don't need access to the index then 'Control.Lens.Fold.allOf' is more flexible in what it accepts.
diff --git a/src/Control/Lens/IndexedGetter.hs b/src/Control/Lens/IndexedGetter.hs
--- a/src/Control/Lens/IndexedGetter.hs
+++ b/src/Control/Lens/IndexedGetter.hs
@@ -17,8 +17,8 @@
   , IndexedGetting
   ) where
 
-import Control.Lens.Getter
 import Control.Lens.Indexed
+import Control.Lens.Internal
 
 ------------------------------------------------------------------------------
 -- Indexed Getters
diff --git a/src/Control/Lens/IndexedSetter.hs b/src/Control/Lens/IndexedSetter.hs
--- a/src/Control/Lens/IndexedSetter.hs
+++ b/src/Control/Lens/IndexedSetter.hs
@@ -25,7 +25,7 @@
   ) where
 
 import Control.Lens.Indexed
-import Control.Lens.Setter
+import Control.Lens.Internal
 import Control.Lens.Type
 import Control.Monad.State.Class as State
 
diff --git a/src/Control/Lens/Internal.hs b/src/Control/Lens/Internal.hs
--- a/src/Control/Lens/Internal.hs
+++ b/src/Control/Lens/Internal.hs
@@ -1,3 +1,8 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Lens.Internal
@@ -18,6 +23,11 @@
   -- * Implementation details
     IndexedStore(..)
   , Focusing(..)
+  , FocusingWith(..)
+  , FocusingPlus(..)
+  , FocusingOn(..)
+  , FocusingErr(..), Err(..)
+  , FocusingMay(..), May(..)
   , Traversed(..)
   , Sequenced(..)
   , AppliedState(..)
@@ -27,20 +37,30 @@
   , getMax
   , ElementOf(..)
   , ElementOfResult(..)
+  , Kleene(..), kleene
+  , Effect(..)
+  , EffectRWS(..)
+  -- , EffectS(..)
+  , Gettable(..), Accessor(..), Effective(..), ineffective
+  , Settable(..), Mutator(..)
   ) where
 
+
 import Control.Applicative
+import Control.Applicative.Backwards
 import Control.Category
+import Control.Lens.Isomorphic
 import Control.Monad
 import Prelude hiding ((.),id)
+import Data.Functor.Compose
+import Data.Functor.Identity
 import Data.Monoid
 
 -----------------------------------------------------------------------------
 -- Functors
 -----------------------------------------------------------------------------
 
--- | Used by 'Control.Lens.Type.Focus'
-
+-- | Used by 'Control.Lens.Type.Zoom' to 'Control.Lens.Type.zoom' into 'Control.Monad.State.StateT'
 newtype Focusing m c a = Focusing { unfocusing :: m (c, a) }
 
 instance Monad m => Functor (Focusing m c) where
@@ -55,9 +75,81 @@
     (d, a) <- ma
     return (mappend c d, f a)
 
+-- | Used by 'Control.Lens.Type.Zoom' to 'Control.Lens.Type.zoom' into 'Control.Monad.RWS.RWST'
+newtype FocusingWith w m c a = FocusingWith { unfocusingWith :: m (c, a, w) }
+
+instance Monad m => Functor (FocusingWith w m c) where
+  fmap f (FocusingWith m) = FocusingWith $ do
+     (c, a, w) <- m
+     return (c, f a, w)
+
+instance (Monad m, Monoid c, Monoid w) => Applicative (FocusingWith w m c) where
+  pure a = FocusingWith (return (mempty, a, mempty))
+  FocusingWith mf <*> FocusingWith ma = FocusingWith $ do
+    (c, f, w) <- mf
+    (d, a, w') <- ma
+    return (mappend c d, f a, mappend w w')
+
+-- | Used by 'Control.Lens.Type.Zoom' to 'Control.Lens.Type.zoom' into 'Control.Monad.Writer.WriterT'.
+newtype FocusingPlus w k c a = FocusingPlus { unfocusingPlus :: k (c, w) a }
+
+instance Functor (k (c, w)) => Functor (FocusingPlus w k c) where
+  fmap f (FocusingPlus as) = FocusingPlus (fmap f as)
+
+instance (Monoid w, Applicative (k (c, w))) => Applicative (FocusingPlus w k c) where
+  pure = FocusingPlus . pure
+  FocusingPlus kf <*> FocusingPlus ka = FocusingPlus (kf <*> ka)
+
+-- | Used by 'Control.Lens.Type.Zoom' to 'Control.Lens.Type.zoom' into 'Control.Monad.Trans.Maybe.MaybeT' or 'Control.Monad.Trans.List.ListT'
+newtype FocusingOn f k c a = FocusingOn { unfocusingOn :: k (f c) a }
+
+instance Functor (k (f c)) => Functor (FocusingOn f k c) where
+  fmap f (FocusingOn as) = FocusingOn (fmap f as)
+
+instance Applicative (k (f c)) => Applicative (FocusingOn f k c) where
+  pure = FocusingOn . pure
+  FocusingOn kf <*> FocusingOn ka = FocusingOn (kf <*> ka)
+
+-- | Make a monoid out of 'Maybe' for error handling
+newtype May a = May { getMay :: Maybe a }
+
+instance Monoid a => Monoid (May a) where
+  mempty = May (Just mempty)
+  May Nothing `mappend` _ = May Nothing
+  _ `mappend` May Nothing = May Nothing
+  May (Just a) `mappend` May (Just b) = May (Just (mappend a b))
+
+-- | Used by 'Control.Lens.Type.Zoom' to 'Control.Lens.Type.zoom' into 'Control.Monad.Error.ErrorT'
+newtype FocusingMay k c a = FocusingMay { unfocusingMay :: k (May c) a }
+
+instance Functor (k (May c)) => Functor (FocusingMay k c) where
+  fmap f (FocusingMay as) = FocusingMay (fmap f as)
+
+instance Applicative (k (May c)) => Applicative (FocusingMay k c) where
+  pure = FocusingMay . pure
+  FocusingMay kf <*> FocusingMay ka = FocusingMay (kf <*> ka)
+
+-- | Make a monoid out of 'Either' for error handling
+newtype Err e a = Err { getErr :: Either e a }
+
+instance Monoid a => Monoid (Err e a) where
+  mempty = Err (Right mempty)
+  Err (Left e) `mappend` _ = Err (Left e)
+  _ `mappend` Err (Left e) = Err (Left e)
+  Err (Right a) `mappend` Err (Right b) = Err (Right (mappend a b))
+
+-- | Used by 'Control.Lens.Type.Zoom' to 'Control.Lens.Type.zoom' into 'Control.Monad.Error.ErrorT'
+newtype FocusingErr e k c a = FocusingErr { unfocusingErr :: k (Err e c) a }
+
+instance Functor (k (Err e c)) => Functor (FocusingErr e k c) where
+  fmap f (FocusingErr as) = FocusingErr (fmap f as)
+
+instance Applicative (k (Err e c)) => Applicative (FocusingErr e k c) where
+  pure = FocusingErr . pure
+  FocusingErr kf <*> FocusingErr ka = FocusingErr (kf <*> ka)
+
 -- | The indexed store can be used to characterize a 'Control.Lens.Type.Lens'
 -- and is used by 'Control.Lens.Type.clone'
-
 data IndexedStore c d a = IndexedStore (d -> a) c
 
 instance Functor (IndexedStore c d) where
@@ -65,7 +157,6 @@
 
 -- | Applicative composition of @'Control.Monad.Trans.State.Lazy.State' 'Int'@ with a 'Functor', used
 -- by 'Control.Lens.Traversal.elementOf', 'Control.Lens.Traversal.elementsOf', 'Control.Lens.Traversal.traverseElement', 'Control.Lens.Traversal.traverseElementsOf'
-
 newtype AppliedState f a = AppliedState { runAppliedState :: Int -> (f a, Int) }
 
 instance Functor f => Functor (AppliedState f) where
@@ -79,7 +170,6 @@
        (fa, k) -> (ff <*> fa, k)
 
 -- | Used internally by 'Control.Lens.Traversal.traverseOf_' and the like.
-
 newtype Traversed f = Traversed { getTraversed :: f () }
 
 instance Applicative f => Monoid (Traversed f) where
@@ -153,3 +243,189 @@
       Searching k a -> Searching k (f a)
       NotFound e    -> NotFound e
     NotFound e -> NotFound e
+
+
+-- | The "Indexed Kleene Store comonad", aka the 'indexed cartesian store comonad' or an indexed 'FunList'.
+--
+-- This is used to characterize a 'Control.Lens.Traversal.Traversal'.
+--
+-- <http://twanvl.nl/blog/haskell/non-regular1>
+data Kleene c d a
+  = Done a
+  | More (Kleene c d (d -> a)) c
+
+instance Functor (Kleene c d) where
+  fmap f (Done a) = Done (f a)
+  fmap f (More k b) = More (fmap (f .) k)  b
+
+instance Applicative (Kleene c d) where
+  pure = Done
+  Done f   <*> m = fmap f m
+  More k c <*> m = More (flip <$> k <*> m) c
+
+-- | Given an action to run for each matched pair, traverse a store.
+kleene :: Applicative f => (c -> f d) -> Kleene c d b -> f b
+kleene _ (Done b) = pure b
+kleene f (More k c) = f c <**> kleene f k
+
+-- | Wrap a monadic effect with a phantom type argument.
+newtype Effect m r a = Effect { getEffect :: m r }
+
+instance Functor (Effect m r) where
+  fmap _ (Effect m) = Effect m
+
+instance (Monad m, Monoid r) => Monoid (Effect m r a) where
+  mempty = Effect (return mempty)
+  Effect ma `mappend` Effect mb = Effect (liftM2 mappend ma mb)
+
+instance (Monad m, Monoid r) => Applicative (Effect m r) where
+  pure _ = Effect (return mempty)
+  Effect ma <*> Effect mb = Effect (liftM2 mappend ma mb)
+
+-- | Wrap a monadic effect with a phantom type argument. Used when magnifying RWST.
+newtype EffectRWS w s m c a = EffectRWS { getEffectRWS :: s -> m (c,s,w) }
+
+instance Functor (EffectRWS w s m c) where
+  fmap _ (EffectRWS m) = EffectRWS m
+
+instance (Monoid c, Monoid w, Monad m) => Applicative (EffectRWS w s m c) where
+  pure _ = EffectRWS $ \s -> return (mempty, s, mempty)
+  EffectRWS m <*> EffectRWS n = EffectRWS $ \s -> m s >>= \ (c,t,w) -> n t >>= \ (c',u,w') -> return (mappend c c', u, mappend w w')
+
+{-
+-- | Wrap a monadic effect with a phantom type argument. Used when magnifying StateT.
+newtype EffectS s k c a = EffectS { runEffect :: s -> k (c, s) a }
+
+instance Functor (k (c, s)) => Functor (EffectS s m c) where
+  fmap f (EffectS m) = EffectS (fmap f . m)
+
+instance (Monoid c, Monad m) => Applicative (EffectS s m c) where
+  pure _ = EffectS $ \s -> return (mempty, s)
+  EffectS m <*> EffectS n = EffectS $ \s -> m s >>= \ (c,t) -> n s >>= \ (d, u) -> return (mappend c d, u)
+-}
+
+-------------------------------------------------------------------------------
+-- Gettables & Accessors
+-------------------------------------------------------------------------------
+
+-- | Generalizing 'Const' so we can apply simple 'Applicative'
+-- transformations to it and so we can get nicer error messages
+--
+-- A 'Gettable' 'Functor' ignores its argument, which it carries solely as a
+-- phantom type parameter.
+--
+-- To ensure this, an instance of 'Gettable' is required to satisfy:
+--
+-- @'id' = 'fmap' f = 'coerce'@
+class Functor f => Gettable f where
+  -- | Replace the phantom type argument.
+  coerce :: f a -> f b
+
+instance Gettable (Const r) where
+  coerce (Const m) = Const m
+
+instance Gettable f => Gettable (Backwards f) where
+  coerce = Backwards . coerce . forwards
+
+instance (Functor f, Gettable g) => Gettable (Compose f g) where
+  coerce = Compose . fmap coerce . getCompose
+
+instance Gettable (Effect m r) where
+  coerce (Effect m) = Effect m
+
+instance Gettable (EffectRWS w s m c) where
+  coerce (EffectRWS m) = EffectRWS m
+
+--instance Gettable (EffectS s m c) where
+--  coerce (EffectS m) = EffectS m
+
+-- | This instance is a lie, but it is a useful lie.
+instance Gettable f => Gettable (ElementOf f) where
+  coerce (ElementOf m) = ElementOf $ \i -> case m i of
+    Searching _ _ -> NotFound "coerced while searching" -- er...
+    Found j as    -> Found j (coerce as)
+    NotFound s    -> NotFound s
+
+instance Gettable (Accessor r) where
+  coerce (Accessor m) = Accessor m
+
+-- | Used instead of 'Const' to report
+--
+-- @No instance of ('Control.Lens.Setter.Settable' 'Accessor')@
+--
+-- when the user attempts to misuse a 'Control.Lens.Setter.Setter' as a
+-- 'Getter', rather than a monolithic unification error.
+newtype Accessor r a = Accessor { runAccessor :: r }
+
+instance Functor (Accessor r) where
+  fmap _ (Accessor m) = Accessor m
+
+instance Monoid r => Applicative (Accessor r) where
+  pure _ = Accessor mempty
+  Accessor a <*> Accessor b = Accessor (mappend a b)
+
+-- | An 'Effective' 'Functor' ignores its argument and is isomorphic to a monad wrapped around a value.
+--
+-- That said, the monad is possibly rather unrelated to any 'Applicative' structure.
+class (Monad m, Gettable f) => Effective m r f | f -> m r where
+  effective :: Isomorphic k => k (m r) (f a)
+
+-- | A convenient antonym that is used internally.
+ineffective :: Effective m r f => Isomorphic k => k (f a) (m r)
+ineffective = from effective
+{-# INLINE ineffective #-}
+
+instance Effective Identity r (Accessor r) where
+  effective = isomorphic (Accessor . runIdentity) (Identity . runAccessor)
+  {-# INLINE effective #-}
+  {-# SPECIALIZE effective :: Identity r -> Accessor r a #-}
+  {-# SPECIALIZE effective :: Isomorphism (Identity r) (Accessor r a) #-}
+
+instance Effective m r f => Effective m (Dual r) (Backwards f) where
+  effective = isomorphic (Backwards . effective . liftM getDual) (liftM Dual . ineffective . forwards)
+
+instance Monad m => Effective m r (Effect m r) where
+  effective = isomorphic Effect getEffect
+  {-# SPECIALIZE effective :: Monad m => m r -> Effect m r a #-}
+  {-# SPECIALIZE effective :: Monad m => Isomorphism (m r) (Effect m r a) #-}
+
+-----------------------------------------------------------------------------
+-- Settables & Mutators
+-----------------------------------------------------------------------------
+
+-- | Anything 'Settable' must be isomorphic to the 'Identity' 'Functor'.
+class Applicative f => Settable f where
+  untainted :: f a -> a
+
+-- | so you can pass our a 'Setter' into combinators from other lens libraries
+instance Settable Identity where
+  untainted = runIdentity
+  {-# INLINE untainted #-}
+
+-- | 'Control.Lens.Fold.backwards'
+instance Settable f => Settable (Backwards f) where
+  untainted = untainted . forwards
+  {-# INLINE untainted #-}
+
+instance (Settable f, Settable g) => Settable (Compose f g) where
+  untainted = untainted . untainted . getCompose
+  {-# INLINE untainted #-}
+
+instance Settable Mutator where
+  untainted = runMutator
+  {-# INLINE untainted #-}
+
+-- | 'Mutator' is just a renamed 'Identity' functor to give better error
+-- messages when someone attempts to use a getter as a setter.
+--
+-- Most user code will never need to see this type.
+newtype Mutator a = Mutator { runMutator :: a }
+
+instance Functor Mutator where
+  fmap f (Mutator a) = Mutator (f a)
+
+instance Applicative Mutator where
+  pure = Mutator
+  Mutator f <*> Mutator a = Mutator (f a)
+
+
diff --git a/src/Control/Lens/Iso.hs b/src/Control/Lens/Iso.hs
--- a/src/Control/Lens/Iso.hs
+++ b/src/Control/Lens/Iso.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE DeriveDataTypeable #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Lens.Iso
@@ -19,97 +18,27 @@
   , au
   , auf
   , under
-  -- ** Combinators
-  , via
+  -- * Primitive isomorphisms
   , from
+  , via
+  , Isomorphism(..)
+  , Isomorphic(..)
   -- ** Common Isomorphisms
   , _const
   , identity
-  -- * Implementation
-  , Isomorphic(..)
-  , Isomorphism(..)
   -- * Simplicity
   , SimpleIso
   ) where
 
 import Control.Applicative
 import Control.Category
-import Control.Lens.Type
 import Control.Lens.Getter
+import Control.Lens.Internal
+import Control.Lens.Isomorphic
 import Control.Lens.Setter
+import Control.Lens.Type
 import Data.Functor.Identity
-import Data.Typeable
 import Prelude hiding ((.),id)
-
-----------------------------------------------------------------------------
--- Isomorphism Implementation Details
------------------------------------------------------------------------------
-
--- | Used to provide overloading of isomorphism application
---
--- This is a 'Category' with a canonical mapping to it from the
--- category of isomorphisms over Haskell types.
-class Category k => Isomorphic k where
-  -- | Build this morphism out of an isomorphism
-  --
-  -- The intention is that by using 'isomorphic', you can supply both halves of an
-  -- isomorphism, but k can be instantiated to @(->)@, so you can freely use
-  -- the resulting isomorphism as a function.
-  isomorphic :: (a -> b) -> (b -> a) -> k a b
-
-  -- | Map a morphism in the target category using an isomorphism between morphisms
-  -- in Hask.
-  isomap :: ((a -> b) -> c -> d) -> ((b -> a) -> d -> c) -> k a b -> k c d
-
-instance Isomorphic (->) where
-  isomorphic = const
-  {-# INLINE isomorphic #-}
-  isomap = const
-  {-# INLINE isomap #-}
-
--- | A concrete data type for isomorphisms.
---
--- This lets you place an isomorphism inside a container without using @ImpredicativeTypes@.
-data Isomorphism a b = Isomorphism (a -> b) (b -> a)
-  deriving Typeable
-
-instance Category Isomorphism where
-  id = Isomorphism id id
-  {-# INLINE id #-}
-  Isomorphism bc cb . Isomorphism ab ba = Isomorphism (bc . ab) (ba . cb)
-  {-# INLINE (.) #-}
-
-instance Isomorphic Isomorphism where
-  isomorphic = Isomorphism
-  {-# INLINE isomorphic #-}
-  isomap abcd badc (Isomorphism ab ba) = Isomorphism (abcd ab) (badc ba)
-  {-# INLINE isomap #-}
-
--- | Invert an isomorphism.
---
--- Note to compose an isomorphism and receive an isomorphism in turn you'll need to use
--- 'Control.Category.Category'
---
--- > from (from l) = l
---
--- If you imported 'Control.Category..' from @Control.Category@, then:
---
--- > from l . from r = from (r . l)
-from :: Isomorphic k => Isomorphism a b -> k b a
-from (Isomorphism a b) = isomorphic b a
-{-# INLINE from #-}
-{-# SPECIALIZE from :: Isomorphism a b -> b -> a #-}
-{-# SPECIALIZE from :: Isomorphism a b -> Isomorphism b a #-}
-
--- | Convert from an 'Isomorphism' back to any 'Isomorphic' value.
---
--- This is useful when you need to store an isomoprhism as a data type inside a container
--- and later reconstitute it as an overloaded function.
-via :: Isomorphic k => Isomorphism a b -> k a b
-via (Isomorphism a b) = isomorphic a b
-{-# INLINE via #-}
-{-# SPECIALIZE via :: Isomorphism a b -> a -> b #-}
-{-# SPECIALIZE via :: Isomorphism a b -> Isomorphism a b #-}
 
 -----------------------------------------------------------------------------
 -- Isomorphisms families as Lenses
diff --git a/src/Control/Lens/Isomorphic.hs b/src/Control/Lens/Isomorphic.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Lens/Isomorphic.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Lens.Isomorphic
+-- Copyright   :  (C) 2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  Rank2Types
+--
+----------------------------------------------------------------------------
+module Control.Lens.Isomorphic
+  ( Isomorphic(..)
+  , Isomorphism(..)
+  , from
+  , via
+  ) where
+
+import Control.Category
+import Data.Typeable
+import Prelude hiding ((.),id)
+
+----------------------------------------------------------------------------
+-- Isomorphism Implementation Details
+-----------------------------------------------------------------------------
+
+-- | Used to provide overloading of isomorphism application
+--
+-- This is a 'Category' with a canonical mapping to it from the
+-- category of isomorphisms over Haskell types.
+class Category k => Isomorphic k where
+  -- | Build this morphism out of an isomorphism
+  --
+  -- The intention is that by using 'isomorphic', you can supply both halves of an
+  -- isomorphism, but k can be instantiated to @(->)@, so you can freely use
+  -- the resulting isomorphism as a function.
+  isomorphic :: (a -> b) -> (b -> a) -> k a b
+
+  -- | Map a morphism in the target category using an isomorphism between morphisms
+  -- in Hask.
+  isomap :: ((a -> b) -> c -> d) -> ((b -> a) -> d -> c) -> k a b -> k c d
+
+instance Isomorphic (->) where
+  isomorphic = const
+  {-# INLINE isomorphic #-}
+  isomap = const
+  {-# INLINE isomap #-}
+
+-- | A concrete data type for isomorphisms.
+--
+-- This lets you place an isomorphism inside a container without using @ImpredicativeTypes@.
+data Isomorphism a b = Isomorphism (a -> b) (b -> a)
+  deriving Typeable
+
+instance Category Isomorphism where
+  id = Isomorphism id id
+  {-# INLINE id #-}
+  Isomorphism bc cb . Isomorphism ab ba = Isomorphism (bc . ab) (ba . cb)
+  {-# INLINE (.) #-}
+
+instance Isomorphic Isomorphism where
+  isomorphic = Isomorphism
+  {-# INLINE isomorphic #-}
+  isomap abcd badc (Isomorphism ab ba) = Isomorphism (abcd ab) (badc ba)
+  {-# INLINE isomap #-}
+
+-- | Invert an isomorphism.
+--
+-- Note to compose an isomorphism and receive an isomorphism in turn you'll need to use
+-- 'Control.Category.Category'
+--
+-- > from (from l) = l
+--
+-- If you imported 'Control.Category..' from @Control.Category@, then:
+--
+-- > from l . from r = from (r . l)
+from :: Isomorphic k => Isomorphism a b -> k b a
+from (Isomorphism a b) = isomorphic b a
+{-# INLINE from #-}
+{-# SPECIALIZE from :: Isomorphism a b -> b -> a #-}
+{-# SPECIALIZE from :: Isomorphism a b -> Isomorphism b a #-}
+
+-- | Convert from an 'Isomorphism' back to any 'Isomorphic' value.
+--
+-- This is useful when you need to store an isomoprhism as a data type inside a container
+-- and later reconstitute it as an overloaded function.
+via :: Isomorphic k => Isomorphism a b -> k a b
+via (Isomorphism a b) = isomorphic a b
+{-# INLINE via #-}
+{-# SPECIALIZE via :: Isomorphism a b -> a -> b #-}
+{-# SPECIALIZE via :: Isomorphism a b -> Isomorphism a b #-}
diff --git a/src/Control/Lens/Setter.hs b/src/Control/Lens/Setter.hs
--- a/src/Control/Lens/Setter.hs
+++ b/src/Control/Lens/Setter.hs
@@ -25,7 +25,6 @@
   (
   -- * Setters
     Setter
-  , Settable(..)
   -- * Building Setters
   , sets
   -- * Common Setters
@@ -42,17 +41,14 @@
   , (<~)
   -- * Setter Internals
   , Setting
-  , Mutator(..)
   , SimpleSetting
   -- * Simplicity
   , SimpleSetter
   ) where
 
 import Control.Applicative
-import Control.Applicative.Backwards
+import Control.Lens.Internal
 import Control.Monad.State.Class        as State
-import Data.Functor.Compose
-import Data.Functor.Identity
 
 infixr 4 .~, +~, *~, -~, //~, ^~, ^^~, **~, &&~, ||~, %~, <.~
 infix  4 .=, +=, *=, -=, //=, ^=, ^^=, **=, &&=, ||=, %=, <.=
@@ -114,45 +110,6 @@
 --
 -- @type 'SimpleSetting' m = 'Control.Lens.Type.Simple' 'Setting'@
 type SimpleSetting a b = Setting a a b b
-
------------------------------------------------------------------------------
--- Settables & Mutators
------------------------------------------------------------------------------
-
--- | Anything 'Settable' must be isomorphic to the 'Identity' 'Functor'.
-class Applicative f => Settable f where
-  untainted :: f a -> a
-
--- | so you can pass our a 'Setter' into combinators from other lens libraries
-instance Settable Identity where
-  untainted = runIdentity
-  {-# INLINE untainted #-}
-
--- | 'Control.Lens.Fold.backwards'
-instance Settable f => Settable (Backwards f) where
-  untainted = untainted . forwards
-  {-# INLINE untainted #-}
-
-instance (Settable f, Settable g) => Settable (Compose f g) where
-  untainted = untainted . untainted . getCompose
-  {-# INLINE untainted #-}
-
--- | 'Mutator' is just a renamed 'Identity' functor to give better error
--- messages when someone attempts to use a getter as a setter.
---
--- Most user code will never need to see this type.
-newtype Mutator a = Mutator { runMutator :: a }
-
-instance Functor Mutator where
-  fmap f (Mutator a) = Mutator (f a)
-
-instance Applicative Mutator where
-  pure = Mutator
-  Mutator f <*> Mutator a = Mutator (f a)
-
-instance Settable Mutator where
-  untainted = runMutator
-  {-# INLINE untainted #-}
 
 -----------------------------------------------------------------------------
 -- Setters
diff --git a/src/Control/Lens/TH.hs b/src/Control/Lens/TH.hs
--- a/src/Control/Lens/TH.hs
+++ b/src/Control/Lens/TH.hs
@@ -37,8 +37,9 @@
 import Control.Lens.Getter
 import Control.Lens.Iso
 import Control.Lens.Setter
-import Control.Lens.Type
+import Control.Lens.Tuple
 import Control.Lens.Traversal
+import Control.Lens.Type
 import Control.Monad
 import Data.Char (toLower)
 import Data.Foldable
@@ -259,33 +260,38 @@
     Just (FieldDesc _ _ bds') -> at nm .~ Just (FieldDesc nm ty (bds `Set.union` bds')) $ m
     Nothing                   -> at nm .~ Just d                                        $ m
 
-errorClause :: Name -> Name -> Name -> ClauseQ
-errorClause lensName fieldName conName
-  = clause [] (normalB (return (VarE 'error) `appE` litE (stringL err))) []
-  where
-    err = show lensName ++ ": no matching field "
-       ++ show fieldName ++ " in constructor "
-       ++ show conName
-
 makeFieldLensBody :: Name -> Name -> [Con] -> Maybe Name -> Q Dec
 makeFieldLensBody lensName fieldName cons maybeMethodName = case maybeMethodName of
     Just methodName -> do
        go <- newName "go"
-       funD lensName [ clause [] (normalB (infixApp (varE methodName) (varE (mkName ".")) (varE go))) [funD go (map clauses cons)]]
+       let expr = infixApp (varE methodName) (varE (mkName ".")) (varE go)
+       funD lensName [ clause [] (normalB expr) [funD go (map clauses cons)] ]
     Nothing -> funD lensName (map clauses cons)
   where
-    clauses (RecC conName fields) = case List.findIndex (\(n,_,_) -> n == fieldName) fields of
-      Just i -> do
-        names <- for fields $ \(n,_,_) -> newName (nameBase n)
-        f     <- newName "f"
-        x     <- newName "y"
-        clause [varP f, conP conName $ map varP names] (normalB
-               (appsE [ return (VarE 'fmap)
-                      , lamE [varP x] $ appsE $ conE conName : map varE (element i .~ x $ names)
-                      , varE f `appE` varE (names^.element i)
-                      ])) []
-      Nothing -> errorClause lensName fieldName conName
-    clauses con = errorClause lensName fieldName (con^.name)
+    clauses con = do
+      let errorPats
+            = [wildP, conP (con^.name) (replicate (lengthOf conFields con) wildP)]
+          errorBody
+            = normalB . appE (varE 'error) . litE . stringL
+            $ show lensName ++ ": no matching field "
+           ++ show fieldName ++ " in constructor "
+           ++ show (con^.name)
+          errorClause = clause errorPats errorBody []
+      case con of
+        (RecC conName fields) ->
+          case List.findIndex (\(n,_,_) -> n == fieldName) fields of
+            Just i -> do
+              f     <- newName "f"
+              x     <- newName "y"
+              names <- for fields $ \(n,_,_) -> newName (nameBase n)
+              let expr = appsE 
+                       [ return (VarE 'fmap)
+                       , lamE [varP x] $ appsE $ conE conName : map varE (element i .~ x $ names)
+                       , varE f `appE` varE (names^.element i)
+                       ]
+              clause [varP f, conP conName $ map varP names] (normalB expr) []
+            Nothing -> errorClause
+        _ -> errorClause
 
 -- TODO: When there are constructors with missing fields, turn that field into a _traversal_ not a lens.
 -- TODO: When the supplied mapping function maps multiple different fields to the same name, try to unify them into a Traversal.
diff --git a/src/Control/Lens/Traversal.hs b/src/Control/Lens/Traversal.hs
--- a/src/Control/Lens/Traversal.hs
+++ b/src/Control/Lens/Traversal.hs
@@ -44,6 +44,8 @@
   -- * Common Traversals
   , Traversable(traverse)
   , traverseNothing
+  -- * Cloning Traversals
+  , cloneTraversal
 
   -- * Simple
   , SimpleTraversal
@@ -72,24 +74,21 @@
 -- and the more evocative name suggests their application.
 --
 -- Most of the time the 'Traversal' you will want to use is just 'traverse', but you can also pass any
--- 'Lens' or 'Control.Lens.Iso.Iso' as a Traversal, and composition of a 'Traversal' (or 'Lens' or 'Control.Lens.Iso.Iso') with a 'Traversal' (or 'Lens' or 'Control.Lens.Iso.Iso')
+-- 'Lens' or 'Control.Lens.Iso.Iso' as a 'Traversal', and composition of a 'Traversal' (or 'Lens' or 'Control.Lens.Iso.Iso') with a 'Traversal' (or 'Lens' or 'Control.Lens.Iso.Iso')
 -- using (.) forms a valid 'Traversal'.
 --
 -- The laws for a Traversal @t@ follow from the laws for Traversable as stated in \"The Essence of the Iterator Pattern\".
 --
--- 1) Idiomatic naturality:
---
--- @t 'pure' = 'pure'@
---
--- 2) Sequential composition:
---
--- @'fmap' (t f) . t g = 'Data.Functor.Compose.getCompose' . t ('Data.Functor.Compose.Compose' . 'fmap' f . g)@
---
--- One consequence of this requirement is that a traversal needs to leave the same number of elements as a candidate for
--- subsequent traversal as it started with.
+-- @
+-- t 'pure' = 'pure'
+-- 'fmap' (t f) . t g = 'Data.Functor.Compose.getCompose' . t ('Data.Functor.Compose.Compose' . 'fmap' f . g)
+-- @
 --
--- 3) No duplication of elements (as defined in \"The Essence of the Iterator Pattern\" section 5.5), which states
--- that you should incur no effect caused by visiting the same element of the container twice.
+-- One consequence of this requirement is that a 'Traversal' needs to leave the same number of elements as a
+-- candidate for subsequent 'Traversal' that it started with. Another testament to the strength of these laws
+-- is that the caveat expressed in section 5.5 of the \"Essence of the Iterator Pattern\" about exotic
+-- 'Traversable' instances that 'traverse' the same entry multiple times was actually already ruled out by the
+-- second law in that same paper!
 type Traversal a b c d = forall f. Applicative f => (c -> f d) -> a -> f b
 
 -- | @type SimpleTraversal = 'Simple' 'Traversal'@
@@ -283,7 +282,7 @@
 -- Common Lenses
 ------------------------------------------------------------------------------
 
--- | A 'Lens' to view/edit the nth element 'elementOf' a 'Traversal', 'Lens' or 'Control.Lens.Iso.Iso'.
+-- | A 'Lens' to 'Control.Lens.Getter.view'/'Control.Lens.Setter.set' the nth element 'elementOf' a 'Traversal', 'Lens' or 'Control.Lens.Iso.Iso'.
 --
 -- Attempts to access beyond the range of the 'Traversal' will cause an error.
 --
@@ -317,3 +316,20 @@
 traverseNothing = const pure
 {-# INLINE traverseNothing #-}
 
+------------------------------------------------------------------------------
+-- Cloning Traversals
+------------------------------------------------------------------------------
+
+-- | A traversal is completely characterized by its behavior on the indexed
+-- 'Kleene' store comonad.
+--
+-- Cloning a 'Traversal' is one way to make sure you arent given
+-- something weaker, such as a 'Control.Lens.Traversal.Fold' and can be
+-- used as a way to pass around traversals that have to be monomorphic in @f@.
+--
+-- Note: This only accepts a proper 'Traversal' (or 'Lens').
+--
+-- To clone a 'Lens' as such, use 'cloneLens'
+cloneTraversal :: Applicative f => ((c -> Kleene c d d) -> a -> Kleene c d b) -> (c -> f d) -> a -> f b
+cloneTraversal l f = kleene f . l (More (Done id))
+{-# INLINE cloneTraversal #-}
diff --git a/src/Control/Lens/Tuple.hs b/src/Control/Lens/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Lens/Tuple.hs
@@ -0,0 +1,283 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Lens.Tuple
+-- Copyright   :  (C) 2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  Rank2Types
+--
+-------------------------------------------------------------------------------
+module Control.Lens.Tuple
+  (
+  -- * Tuples
+    Field1(..)
+  , Field2(..)
+  , Field3(..)
+  , Field4(..)
+  , Field5(..)
+  , Field6(..)
+  , Field7(..)
+  , Field8(..)
+  , Field9(..)
+  ) where
+
+import Control.Lens.Type
+import Data.Functor
+
+-- | Provides access to 1st field of a tuple.
+class Field1 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 1st field of a tuple (and possibly change its type).
+  --
+  -- >>> import Control.Lens
+  -- >>> (1,2)^._1
+  -- 1
+  --
+  -- >>> _1 .~ "hello" $ (1,2)
+  -- ("hello",2)
+  --
+  -- This can also be used on larger tuples as well
+  --
+  -- >>> _1 +~ 41 $ (1,2,3,4,5)
+  -- (42,2,3,4,5)
+  --
+  -- @
+  -- _1 :: 'Lens' (a,b) (a',b) a a'
+  -- _1 :: 'Lens' (a,b,c) (a',b,c) a a'
+  -- _1 :: 'Lens' (a,b,c,d) (a',b,c,d) a a'
+  -- ...
+  -- _1 :: 'Lens' (a,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a'
+  -- @
+  _1 :: Lens a b c d
+
+instance Field1 (a,b) (a',b) a a' where
+  _1 k (a,b) = (\a' -> (a',b)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c) (a',b,c) a a' where
+  _1 k (a,b,c) = (\a' -> (a',b,c)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c,d) (a',b,c,d) a a' where
+  _1 k (a,b,c,d) = (\a' -> (a',b,c,d)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c,d,e) (a',b,c,d,e) a a' where
+  _1 k (a,b,c,d,e) = (\a' -> (a',b,c,d,e)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c,d,e,f) (a',b,c,d,e,f) a a' where
+  _1 k (a,b,c,d,e,f) = (\a' -> (a',b,c,d,e,f)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c,d,e,f,g) (a',b,c,d,e,f,g) a a' where
+  _1 k (a,b,c,d,e,f,g) = (\a' -> (a',b,c,d,e,f,g)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c,d,e,f,g,h) (a',b,c,d,e,f,g,h) a a' where
+  _1 k (a,b,c,d,e,f,g,h) = (\a' -> (a',b,c,d,e,f,g,h)) <$> k a
+  {-# INLINE _1 #-}
+
+instance Field1 (a,b,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a' where
+  _1 k (a,b,c,d,e,f,g,h,i) = (\a' -> (a',b,c,d,e,f,g,h,i)) <$> k a
+  {-# INLINE _1 #-}
+
+-- | Provides access to the 2nd field of a tuple
+class Field2 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 2nd field of a tuple
+  --
+  -- >>> import Control.Lens
+  -- >>> _2 .~ "hello" $ (1,(),3,4)
+  -- (1,"hello",3,4)
+  --
+  -- @
+  -- 'Control.Lens.Fold.anyOf' '_2' :: (c -> 'Bool') -> (a, c) -> 'Bool'
+  -- 'Data.Traversable.traverse' '.' '_2' :: ('Applicative' f, 'Data.Traversable.Traversable' t) => (a -> f b) -> t (c, a) -> f (t (c, b))
+  -- 'Control.Lens.Fold.foldMapOf' ('Data.Traversable.traverse' '.' '_2') :: ('Data.Traversable.Traversable' t, 'Data.Monoid.Monoid' m) => (c -> m) -> t (b, c) -> m
+  -- @
+  _2 :: Lens a b c d
+
+instance Field2 (a,b) (a,b') b b' where
+  _2 k (a,b) = (\b' -> (a,b')) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c) (a,b',c) b b' where
+  _2 k (a,b,c) = (\b' -> (a,b',c)) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c,d) (a,b',c,d) b b' where
+  _2 k (a,b,c,d) = (\b' -> (a,b',c,d)) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c,d,e) (a,b',c,d,e) b b' where
+  _2 k (a,b,c,d,e) = (\b' -> (a,b',c,d,e)) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c,d,e,f) (a,b',c,d,e,f) b b' where
+  _2 k (a,b,c,d,e,f) = (\b' -> (a,b',c,d,e,f)) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c,d,e,f,g) (a,b',c,d,e,f,g) b b' where
+  _2 k (a,b,c,d,e,f,g) = (\b' -> (a,b',c,d,e,f,g)) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c,d,e,f,g,h) (a,b',c,d,e,f,g,h) b b' where
+  _2 k (a,b,c,d,e,f,g,h) = (\b' -> (a,b',c,d,e,f,g,h)) <$> k b
+  {-# INLINE _2 #-}
+
+instance Field2 (a,b,c,d,e,f,g,h,i) (a,b',c,d,e,f,g,h,i) b b' where
+  _2 k (a,b,c,d,e,f,g,h,i) = (\b' -> (a,b',c,d,e,f,g,h,i)) <$> k b
+  {-# INLINE _2 #-}
+
+-- | Provides access to the 3rd field of a tuple
+class Field3 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 3rd field of a tuple
+  _3 :: Lens a b c d
+
+instance Field3 (a,b,c) (a,b,c') c c' where
+  _3 k (a,b,c) = (\c' -> (a,b,c')) <$> k c
+  {-# INLINE _3 #-}
+
+instance Field3 (a,b,c,d) (a,b,c',d) c c' where
+  _3 k (a,b,c,d) = (\c' -> (a,b,c',d)) <$> k c
+  {-# INLINE _3 #-}
+
+instance Field3 (a,b,c,d,e) (a,b,c',d,e) c c' where
+  _3 k (a,b,c,d,e) = (\c' -> (a,b,c',d,e)) <$> k c
+  {-# INLINE _3 #-}
+
+instance Field3 (a,b,c,d,e,f) (a,b,c',d,e,f) c c' where
+  _3 k (a,b,c,d,e,f) = (\c' -> (a,b,c',d,e,f)) <$> k c
+  {-# INLINE _3 #-}
+
+instance Field3 (a,b,c,d,e,f,g) (a,b,c',d,e,f,g) c c' where
+  _3 k (a,b,c,d,e,f,g) = (\c' -> (a,b,c',d,e,f,g)) <$> k c
+  {-# INLINE _3 #-}
+
+instance Field3 (a,b,c,d,e,f,g,h) (a,b,c',d,e,f,g,h) c c' where
+  _3 k (a,b,c,d,e,f,g,h) = (\c' -> (a,b,c',d,e,f,g,h)) <$> k c
+  {-# INLINE _3 #-}
+
+instance Field3 (a,b,c,d,e,f,g,h,i) (a,b,c',d,e,f,g,h,i) c c' where
+  _3 k (a,b,c,d,e,f,g,h,i) = (\c' -> (a,b,c',d,e,f,g,h,i)) <$> k c
+  {-# INLINE _3 #-}
+
+-- | Provide access to the 4th field of a tuple
+class Field4 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 4th field of a tuple
+  _4 :: Lens a b c d
+
+instance Field4 (a,b,c,d) (a,b,c,d') d d' where
+  _4 k (a,b,c,d) = (\d' -> (a,b,c,d')) <$> k d
+  {-# INLINE _4 #-}
+
+instance Field4 (a,b,c,d,e) (a,b,c,d',e) d d' where
+  _4 k (a,b,c,d,e) = (\d' -> (a,b,c,d',e)) <$> k d
+  {-# INLINE _4 #-}
+
+instance Field4 (a,b,c,d,e,f) (a,b,c,d',e,f) d d' where
+  _4 k (a,b,c,d,e,f) = (\d' -> (a,b,c,d',e,f)) <$> k d
+  {-# INLINE _4 #-}
+
+instance Field4 (a,b,c,d,e,f,g) (a,b,c,d',e,f,g) d d' where
+  _4 k (a,b,c,d,e,f,g) = (\d' -> (a,b,c,d',e,f,g)) <$> k d
+  {-# INLINE _4 #-}
+
+instance Field4 (a,b,c,d,e,f,g,h) (a,b,c,d',e,f,g,h) d d' where
+  _4 k (a,b,c,d,e,f,g,h) = (\d' -> (a,b,c,d',e,f,g,h)) <$> k d
+  {-# INLINE _4 #-}
+
+instance Field4 (a,b,c,d,e,f,g,h,i) (a,b,c,d',e,f,g,h,i) d d' where
+  _4 k (a,b,c,d,e,f,g,h,i) = (\d' -> (a,b,c,d',e,f,g,h,i)) <$> k d
+  {-# INLINE _4 #-}
+
+-- | Provides access to the 5th field of a tuple
+class Field5 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 5th field of a tuple
+  _5 :: Lens a b c d
+
+instance Field5 (a,b,c,d,e) (a,b,c,d,e') e e' where
+  _5 k (a,b,c,d,e) = (\e' -> (a,b,c,d,e')) <$> k e
+  {-# INLINE _5 #-}
+
+instance Field5 (a,b,c,d,e,f) (a,b,c,d,e',f) e e' where
+  _5 k (a,b,c,d,e,f) = (\e' -> (a,b,c,d,e',f)) <$> k e
+  {-# INLINE _5 #-}
+
+instance Field5 (a,b,c,d,e,f,g) (a,b,c,d,e',f,g) e e' where
+  _5 k (a,b,c,d,e,f,g) = (\e' -> (a,b,c,d,e',f,g)) <$> k e
+  {-# INLINE _5 #-}
+
+instance Field5 (a,b,c,d,e,f,g,h) (a,b,c,d,e',f,g,h) e e' where
+  _5 k (a,b,c,d,e,f,g,h) = (\e' -> (a,b,c,d,e',f,g,h)) <$> k e
+  {-# INLINE _5 #-}
+
+instance Field5 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e',f,g,h,i) e e' where
+  _5 k (a,b,c,d,e,f,g,h,i) = (\e' -> (a,b,c,d,e',f,g,h,i)) <$> k e
+  {-# INLINE _5 #-}
+
+-- | Provides access to the 6th element of a tuple
+class Field6 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 6th field of a tuple
+  _6 :: Lens a b c d
+
+instance Field6 (a,b,c,d,e,f) (a,b,c,d,e,f') f f' where
+  _6 k (a,b,c,d,e,f) = (\f' -> (a,b,c,d,e,f')) <$> k f
+  {-# INLINE _6 #-}
+
+instance Field6 (a,b,c,d,e,f,g) (a,b,c,d,e,f',g) f f' where
+  _6 k (a,b,c,d,e,f,g) = (\f' -> (a,b,c,d,e,f',g)) <$> k f
+  {-# INLINE _6 #-}
+
+instance Field6 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f',g,h) f f' where
+  _6 k (a,b,c,d,e,f,g,h) = (\f' -> (a,b,c,d,e,f',g,h)) <$> k f
+  {-# INLINE _6 #-}
+
+instance Field6 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f',g,h,i) f f' where
+  _6 k (a,b,c,d,e,f,g,h,i) = (\f' -> (a,b,c,d,e,f',g,h,i)) <$> k f
+  {-# INLINE _6 #-}
+
+-- | Provide access to the 7th field of a tuple
+class Field7 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 7th field of a tuple
+  _7 :: Lens a b c d
+
+instance Field7 (a,b,c,d,e,f,g) (a,b,c,d,e,f,g') g g' where
+  _7 k (a,b,c,d,e,f,g) = (\g' -> (a,b,c,d,e,f,g')) <$> k g
+  {-# INLINE _7 #-}
+
+instance Field7 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g',h) g g' where
+  _7 k (a,b,c,d,e,f,g,h) = (\g' -> (a,b,c,d,e,f,g',h)) <$> k g
+  {-# INLINE _7 #-}
+
+instance Field7 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g',h,i) g g' where
+  _7 k (a,b,c,d,e,f,g,h,i) = (\g' -> (a,b,c,d,e,f,g',h,i)) <$> k g
+  {-# INLINE _7 #-}
+
+-- | Provide access to the 8th field of a tuple
+class Field8 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 8th field of a tuple
+  _8 :: Lens a b c d
+
+instance Field8 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g,h') h h' where
+  _8 k (a,b,c,d,e,f,g,h) = (\h' -> (a,b,c,d,e,f,g,h')) <$> k h
+  {-# INLINE _8 #-}
+
+instance Field8 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h',i) h h' where
+  _8 k (a,b,c,d,e,f,g,h,i) = (\h' -> (a,b,c,d,e,f,g,h',i)) <$> k h
+  {-# INLINE _8 #-}
+
+-- | Provides access to the 9th field of a tuple
+class Field9 a b c d | a -> c, b -> d, a d -> b, b c -> a where
+  -- | Access the 9th field of a tuple
+  _9 :: Lens a b c d
+
+instance Field9 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h,i') i i' where
+  _9 k (a,b,c,d,e,f,g,h,i) = (\i' -> (a,b,c,d,e,f,g,h,i')) <$> k i
+  {-# INLINE _9 #-}
diff --git a/src/Control/Lens/Type.hs b/src/Control/Lens/Type.hs
--- a/src/Control/Lens/Type.hs
+++ b/src/Control/Lens/Type.hs
@@ -23,8 +23,8 @@
 --
 -- While a 'Control.Lens.Traversal.Traversal' could be used for
 -- 'Control.Lens.Getter.Getting' like a valid 'Control.Lens.Fold.Fold',
--- it wasn't a valid 'Getter' as Applicative isn't a superclass of
--- 'Gettable'.
+-- it wasn't a valid 'Control.Lens.Getter.Getter' as 'Applicative' wasn't a superclass of
+-- 'Control.Lens.Getter.Gettable'.
 --
 -- 'Functor', however is the superclass of both.
 --
@@ -41,10 +41,10 @@
 -- the 'Functor' part of the 'Applicative' it is supplied.
 --
 -- Every 'Lens' can be used for 'Control.Lens.Getter.Getting' like a valid
--- 'Getter', since 'Functor' is a superclass of 'Control.Lens.Getter.Gettable'
+-- 'Control.Lens.Getter.Getter', since 'Functor' is a superclass of 'Control.Lens.Getter.Gettable'
 --
 -- Since every 'Lens' can be used for 'Control.Lens.Getter.Getting' like a
--- valid 'Getter' it follows that it must view exactly one element in the
+-- valid 'Control.Lens.Getter.Getter' it follows that it must view exactly one element in the
 -- structure.
 --
 -- The lens laws follow from this property and the desire for it to act like
@@ -60,22 +60,6 @@
   , (%%~)
   , (%%=)
 
-  -- * Traversing and Lensing
-  , Focus(..)
-  , Zoom(..)
-
-  -- * Common Lenses
-  -- ** Tuples
-  , Field1(..)
-  , Field2(..)
-  , Field3(..)
-  , Field4(..)
-  , Field5(..)
-  , Field6(..)
-  , Field7(..)
-  , Field8(..)
-  , Field9(..)
-  -- ** Functions
   , resultAt
 
   -- * Lateral Composition
@@ -93,7 +77,7 @@
   , (<||=), (<&&=)
 
   -- * Cloning Lenses
-  , clone
+  , cloneLens
 
   -- * Simplified and In-Progress
   , LensLike
@@ -101,28 +85,11 @@
   , SimpleLens
   , SimpleLensLike
   , SimpleOverloaded
-
   ) where
 
 import Control.Applicative              as Applicative
 import Control.Lens.Internal
-import Control.Lens.Setter
-import Control.Monad
 import Control.Monad.State.Class        as State
-import Control.Monad.Trans.State.Lazy   as Lazy
-import Control.Monad.Trans.State.Strict as Strict
-import Control.Monad.Trans.Writer.Lazy   as Lazy
-import Control.Monad.Trans.Writer.Strict as Strict
-import Control.Monad.Trans.RWS.Lazy   as Lazy
-import Control.Monad.Trans.RWS.Strict as Strict
-import Control.Monad.Trans.Reader
-import Control.Monad.Trans.Cont
-import Control.Monad.Trans.Error
-import Control.Monad.Trans.List
-import Control.Monad.Trans.Identity
-import Control.Monad.Trans.Maybe
-import Data.Functor.Identity
-import Data.Monoid
 
 infixr 4 %%~
 infix  4 %%=
@@ -142,15 +109,15 @@
 --
 -- 1) You get back what you put in:
 --
--- @'view' l ('set' l b a)  = b@
+-- @'Control.Lens.Getter.view' l ('Control.Lens.Setter.set' l b a)  = b@
 --
 -- 2) Putting back what you got doesn't change anything:
 --
--- @'set' l ('view' l a) a  = a@
+-- @'Control.Lens.Setter.set' l ('Control.Lens.Getter.view' l a) a  = a@
 --
 -- 3) Setting twice is the same as setting once:
 --
--- @'set' l c ('set' l b a) = 'set' l c a@
+-- @'Control.Lens.Setter.set' l c ('Control.Lens.Setter.set' l b a) = 'Control.Lens.Setter.set' l c a@
 --
 -- These laws are strong enough that the 4 type parameters of a 'Lens' cannot
 -- vary fully independently. For more on how they interact, read the "Why is
@@ -161,18 +128,15 @@
 -- 'Control.Lens.Traversal.Traversal'.
 --
 -- You can also use a 'Lens' for 'Control.Lens.Getter.Getting' as if it were a
--- 'Control.Lens.Fold.Fold' or 'Getter'.
+-- 'Control.Lens.Fold.Fold' or 'Control.Lens.Getter.Getter'.
 --
 -- Since every lens is a valid 'Control.Lens.Traversal.Traversal', the
 -- traversal laws should also apply to any lenses you create.
 --
--- 1.) Idiomatic naturality:
---
--- @l 'pure' = 'pure'@
---
--- 2.) Sequential composition:
---
--- @'fmap' (l f) . l g = 'Data.Functor.Compose.getCompose' . l ('Data.Functor.Compose.Compose' . 'fmap' f . g)@
+-- @
+-- l 'pure' = 'pure'
+-- 'fmap' (l f) . l g = 'Data.Functor.Compose.getCompose' . l ('Data.Functor.Compose.Compose' . 'fmap' f . g)
+-- @
 --
 -- @type 'Lens' a b c d = forall f. 'Functor' f => 'LensLike' f a b c d@
 type Lens a b c d = forall f. Functor f => (c -> f d) -> a -> f b
@@ -286,156 +250,6 @@
 #endif
 {-# INLINE (%%=) #-}
 
-
--- | This class allows us to use 'focus' on a number of different monad
--- transformers.
-class Focus st where
-  -- | Run a monadic action in a larger context than it was defined in,
-  -- using a 'Simple' 'Lens' or 'Simple' 'Control.Lens.Traversal.Traversal'.
-  --
-  -- This is commonly used to lift actions in a simpler state monad into a
-  -- state monad with a larger state type.
-  --
-  -- When applied to a 'Simple 'Control.Lens.Traversal.Traversal' over
-  -- multiple values, the actions for each target are executed sequentially
-  -- and the results are aggregated monoidally and a monoidal summary
-  -- of the result is given.
-  --
-  -- @
-  -- focus :: 'Monad' m             => 'Simple' 'Control.Lens.Iso.Iso' a b       -> st b m c -> st a m c
-  -- focus :: 'Monad' m             => 'Simple' 'Lens' a b      -> st b m c -> st a m c
-  -- focus :: ('Monad' m, 'Monoid' c) => 'Simple' 'Control.Lens.Traversal.Traversal' a b -> st b m c -> st a m c
-  -- @
-  focus :: Monad m => LensLike (Focusing m c) a a b b -> st b m c -> st a m c
-
-  -- | Like 'focus', but discarding any accumulated results as you go.
-  --
-  -- @
-  -- focus_ :: 'Monad' m             => 'Simple' 'Control.Lens.Iso.Iso' a b       -> st b m c -> st a m ()
-  -- focus_ :: 'Monad' m             => 'Simple' 'Lens' a b      -> st b m c -> st a m ()
-  -- focus_ :: ('Monad' m, 'Monoid' c) => 'Simple' 'Control.Lens.Traversal.Traversal' a b -> st b m c -> st a m ()
-  -- @
-  focus_ :: Monad m => LensLike (Focusing m ()) a a b b -> st b m c -> st a m ()
-
-  -- | A much more limited version of 'focus' that can work with a 'Setter'.
-  setFocus :: Simple Setter a b -> st b Identity c -> st a Identity ()
-
-skip :: a -> ()
-skip _ = ()
-{-# INLINE skip #-}
-
-instance Focus Strict.StateT where
-  focus l m = Strict.StateT $
-    unfocusing . l (Focusing . Strict.runStateT m)
-  {-# INLINE focus #-}
-  focus_ l m = Strict.StateT $
-    unfocusing . l (Focusing . Strict.runStateT (liftM skip m))
-  {-# INLINE focus_ #-}
-  setFocus l m = State.state $
-    (,) () . runIdentity . l (Identity . snd . Strict.runState m)
-
-instance Focus Lazy.StateT where
-  focus l m = Lazy.StateT $
-    unfocusing . l (Focusing . Lazy.runStateT m)
-  {-# INLINE focus #-}
-  focus_ l m = Lazy.StateT $
-    unfocusing . l (Focusing . Lazy.runStateT (liftM skip m))
-  {-# INLINE focus_ #-}
-  setFocus l m = State.state $
-    (,) () . runIdentity . l (Identity . snd . Lazy.runState m)
-  {-# INLINE setFocus #-}
-
-instance Focus ReaderT where
-  focus l m = ReaderT $
-    liftM fst . unfocusing . l (\b -> Focusing $
-      (\c -> (c,b)) `liftM` runReaderT m b)
-  {-# INLINE focus #-}
-  focus_ l m = ReaderT $ \a -> liftM skip $
-    unfocusing $ l (\b -> Focusing $ (\_ -> ((),b)) `liftM` runReaderT m b) a
-  {-# INLINE focus_ #-}
-  setFocus _ _ = return () -- BOOORING
-
--- | This class allows us to use 'zoom' in, changing the State supplied by
--- many different monad transformers. Unlike 'focus' this can change the state
--- of a deeply nested monad transformer. However, also unlike 'focus' it can
--- only be used on an actual 'Lens' or 'Control.Lens.Iso.Iso' and cannot accept
--- a 'Control.Lens.Traversal.Traversal'
-class (MonadState s m, MonadState t n) => Zoom m n s t | m -> s, n -> t, m t -> n, n s -> m where
-  -- | Run a monadic action in a larger state than it was defined in,
-  -- using a 'Simple' 'Lens'.
-  --
-  -- This is commonly used to lift actions in a simpler state monad into a
-  -- state monad with a larger state type.
-  --
-  -- This can be used to edit pretty much any monad transformer stack with a state in it:
-  --
-  -- @
-  -- zoom :: 'Monad' m => 'Simple' 'Lens' a b -> StateT b m c -> StateT a m c
-  -- zoom :: 'Monad' m => 'Simple' 'Lens' a b -> RWST r w b m c -> RWST r w a m c
-  -- zoom :: 'Monad' m => 'Simple' 'Lens' a b -> ErrorT e (RWST r w b m c) -> ErrorT e (RWST r w a m c)
-  -- zoom :: 'Monad' m => 'Simple' 'Lens' a b -> ErrorT e (RWST r w b m c) -> ErrorT e (RWST r w a m c)
-  -- ...
-  -- @
-  zoom :: SimpleLensLike (IndexedStore s s) t s -> m c -> n c
-
-instance Monad m => Zoom (Strict.StateT s m) (Strict.StateT t m) s t where
-  zoom = focus . clone
-  {-# INLINE zoom #-}
-
-instance Monad m => Zoom (Lazy.StateT s m) (Lazy.StateT t m) s t where
-  zoom = focus . clone
-  {-# INLINE zoom #-}
-
-instance Zoom m n s t => Zoom (ReaderT e m) (ReaderT e n) s t where
-  zoom l (ReaderT m) = ReaderT (zoom l . m)
-  {-# INLINE zoom #-}
-
-instance (Monoid w, Zoom m n s t) => Zoom (Strict.WriterT w m) (Strict.WriterT w n) s t where
-  zoom l (Strict.WriterT m) = Strict.WriterT (zoom l m)
-  {-# INLINE zoom #-}
-
-instance (Monoid w, Zoom m n s t) => Zoom (Lazy.WriterT w m) (Lazy.WriterT w n) s t where
-  zoom l (Lazy.WriterT m) = Lazy.WriterT (zoom l m)
-  {-# INLINE zoom #-}
-
-instance (Monoid w, Monad m) => Zoom (Strict.RWST r w s m) (Strict.RWST r w t m) s t where
-  zoom l (Strict.RWST m) = Strict.RWST $ \ r t -> case l (IndexedStore id) t of
-    IndexedStore st s -> do
-      (a,s',w) <- m r s
-      return (a,st s',w)
-  {-# INLINE zoom #-}
-
-instance (Monoid w, Monad m) => Zoom (Lazy.RWST r w s m) (Lazy.RWST r w t m) s t where
-  zoom l (Lazy.RWST m) = Lazy.RWST $ \ r t -> case l (IndexedStore id) t of
-    IndexedStore st s -> do
-      (a,s',w) <- m r s
-      return (a,st s',w)
-  {-# INLINE zoom #-}
-
-instance (Error e, Zoom m n s t) => Zoom (ErrorT e m) (ErrorT e n) s t where
-  zoom l (ErrorT m) = ErrorT (zoom l m)
-  {-# INLINE zoom #-}
-
-instance Zoom m n s t => Zoom (ListT m) (ListT n) s t where
-  zoom l (ListT m) = ListT (zoom l m)
-  {-# INLINE zoom #-}
-
-instance Zoom m n s t => Zoom (IdentityT m) (IdentityT n) s t where
-  zoom l (IdentityT m) = IdentityT (zoom l m)
-  {-# INLINE zoom #-}
-
-instance Zoom m n s t => Zoom (MaybeT m) (MaybeT n) s t where
-  zoom l (MaybeT m) = MaybeT (zoom l m)
-  {-# INLINE zoom #-}
-
-instance Zoom m m a a => Zoom (ContT r m) (ContT r m) a a where
-  zoom l (ContT m) = ContT $ \k -> do
-    f <- State.state $ \s -> case l (IndexedStore id) s of
-      IndexedStore f t -> (f, t)
-    r <- m k
-    State.state $ \t -> (r, f t)
-  {-# INLINE zoom #-}
-
 -------------------------------------------------------------------------------
 -- Common Lenses
 -------------------------------------------------------------------------------
@@ -472,22 +286,20 @@
 -------------------------------------------------------------------------------
 
 -- |
---
 -- Cloning a 'Lens' is one way to make sure you arent given
 -- something weaker, such as a 'Control.Lens.Traversal.Traversal' and can be
 -- used as a way to pass around lenses that have to be monomorphic in @f@.
 --
--- Note: This only accepts a proper 'Lens', because 'IndexedStore' lacks its
--- (admissable) 'Applicative' instance.
+-- Note: This only accepts a proper 'Lens'.
 --
 -- \"Costate Comonad Coalgebra is equivalent of Java's member variable
 -- update technology for Haskell\" -- \@PLT_Borat on Twitter
-clone :: Functor f
+cloneLens :: Functor f
       => LensLike (IndexedStore c d) a b c d
       -> (c -> f d) -> a -> f b
-clone f cfd a = case f (IndexedStore id) a of
+cloneLens f cfd a = case f (IndexedStore id) a of
   IndexedStore db c -> db <$> cfd c
-{-# INLINE clone #-}
+{-# INLINE cloneLens #-}
 
 -------------------------------------------------------------------------------
 -- Overloading function application
@@ -505,28 +317,28 @@
 
 -- | Modify the target of a 'Lens' and return the result
 --
--- When you do not need the result of the addition, ('+~') is more flexible.
+-- When you do not need the result of the addition, ('Control.Lens.Setter.+~') is more flexible.
 (<%~) :: LensLike ((,)d) a b c d -> (c -> d) -> a -> (d, b)
 l <%~ f = l $ \c -> let d = f c in (d, d)
 {-# INLINE (<%~) #-}
 
 -- | Increment the target of a numerically valued 'Lens' and return the result
 --
--- When you do not need the result of the addition, ('+~') is more flexible.
+-- When you do not need the result of the addition, ('Control.Lens.Setter.+~') is more flexible.
 (<+~) :: Num c => LensLike ((,)c) a b c c -> c -> a -> (c, b)
 l <+~ c = l <%~ (+ c)
 {-# INLINE (<+~) #-}
 
 -- | Decrement the target of a numerically valued 'Lens' and return the result
 --
--- When you do not need the result of the subtraction, ('-~') is more flexible.
+-- When you do not need the result of the subtraction, ('Control.Lens.Setter.-~') is more flexible.
 (<-~) :: Num c => LensLike ((,)c) a b c c -> c -> a -> (c, b)
 l <-~ c = l <%~ subtract c
 {-# INLINE (<-~) #-}
 
 -- | Multiply the target of a numerically valued 'Lens' and return the result
 --
--- When you do not need the result of the multiplication, ('*~') is more
+-- When you do not need the result of the multiplication, ('Control.Lens.Setter.*~') is more
 -- flexible.
 (<*~) :: Num c => LensLike ((,)c) a b c c -> c -> a -> (c, b)
 l <*~ c = l <%~ (* c)
@@ -534,7 +346,7 @@
 
 -- | Divide the target of a fractionally valued 'Lens' and return the result.
 --
--- When you do not need the result of the division, ('//~') is more flexible.
+-- When you do not need the result of the division, ('Control.Lens.Setter.//~') is more flexible.
 (<//~) :: Fractional c => LensLike ((,)c) a b c c -> c -> a -> (c, b)
 l <//~ c = l <%~ (/ c)
 {-# INLINE (<//~) #-}
@@ -542,7 +354,7 @@
 -- | Raise the target of a numerically valued 'Lens' to a non-negative
 -- 'Integral' power and return the result
 --
--- When you do not need the result of the division, ('^~') is more flexible.
+-- When you do not need the result of the division, ('Control.Lens.Setter.^~') is more flexible.
 (<^~) :: (Num c, Integral d) => LensLike ((,)c) a b c c -> d -> a -> (c, b)
 l <^~ d = l <%~ (^ d)
 {-# INLINE (<^~) #-}
@@ -550,7 +362,7 @@
 -- | Raise the target of a fractionally valued 'Lens' to an 'Integral' power
 -- and return the result.
 --
--- When you do not need the result of the division, ('^^~') is more flexible.
+-- When you do not need the result of the division, ('Control.Lens.Setter.^^~') is more flexible.
 (<^^~) :: (Fractional c, Integral d) => LensLike ((,)c) a b c c -> d -> a -> (c, b)
 l <^^~ d = l <%~ (^^ d)
 {-# INLINE (<^^~) #-}
@@ -558,21 +370,21 @@
 -- | Raise the target of a floating-point valued 'Lens' to an arbitrary power
 -- and return the result.
 --
--- When you do not need the result of the division, ('**~') is more flexible.
+-- When you do not need the result of the division, ('Control.Lens.Setter.**~') is more flexible.
 (<**~) :: Floating c => LensLike ((,)c) a b c c -> c -> a -> (c, b)
 l <**~ c = l <%~ (** c)
 {-# INLINE (<**~) #-}
 
 -- | Logically '||' a Boolean valued 'Lens' and return the result
 --
--- When you do not need the result of the operation, ('||~') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.||~') is more flexible.
 (<||~) :: LensLike ((,)Bool) a b Bool Bool -> Bool -> a -> (Bool, b)
 l <||~ c = l <%~ (|| c)
 {-# INLINE (<||~) #-}
 
 -- | Logically '&&' a Boolean valued 'Lens' and return the result
 --
--- When you do not need the result of the operation, ('&&~') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.&&~') is more flexible.
 (<&&~) :: LensLike ((,)Bool) a b Bool Bool -> Bool -> a -> (Bool, b)
 l <&&~ c = l <%~ (&& c)
 {-# INLINE (<&&~) #-}
@@ -584,7 +396,7 @@
 -- | Modify the target of a 'Lens' into your monad's state by a user supplied
 -- function and return the result.
 --
--- When you do not need the result of the operation, ('%=') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.%=') is more flexible.
 (<%=) :: MonadState a m => LensLike ((,)d) a a c d -> (c -> d) -> m d
 l <%= f = l %%= (\c -> let d = f c in (d,d))
 {-# INLINE (<%=) #-}
@@ -592,7 +404,7 @@
 -- | Add to the target of a numerically valued 'Lens' into your monad's state
 -- and return the result.
 --
--- When you do not need the result of the multiplication, ('+=') is more
+-- When you do not need the result of the multiplication, ('Control.Lens.Setter.+=') is more
 -- flexible.
 (<+=) :: (MonadState a m, Num b) => SimpleLensLike ((,)b) a b -> b -> m b
 l <+= b = l <%= (+ b)
@@ -601,7 +413,7 @@
 -- | Subtract from the target of a numerically valued 'Lens' into your monad's
 -- state and return the result.
 --
--- When you do not need the result of the multiplication, ('-=') is more
+-- When you do not need the result of the multiplication, ('Control.Lens.Setter.-=') is more
 -- flexible.
 (<-=) :: (MonadState a m, Num b) => SimpleLensLike ((,)b) a b -> b -> m b
 l <-= b = l <%= subtract b
@@ -610,7 +422,7 @@
 -- | Multiply the target of a numerically valued 'Lens' into your monad's
 -- state and return the result.
 --
--- When you do not need the result of the multiplication, ('*=') is more
+-- When you do not need the result of the multiplication, ('Control.Lens.Setter.*=') is more
 -- flexible.
 (<*=) :: (MonadState a m, Num b) => SimpleLensLike ((,)b) a b -> b -> m b
 l <*= b = l <%= (* b)
@@ -619,7 +431,7 @@
 -- | Divide the target of a fractionally valued 'Lens' into your monad's state
 -- and return the result.
 --
--- When you do not need the result of the division, ('//=') is more flexible.
+-- When you do not need the result of the division, ('Control.Lens.Setter.//=') is more flexible.
 (<//=) :: (MonadState a m, Fractional b) => SimpleLensLike ((,)b) a b -> b -> m b
 l <//= b = l <%= (/ b)
 {-# INLINE (<//=) #-}
@@ -627,7 +439,7 @@
 -- | Raise the target of a numerically valued 'Lens' into your monad's state
 -- to a non-negative 'Integral' power and return the result.
 --
--- When you do not need the result of the operation, ('**=') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.**=') is more flexible.
 (<^=) :: (MonadState a m, Num b, Integral c) => SimpleLensLike ((,)b) a b -> c -> m b
 l <^= c = l <%= (^ c)
 {-# INLINE (<^=) #-}
@@ -635,7 +447,7 @@
 -- | Raise the target of a fractionally valued 'Lens' into your monad's state
 -- to an 'Integral' power and return the result.
 --
--- When you do not need the result of the operation, ('^^=') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.^^=') is more flexible.
 (<^^=) :: (MonadState a m, Fractional b, Integral c) => SimpleLensLike ((,)b) a b -> c -> m b
 l <^^= c = l <%= (^^ c)
 {-# INLINE (<^^=) #-}
@@ -643,7 +455,7 @@
 -- | Raise the target of a floating-point valued 'Lens' into your monad's
 -- state to an arbitrary power and return the result.
 --
--- When you do not need the result of the operation, ('**=') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.**=') is more flexible.
 (<**=) :: (MonadState a m, Floating b) => SimpleLensLike ((,)b) a b -> b -> m b
 l <**= b = l <%= (** b)
 {-# INLINE (<**=) #-}
@@ -651,7 +463,7 @@
 -- | Logically '||' a Boolean valued 'Lens' into your monad's state and return
 -- the result.
 --
--- When you do not need the result of the operation, ('||=') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.||=') is more flexible.
 (<||=) :: MonadState a m => SimpleLensLike ((,)Bool) a Bool -> Bool -> m Bool
 l <||= b = l <%= (|| b)
 {-# INLINE (<||=) #-}
@@ -659,258 +471,8 @@
 -- | Logically '&&' a Boolean valued 'Lens' into your monad's state and return
 -- the result.
 --
--- When you do not need the result of the operation, ('&&=') is more flexible.
+-- When you do not need the result of the operation, ('Control.Lens.Setter.&&=') is more flexible.
 (<&&=) :: MonadState a m => SimpleLensLike ((,)Bool) a Bool -> Bool -> m Bool
 l <&&= b = l <%= (&& b)
 {-# INLINE (<&&=) #-}
 
--- | Provides access to 1st field of a tuple.
-class Field1 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 1st field of a tuple (and possibly change its type).
-  --
-  -- >>> import Control.Lens
-  -- >>> (1,2)^._1
-  -- 1
-  --
-  -- >>> _1 .~ "hello" $ (1,2)
-  -- ("hello",2)
-  --
-  -- This can also be used on larger tuples as well
-  --
-  -- >>> _1 +~ 41 $ (1,2,3,4,5)
-  -- (42,2,3,4,5)
-  --
-  -- @
-  -- _1 :: 'Lens' (a,b) (a',b) a a'
-  -- _1 :: 'Lens' (a,b,c) (a',b,c) a a'
-  -- _1 :: 'Lens' (a,b,c,d) (a',b,c,d) a a'
-  -- ...
-  -- _1 :: 'Lens' (a,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a'
-  -- @
-  _1 :: Lens a b c d
-
-instance Field1 (a,b) (a',b) a a' where
-  _1 k (a,b) = (\a' -> (a',b)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c) (a',b,c) a a' where
-  _1 k (a,b,c) = (\a' -> (a',b,c)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c,d) (a',b,c,d) a a' where
-  _1 k (a,b,c,d) = (\a' -> (a',b,c,d)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c,d,e) (a',b,c,d,e) a a' where
-  _1 k (a,b,c,d,e) = (\a' -> (a',b,c,d,e)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c,d,e,f) (a',b,c,d,e,f) a a' where
-  _1 k (a,b,c,d,e,f) = (\a' -> (a',b,c,d,e,f)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c,d,e,f,g) (a',b,c,d,e,f,g) a a' where
-  _1 k (a,b,c,d,e,f,g) = (\a' -> (a',b,c,d,e,f,g)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c,d,e,f,g,h) (a',b,c,d,e,f,g,h) a a' where
-  _1 k (a,b,c,d,e,f,g,h) = (\a' -> (a',b,c,d,e,f,g,h)) <$> k a
-  {-# INLINE _1 #-}
-
-instance Field1 (a,b,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a' where
-  _1 k (a,b,c,d,e,f,g,h,i) = (\a' -> (a',b,c,d,e,f,g,h,i)) <$> k a
-  {-# INLINE _1 #-}
-
--- | Provides access to the 2nd field of a tuple
-class Field2 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 2nd field of a tuple
-  --
-  -- >>> import Control.Lens
-  -- >>> _2 .~ "hello" $ (1,(),3,4)
-  -- (1,"hello",3,4)
-  --
-  -- @
-  -- 'Control.Lens.Fold.anyOf' '_2' :: (c -> 'Bool') -> (a, c) -> 'Bool'
-  -- 'Data.Traversable.traverse' '.' '_2' :: ('Applicative' f, 'Data.Traversable.Traversable' t) => (a -> f b) -> t (c, a) -> f (t (c, b))
-  -- 'Control.Lens.Fold.foldMapOf' ('Data.Traversable.traverse' '.' '_2') :: ('Data.Traversable.Traversable' t, 'Data.Monoid.Monoid' m) => (c -> m) -> t (b, c) -> m
-  -- @
-  _2 :: Lens a b c d
-
-instance Field2 (a,b) (a,b') b b' where
-  _2 k (a,b) = (\b' -> (a,b')) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c) (a,b',c) b b' where
-  _2 k (a,b,c) = (\b' -> (a,b',c)) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c,d) (a,b',c,d) b b' where
-  _2 k (a,b,c,d) = (\b' -> (a,b',c,d)) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c,d,e) (a,b',c,d,e) b b' where
-  _2 k (a,b,c,d,e) = (\b' -> (a,b',c,d,e)) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c,d,e,f) (a,b',c,d,e,f) b b' where
-  _2 k (a,b,c,d,e,f) = (\b' -> (a,b',c,d,e,f)) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c,d,e,f,g) (a,b',c,d,e,f,g) b b' where
-  _2 k (a,b,c,d,e,f,g) = (\b' -> (a,b',c,d,e,f,g)) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c,d,e,f,g,h) (a,b',c,d,e,f,g,h) b b' where
-  _2 k (a,b,c,d,e,f,g,h) = (\b' -> (a,b',c,d,e,f,g,h)) <$> k b
-  {-# INLINE _2 #-}
-
-instance Field2 (a,b,c,d,e,f,g,h,i) (a,b',c,d,e,f,g,h,i) b b' where
-  _2 k (a,b,c,d,e,f,g,h,i) = (\b' -> (a,b',c,d,e,f,g,h,i)) <$> k b
-  {-# INLINE _2 #-}
-
--- | Provides access to the 3rd field of a tuple
-class Field3 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 3rd field of a tuple
-  _3 :: Lens a b c d
-
-instance Field3 (a,b,c) (a,b,c') c c' where
-  _3 k (a,b,c) = (\c' -> (a,b,c')) <$> k c
-  {-# INLINE _3 #-}
-
-instance Field3 (a,b,c,d) (a,b,c',d) c c' where
-  _3 k (a,b,c,d) = (\c' -> (a,b,c',d)) <$> k c
-  {-# INLINE _3 #-}
-
-instance Field3 (a,b,c,d,e) (a,b,c',d,e) c c' where
-  _3 k (a,b,c,d,e) = (\c' -> (a,b,c',d,e)) <$> k c
-  {-# INLINE _3 #-}
-
-instance Field3 (a,b,c,d,e,f) (a,b,c',d,e,f) c c' where
-  _3 k (a,b,c,d,e,f) = (\c' -> (a,b,c',d,e,f)) <$> k c
-  {-# INLINE _3 #-}
-
-instance Field3 (a,b,c,d,e,f,g) (a,b,c',d,e,f,g) c c' where
-  _3 k (a,b,c,d,e,f,g) = (\c' -> (a,b,c',d,e,f,g)) <$> k c
-  {-# INLINE _3 #-}
-
-instance Field3 (a,b,c,d,e,f,g,h) (a,b,c',d,e,f,g,h) c c' where
-  _3 k (a,b,c,d,e,f,g,h) = (\c' -> (a,b,c',d,e,f,g,h)) <$> k c
-  {-# INLINE _3 #-}
-
-instance Field3 (a,b,c,d,e,f,g,h,i) (a,b,c',d,e,f,g,h,i) c c' where
-  _3 k (a,b,c,d,e,f,g,h,i) = (\c' -> (a,b,c',d,e,f,g,h,i)) <$> k c
-  {-# INLINE _3 #-}
-
--- | Provide access to the 4th field of a tuple
-class Field4 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 4th field of a tuple
-  _4 :: Lens a b c d
-
-instance Field4 (a,b,c,d) (a,b,c,d') d d' where
-  _4 k (a,b,c,d) = (\d' -> (a,b,c,d')) <$> k d
-  {-# INLINE _4 #-}
-
-instance Field4 (a,b,c,d,e) (a,b,c,d',e) d d' where
-  _4 k (a,b,c,d,e) = (\d' -> (a,b,c,d',e)) <$> k d
-  {-# INLINE _4 #-}
-
-instance Field4 (a,b,c,d,e,f) (a,b,c,d',e,f) d d' where
-  _4 k (a,b,c,d,e,f) = (\d' -> (a,b,c,d',e,f)) <$> k d
-  {-# INLINE _4 #-}
-
-instance Field4 (a,b,c,d,e,f,g) (a,b,c,d',e,f,g) d d' where
-  _4 k (a,b,c,d,e,f,g) = (\d' -> (a,b,c,d',e,f,g)) <$> k d
-  {-# INLINE _4 #-}
-
-instance Field4 (a,b,c,d,e,f,g,h) (a,b,c,d',e,f,g,h) d d' where
-  _4 k (a,b,c,d,e,f,g,h) = (\d' -> (a,b,c,d',e,f,g,h)) <$> k d
-  {-# INLINE _4 #-}
-
-instance Field4 (a,b,c,d,e,f,g,h,i) (a,b,c,d',e,f,g,h,i) d d' where
-  _4 k (a,b,c,d,e,f,g,h,i) = (\d' -> (a,b,c,d',e,f,g,h,i)) <$> k d
-  {-# INLINE _4 #-}
-
--- | Provides access to the 5th field of a tuple
-class Field5 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 5th field of a tuple
-  _5 :: Lens a b c d
-
-instance Field5 (a,b,c,d,e) (a,b,c,d,e') e e' where
-  _5 k (a,b,c,d,e) = (\e' -> (a,b,c,d,e')) <$> k e
-  {-# INLINE _5 #-}
-
-instance Field5 (a,b,c,d,e,f) (a,b,c,d,e',f) e e' where
-  _5 k (a,b,c,d,e,f) = (\e' -> (a,b,c,d,e',f)) <$> k e
-  {-# INLINE _5 #-}
-
-instance Field5 (a,b,c,d,e,f,g) (a,b,c,d,e',f,g) e e' where
-  _5 k (a,b,c,d,e,f,g) = (\e' -> (a,b,c,d,e',f,g)) <$> k e
-  {-# INLINE _5 #-}
-
-instance Field5 (a,b,c,d,e,f,g,h) (a,b,c,d,e',f,g,h) e e' where
-  _5 k (a,b,c,d,e,f,g,h) = (\e' -> (a,b,c,d,e',f,g,h)) <$> k e
-  {-# INLINE _5 #-}
-
-instance Field5 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e',f,g,h,i) e e' where
-  _5 k (a,b,c,d,e,f,g,h,i) = (\e' -> (a,b,c,d,e',f,g,h,i)) <$> k e
-  {-# INLINE _5 #-}
-
--- | Provides access to the 6th element of a tuple
-class Field6 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 6th field of a tuple
-  _6 :: Lens a b c d
-
-instance Field6 (a,b,c,d,e,f) (a,b,c,d,e,f') f f' where
-  _6 k (a,b,c,d,e,f) = (\f' -> (a,b,c,d,e,f')) <$> k f
-  {-# INLINE _6 #-}
-
-instance Field6 (a,b,c,d,e,f,g) (a,b,c,d,e,f',g) f f' where
-  _6 k (a,b,c,d,e,f,g) = (\f' -> (a,b,c,d,e,f',g)) <$> k f
-  {-# INLINE _6 #-}
-
-instance Field6 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f',g,h) f f' where
-  _6 k (a,b,c,d,e,f,g,h) = (\f' -> (a,b,c,d,e,f',g,h)) <$> k f
-  {-# INLINE _6 #-}
-
-instance Field6 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f',g,h,i) f f' where
-  _6 k (a,b,c,d,e,f,g,h,i) = (\f' -> (a,b,c,d,e,f',g,h,i)) <$> k f
-  {-# INLINE _6 #-}
-
--- | Provide access to the 7th field of a tuple
-class Field7 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 7th field of a tuple
-  _7 :: Lens a b c d
-
-instance Field7 (a,b,c,d,e,f,g) (a,b,c,d,e,f,g') g g' where
-  _7 k (a,b,c,d,e,f,g) = (\g' -> (a,b,c,d,e,f,g')) <$> k g
-  {-# INLINE _7 #-}
-
-instance Field7 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g',h) g g' where
-  _7 k (a,b,c,d,e,f,g,h) = (\g' -> (a,b,c,d,e,f,g',h)) <$> k g
-  {-# INLINE _7 #-}
-
-instance Field7 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g',h,i) g g' where
-  _7 k (a,b,c,d,e,f,g,h,i) = (\g' -> (a,b,c,d,e,f,g',h,i)) <$> k g
-  {-# INLINE _7 #-}
-
--- | Provide access to the 8th field of a tuple
-class Field8 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 8th field of a tuple
-  _8 :: Lens a b c d
-
-instance Field8 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g,h') h h' where
-  _8 k (a,b,c,d,e,f,g,h) = (\h' -> (a,b,c,d,e,f,g,h')) <$> k h
-  {-# INLINE _8 #-}
-
-instance Field8 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h',i) h h' where
-  _8 k (a,b,c,d,e,f,g,h,i) = (\h' -> (a,b,c,d,e,f,g,h',i)) <$> k h
-  {-# INLINE _8 #-}
-
--- | Provides access to the 9th field of a tuple
-class Field9 a b c d | a -> c, b -> d, a d -> b, b c -> a where
-  -- | Access the 9th field of a tuple
-  _9 :: Lens a b c d
-
-instance Field9 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h,i') i i' where
-  _9 k (a,b,c,d,e,f,g,h,i) = (\i' -> (a,b,c,d,e,f,g,h,i')) <$> k i
-  {-# INLINE _9 #-}
diff --git a/src/Control/Lens/Zoom.hs b/src/Control/Lens/Zoom.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Lens/Zoom.hs
@@ -0,0 +1,205 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE LiberalTypeSynonyms #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Lens.Zoom
+-- Copyright   :  (C) 2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  provisional
+-- Portability :  Rank2Types
+--
+-------------------------------------------------------------------------------
+module Control.Lens.Zoom
+  ( Magnify(..)
+  , Zoom(..)
+  ) where
+
+import Control.Lens.Internal
+import Control.Lens.Type
+import Control.Lens.Getter
+import Control.Monad
+import Control.Monad.Reader.Class       as Reader
+import Control.Monad.State.Class        as State
+import Control.Monad.Trans.State.Lazy   as Lazy
+import Control.Monad.Trans.State.Strict as Strict
+import Control.Monad.Trans.Writer.Lazy   as Lazy
+import Control.Monad.Trans.Writer.Strict as Strict
+import Control.Monad.Trans.RWS.Lazy   as Lazy
+import Control.Monad.Trans.RWS.Strict as Strict
+import Control.Monad.Trans.Reader
+import Control.Monad.Trans.Error
+import Control.Monad.Trans.List
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Data.Monoid
+
+-- | This class allows us to use 'zoom' in, changing the State supplied by
+-- many different monad transformers, potentially quite deep in a monad transformer stack.
+class (MonadState s m, MonadState t n) => Zoom m n k s t | m -> s k, n -> t k, m t -> n, n s -> m where
+  -- | Run a monadic action in a larger state than it was defined in,
+  -- using a 'Simple' 'Lens' or 'Simple' 'Control.Lens.Traversal.Traversal'.
+  --
+  -- This is commonly used to lift actions in a simpler state monad into a
+  -- state monad with a larger state type.
+  --
+  -- When applied to a 'Simple 'Control.Lens.Traversal.Traversal' over
+  -- multiple values, the actions for each target are executed sequentially
+  -- and the results are aggregated.
+  --
+  -- This can be used to edit pretty much any monad transformer stack with a state in it!
+  --
+  -- @
+  -- zoom :: 'Monad' m             => 'Simple' 'Lens' a b      -> 'StateT' b m c -> 'StateT' a m c
+  -- zoom :: ('Monad' m, 'Monoid' c) => 'Simple' 'Control.Lens.Traversal.Traversal' a b -> 'StateT' b m c -> 'StateT' a m c
+  -- zoom :: 'Monad' m             => 'Simple' 'Lens' a b      -> 'RWST' r w b m c -> 'RWST' r w a m c
+  -- zoom :: ('Monad' m, 'Monoid' c) => 'Simple' 'Control.Lens.Traversal.Traversal' a b -> 'RWST' r w b m c -> 'RWST' r w a m c
+  -- zoom :: 'Monad' m             => 'Simple' 'Lens' a b      -> 'ErrorT' e ('RWST' r w b m c) -> 'ErrorT' e ('RWST' r w a m c)
+  -- zoom :: ('Monad' m, 'Monoid' c) => 'Simple' 'Control.Lens.Traversal.Traversal' a b -> 'ErrorT' e ('RWST' r w b m c) -> 'ErrorT' e ('RWST' r w a m c)
+  -- ...
+  -- @
+  zoom :: Monad m => SimpleLensLike (k c) t s -> m c -> n c
+
+instance Monad z => Zoom (Strict.StateT s z) (Strict.StateT t z) (Focusing z) s t where
+  zoom l (Strict.StateT m) = Strict.StateT $ unfocusing . l (Focusing . m)
+  {-# INLINE zoom #-}
+
+instance Monad z => Zoom (Lazy.StateT s z) (Lazy.StateT t z) (Focusing z) s t where
+  zoom l (Lazy.StateT m) = Lazy.StateT $ unfocusing . l (Focusing . m)
+  {-# INLINE zoom #-}
+
+instance Zoom m n k s t => Zoom (ReaderT e m) (ReaderT e n) k s t where
+  zoom l (ReaderT m) = ReaderT (zoom l . m)
+  {-# INLINE zoom #-}
+
+instance Zoom m n k s t => Zoom (IdentityT m) (IdentityT n) k s t where
+  zoom l (IdentityT m) = IdentityT (zoom l m)
+  {-# INLINE zoom #-}
+
+instance (Monoid w, Monad z) => Zoom (Strict.RWST r w s z) (Strict.RWST r w t z) (FocusingWith w z) s t where
+  zoom l (Strict.RWST m) = Strict.RWST $ \r -> unfocusingWith . l (FocusingWith . m r)
+  {-# INLINE zoom #-}
+
+instance (Monoid w, Monad z) => Zoom (Lazy.RWST r w s z) (Lazy.RWST r w t z) (FocusingWith w z) s t where
+  zoom l (Lazy.RWST m) = Lazy.RWST $ \r -> unfocusingWith . l (FocusingWith . m r)
+  {-# INLINE zoom #-}
+
+instance (Monoid w, Zoom m n k s t) => Zoom (Strict.WriterT w m) (Strict.WriterT w n) (FocusingPlus w k) s t where
+  zoom l = Strict.WriterT . zoom (\cfd -> unfocusingPlus . l (FocusingPlus  . cfd)) . Strict.runWriterT
+  {-# INLINE zoom #-}
+
+instance (Monoid w, Zoom m n k s t) => Zoom (Lazy.WriterT w m) (Lazy.WriterT w n) (FocusingPlus w k) s t where
+  zoom l = Lazy.WriterT . zoom (\cfd -> unfocusingPlus . l (FocusingPlus  . cfd)) . Lazy.runWriterT
+  {-# INLINE zoom #-}
+
+instance Zoom m n k s t => Zoom (ListT m) (ListT n) (FocusingOn [] k) s t where
+  zoom l = ListT . zoom (\cfd -> unfocusingOn . l (FocusingOn . cfd)) . runListT
+  {-# INLINE zoom #-}
+
+instance Zoom m n k s t => Zoom (MaybeT m) (MaybeT n) (FocusingMay k) s t where
+  zoom l = MaybeT . liftM getMay . zoom (\cfd -> unfocusingMay . l (FocusingMay . cfd)) . liftM May . runMaybeT
+  {-# INLINE zoom #-}
+
+instance (Error e, Zoom m n k s t) => Zoom (ErrorT e m) (ErrorT e n) (FocusingErr e k) s t where
+  zoom l = ErrorT . liftM getErr . zoom (\cfd -> unfocusingErr . l (FocusingErr . cfd)) . liftM Err . runErrorT
+  {-# INLINE zoom #-}
+
+-- TODO: instance Zoom m m k a a => Zoom (ContT r m) (ContT r m) k a a where
+
+
+-- | This class allows us to use 'magnify' part of the environment, changing the environment supplied by
+-- many different monad transformers. Unlike 'focus' this can change the environment of a deeply nested monad transformer.
+--
+-- Also, unlike 'focus', this can be used with any valid 'Getter', but cannot be used with a 'Traversal' or 'Fold'.
+class (MonadReader b m, MonadReader a n) => Magnify m n k b a | m -> b, n -> a, m a -> n, n b -> m where
+  -- | Run a monadic action in a larger environment than it was defined in, using a 'Getter'.
+  --
+  -- This acts like 'Control.Monad.Reader.Class.local', but can in many cases change the type of the environment as well.
+  --
+  -- This is commonly used to lift actions in a simpler Reader monad into a monad with a larger environment type.
+  --
+  -- This can be used to edit pretty much any monad transformer stack with an environment in it:
+  --
+  -- @
+  -- magnify ::             'Getter' a b -> (b -> c) -> a -> c
+  -- magnify :: 'Monoid' c => 'Fold' a b   -> (b -> c) -> a -> c
+  -- magnify :: 'Monoid' w                'Getter' a b -> 'RWST' a w s c -> 'RWST' b w s c
+  -- magnify :: ('Monoid' w, 'Monoid' c) => 'Fold' a b   -> 'RWST' a w s c -> 'RWST' b w s c
+  -- ...
+  -- @
+  magnify :: ((b -> k c b) -> a -> k c a) -> m c -> n c
+
+instance Monad m => Magnify (ReaderT b m) (ReaderT a m) (Effect m) b a where
+  magnify l (ReaderT m) = ReaderT $ getEffect . l (Effect . m)
+  {-# INLINE magnify #-}
+
+-- | @'magnify' = 'views'@
+instance Magnify ((->) b) ((->) a) Accessor b a where
+  magnify = views
+  {-# INLINE magnify #-}
+
+instance (Monad m, Monoid w) => Magnify (Strict.RWST b w s m) (Strict.RWST a w s m) (EffectRWS w s m) b a where
+  magnify l (Strict.RWST m) = Strict.RWST $ getEffectRWS . l (EffectRWS . m)
+  {-# INLINE magnify #-}
+
+instance (Monad m, Monoid w) => Magnify (Lazy.RWST b w s m) (Lazy.RWST a w s m) (EffectRWS w s m) b a where
+  magnify l (Lazy.RWST m) = Lazy.RWST $ getEffectRWS . l (EffectRWS . m)
+  {-# INLINE magnify #-}
+
+instance Magnify m n k b a => Magnify (IdentityT m) (IdentityT n) k b a where
+  magnify l (IdentityT m) = IdentityT (magnify l m)
+  {-# INLINE magnify #-}
+
+{-
+-- | Wrap a monadic effect with a phantom type argument. Used when magnifying StateT.
+newtype EffectS s k c a = EffectS { runEffect :: s -> k (c, s) a }
+
+instance Functor (k (c, s)) => Functor (EffectS s k c) where
+  fmap f (EffectS m) = EffectS (fmap f . m)
+
+
+instance (Monoid c, Monad m) => Applicative (EffectS s k c) where
+  pure _ = EffectS $ \s -> return (mempty, s)
+  EffectS m <*> EffectS n = EffectS $ \s -> m s >>= \ (c,t) -> n s >>= \ (d, u) -> return (mappend c d, u)
+
+
+instance Magnify m n k b a => Magnify (Strict.StateT s m) (Strict.StateT s n) (EffectS s k) b a where
+  magnify l (Strict.StateT m) = Strict.StateT $ magnify l . m
+  {-# INLINE magnify #-}
+
+instance Magnify m n b a => Magnify (Lazy.StateT s m) (Lazy.StateT s n) b a where
+  magnify l (Lazy.StateT m) = Lazy.StateT $ magnify l . m
+  {-# INLINE magnify #-}
+
+instance (Monoid w, Magnify m n b a) => Magnify (Strict.WriterT w m) (Strict.WriterT w n) b a where
+  magnify l (Strict.WriterT m) = Strict.WriterT (magnify l m)
+  {-# INLINE magnify #-}
+
+instance (Monoid w, Magnify m n b a) => Magnify (Lazy.WriterT w m) (Lazy.WriterT w n) b a where
+  magnify l (Lazy.WriterT m) = Lazy.WriterT (magnify l m)
+  {-# INLINE magnify #-}
+
+instance Magnify m n b a => Magnify (ListT m) (ListT n) b a where
+  magnify l (ListT m) = ListT (magnify l m)
+  {-# INLINE magnify #-}
+
+instance Magnify m n b a => Magnify (MaybeT m) (MaybeT n) b a where
+  magnify l (MaybeT m) = MaybeT (magnify l m)
+  {-# INLINE magnify #-}
+
+instance (Error e, Magnify m n b a) => Magnify (ErrorT e m) (ErrorT e n) b a where
+  magnify l (ErrorT m) = ErrorT (magnify l m)
+  {-# INLINE magnify #-}
+
+instance Magnify m m a a => Magnify (ContT r m) (ContT r m) a a where
+  magnify l (ContT m) = ContT $ \k -> do
+    r <- Reader.ask
+    magnify l (m (magnify (to (const r)) . k))
+  {-# INLINE magnify #-}
+-}
diff --git a/src/Data/IntSet/Lens.hs b/src/Data/IntSet/Lens.hs
--- a/src/Data/IntSet/Lens.hs
+++ b/src/Data/IntSet/Lens.hs
@@ -17,6 +17,7 @@
 
 import Control.Applicative
 import Control.Lens
+import Control.Lens.Internal
 import Data.IntSet as IntSet
 
 -- | This 'Lens' can be used to read, write or delete a member of an 'IntSet'
diff --git a/src/Data/Set/Lens.hs b/src/Data/Set/Lens.hs
--- a/src/Data/Set/Lens.hs
+++ b/src/Data/Set/Lens.hs
@@ -15,9 +15,10 @@
   ) where
 
 import Control.Applicative
-import Control.Lens.Type
-import Control.Lens.Setter
 import Control.Lens.Getter
+import Control.Lens.Internal
+import Control.Lens.Setter
+import Control.Lens.Type
 import Data.Set as Set
 
 -- | This 'Lens' can be used to read, write or delete a member of a 'Set'
diff --git a/src/Language/Haskell/TH/Lens.hs b/src/Language/Haskell/TH/Lens.hs
--- a/src/Language/Haskell/TH/Lens.hs
+++ b/src/Language/Haskell/TH/Lens.hs
@@ -20,6 +20,7 @@
   , SubstType(..)
   , typeVars      -- :: HasTypeVars t => Simple Traversal t Name
   , substTypeVars -- :: HasTypeVars t => Map Name Name -> t -> t
+  , conFields
   ) where
 
 import Control.Applicative
@@ -34,6 +35,7 @@
 import Data.Set as Set hiding (toList,map)
 import Data.Set.Lens
 import Language.Haskell.TH
+import Language.Haskell.TH.Syntax
 
 -- | Has a 'Name'
 class HasName t where
@@ -111,3 +113,11 @@
 instance SubstType Pred where
   substType m (ClassP n ts) = ClassP n (substType m ts)
   substType m (EqualP l r)  = substType m (EqualP l r)
+
+-- | Provides a 'Traversal' of the types of each field of a constructor.
+conFields :: Simple Traversal Con StrictType
+conFields f (NormalC n tys)     = NormalC n <$> traverse f tys
+conFields f (RecC n tys)        = RecC n <$> traverse sans_var tys
+  where sans_var (fn,s,t) = (\(s', t') -> (fn,s',t')) <$> f (s, t)
+conFields f (InfixC l n r)      = InfixC <$> f l <*> pure n <*> f r
+conFields f (ForallC bds ctx c) = ForallC bds ctx <$> conFields f c
diff --git a/src/System/FilePath/Lens.hs b/src/System/FilePath/Lens.hs
new file mode 100644
--- /dev/null
+++ b/src/System/FilePath/Lens.hs
@@ -0,0 +1,158 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.FilePath.Lens
+-- Copyright   :  (C) 2012 Edward Kmett
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+-- Stability   :  experimental
+-- Portability :  Rank2Types
+--
+----------------------------------------------------------------------------
+module System.FilePath.Lens
+  ( (</>~), (<</>~), (<.>~), (<<.>~)
+  , (</>=), (<</>=), (<.>=), (<<.>=)
+  , _basename, _directory, _extension, _filename
+  ) where
+
+import Control.Applicative ((<$>))
+
+import Control.Monad.State.Class as State
+import System.FilePath ((</>), (<.>), splitExtension, takeBaseName, takeDirectory, takeExtension, takeFileName)
+
+import Control.Lens hiding ((<.>))
+
+
+infixr 4 </>~, <</>~, <.>~, <<.>~
+infix 4 </>=, <</>=, <.>=, <<.>=
+
+
+-- | Modify the path by adding another path.
+--
+-- >>> :m + Control.Lens Data.Pair.Lens
+-- >>> both </>~ "!!!" $ ("hello","world")
+-- ("hello/!!!","world/!!!")
+--
+-- @
+-- (</>~) :: 'Setter' a b 'FilePath' 'FilePath' -> 'FilePath' -> a -> b
+-- (</>~) :: 'Iso' a b 'FilePath' 'FilePath' -> 'FilePath' -> a -> b
+-- (</>~) :: 'Lens' a b 'FilePath' 'FilePath' -> 'FilePath' -> a -> b
+-- (</>~) :: 'Traversal' a b 'FilePath' 'FilePath' -> 'FilePath' -> a -> b
+-- @
+(</>~) :: Setting a b FilePath FilePath -> FilePath -> a -> b
+l </>~ n = over l (</> n)
+{-# INLINE (</>~) #-}
+
+
+-- | Modify the target(s) of a 'Simple' 'Lens', 'Iso', 'Setter' or 'Traversal' by adding a path.
+--
+-- @
+-- (</>=) :: 'MonadState' a m => 'Simple' 'Setter' a 'FilePath' -> 'FilePath' -> m ()
+-- (</>=) :: 'MonadState' a m => 'Simple' 'Iso' a 'FilePath' -> 'FilePath' -> m ()
+-- (</>=) :: 'MonadState' a m => 'Simple' 'Lens' a 'FilePath' -> 'FilePath' -> m ()
+-- (</>=) :: 'MonadState' a m => 'Simple' 'Traversal' a 'FilePath' -> 'FilePath' -> m ()
+-- @
+(</>=) :: MonadState a m => SimpleSetting a FilePath -> FilePath -> m ()
+l </>= b = State.modify (l </>~ b)
+{-# INLINE (</>=) #-}
+
+
+-- | Add a path onto the end of the target of a 'Lens' and return the result
+--
+-- When you do not need the result of the operation, ('</>~') is more flexible.
+(<</>~) :: LensLike ((,)FilePath) a b FilePath FilePath -> FilePath -> a -> (FilePath, b)
+l <</>~ m = l <%~ (</> m)
+{-# INLINE (<</>~) #-}
+
+
+-- | Add a path onto the end of the target of a 'Lens' into
+-- your monad's state and return the result.
+--
+-- When you do not need the result of the operation, ('</>=') is more flexible.
+(<</>=) :: MonadState a m => SimpleLensLike ((,)FilePath) a FilePath -> FilePath -> m FilePath
+l <</>= r = l <%= (</> r)
+{-# INLINE (<</>=) #-}
+
+
+-- | Modify the path by adding extension.
+--
+-- >>> :m + Control.Lens Data.Pair.Lens
+-- >>> both <.>~ "!!!" $ ("hello","world")
+-- ("hello.!!!","world.!!!")
+--
+-- @
+-- (</>~) :: 'Setter' a b 'FilePath' 'FilePath' -> 'String' -> a -> b
+-- (</>~) :: 'Iso' a b 'FilePath' 'FilePath' -> 'String' -> a -> b
+-- (</>~) :: 'Lens' a b 'FilePath' 'FilePath' -> 'String' -> a -> b
+-- (</>~) :: 'Traversal' a b 'FilePath' 'FilePath' -> 'String' -> a -> b
+-- @
+(<.>~) :: Setting a b FilePath FilePath -> String -> a -> b
+l <.>~ n = over l (<.> n)
+{-# INLINE (<.>~) #-}
+
+
+-- | Modify the target(s) of a 'Simple' 'Lens', 'Iso', 'Setter' or 'Traversal' by adding an extension.
+--
+-- @
+-- (<.>=) :: 'MonadState' a m => 'Simple' 'Setter' a 'FilePath' -> 'String' -> m ()
+-- (<.>=) :: 'MonadState' a m => 'Simple' 'Iso' a 'FilePath' -> 'String' -> m ()
+-- (<.>=) :: 'MonadState' a m => 'Simple' 'Lens' a 'FilePath' -> 'String' -> m ()
+-- (<.>=) :: 'MonadState' a m => 'Simple' 'Traversal' a 'FilePath' -> 'String' -> m ()
+-- @
+(<.>=) :: MonadState a m => SimpleSetting a FilePath -> String -> m ()
+l <.>= b = State.modify (l <.>~ b)
+{-# INLINE (<.>=) #-}
+
+
+-- | Add an extension onto the end of the target of a 'Lens' and return the result
+--
+-- When you do not need the result of the operation, ('<.>~') is more flexible.
+(<<.>~) :: LensLike ((,)FilePath) a b FilePath FilePath -> String -> a -> (FilePath, b)
+l <<.>~ m = l <%~ (<.> m)
+{-# INLINE (<<.>~) #-}
+
+
+-- | Add an extension onto the end of the target of a 'Lens' into
+-- your monad's state and return the result.
+--
+-- When you do not need the result of the operation, ('<.>=') is more flexible.
+(<<.>=) :: MonadState a m => SimpleLensLike ((,)FilePath) a FilePath -> String -> m FilePath
+l <<.>= r = l <%= (<.> r)
+{-# INLINE (<<.>=) #-}
+
+
+-- | A lens reading and writing to the basename.
+--
+-- >>> _basename .~ "filename" $ "path/name.png"
+-- "path/filename.png"
+_basename :: Simple Lens FilePath FilePath
+_basename f p = (<.> takeExtension p) . (takeDirectory p </>) <$> f (takeBaseName p)
+{-# INLINE _basename #-}
+
+
+-- | A lens reading and writing to the directory.
+--
+-- >>> "long/path/name.txt" ^. _directory
+-- "long/path"
+_directory :: Simple Lens FilePath FilePath
+_directory f p = (</> takeFileName p) <$> f (takeDirectory p)
+{-# INLINE _directory #-}
+
+
+-- | A lens reading and writing to the extension.
+--
+-- >>> _extension .~ ".png" $ "path/name.txt"
+-- "path/name.png"
+_extension :: Simple Lens FilePath FilePath
+_extension f p = (n <.>) <$> f e
+ where
+  (n, e) = splitExtension p
+{-# INLINE _extension #-}
+
+
+-- | A lens reading and writing to the full filename.
+--
+-- >>> _filename .~ "name.txt" $ "path/name.png"
+-- "path/name.txt"
+_filename :: Simple Lens FilePath FilePath
+_filename f p = (takeDirectory p </>) <$> f (takeFileName p)
+{-# INLINE _filename #-}
diff --git a/tests/templates.hs b/tests/templates.hs
--- a/tests/templates.hs
+++ b/tests/templates.hs
@@ -20,7 +20,7 @@
 -- quartz :: Lens (Quux a b) (Quux a' b') Double Double
 
 data Quark a = Qualified  { _gaffer :: a }
-             | Unqualified { _gaffer :: a, tape :: a }
+             | Unqualified { _gaffer :: a, _tape :: a }
 makeLenses ''Quark
 -- gaffer :: Simple Lens (Quark a) a
 
