diff --git a/lens.cabal b/lens.cabal
--- a/lens.cabal
+++ b/lens.cabal
@@ -1,6 +1,6 @@
 name:          lens
 category:      Data, Lenses
-version:       0.8
+version:       0.9
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -33,17 +33,19 @@
     containers       >= 0.3   && < 0.6,
     mtl              >= 2.1.1 && < 2.2,
     template-haskell >= 2.4   && < 2.8,
+    text             == 0.11.*,
     transformers     >= 0.2   && < 0.4
 
   other-extensions:
     CPP
+    LiberalTypeSynonyms
     Rank2Types
     RankNTypes
     TemplateHaskell
 
   if (impl(ghc>=7.4))
     other-extensions:
-      Safe Trustworthy
+      Trustworthy
 
   ghc-options: -Wall -fwarn-tabs -O2 -fdicts-cheap -funbox-strict-fields
   hs-source-dirs: src
diff --git a/src/Control/Lens.hs b/src/Control/Lens.hs
--- a/src/Control/Lens.hs
+++ b/src/Control/Lens.hs
@@ -1,9 +1,5 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE LiberalTypeSynonyms #-}
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704
-{-# LANGUAGE Safe #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Lens
@@ -13,7 +9,6 @@
 -- Stability   :  provisional
 -- Portability :  Rank2Types
 --
---
 -- This package provides lens families, setters, getters, traversals and folds that
 -- can all be composed automatically with each other (and other lenses from
 -- other van Laarhoven lens libraries) using @(.)@ from Prelude, while
@@ -53,6 +48,7 @@
   (
   -- * Lenses
     Lens
+  , LensLike
 
   -- * "Simple" Lenses
   , Simple
@@ -64,6 +60,7 @@
 
   -- * Getters
   , Getter
+  , Getting
   , to
 
   -- ** Getting Values
@@ -97,18 +94,29 @@
   , containsInt
   , identity
   , resultAt
+  , real
+  , imaginary
+  , polarize
 
   -- * Folds
   , Fold
 
   -- ** Common Folds
   , folded
-  , folding
+  , filtered
+  , reversed
 
   -- ** Fold Combinators
   , foldMapOf
-  , foldrOf
   , foldOf
+  , foldrOf
+  , foldlOf
+  , foldrOf'
+  , foldlOf'
+  , foldr1Of
+  , foldl1Of
+  , foldrMOf
+  , foldlMOf
   , toListOf
   , anyOf
   , allOf
@@ -128,6 +136,13 @@
   , concatOf
   , elemOf
   , notElemOf
+  , lengthOf
+  , nullOf
+  , maximumOf
+  , minimumOf
+  , maximumByOf
+  , minimumByOf
+  , findOf
 
   -- * Traversals
   , Traversal
@@ -148,14 +163,17 @@
   , traverseElements
 
   , TraverseByteString(..)
+  , TraverseText(..)
 
   , TraverseValueAtMin(..)
   , TraverseValueAtMax(..)
 
   , traverseBits
+  , traverseDynamic
+  , traverseException
 
   -- ** Traversal Combinators
-  -- , traverseOf
+  , traverseOf
   , mapMOf
   , sequenceAOf
   , sequenceOf
@@ -165,6 +183,7 @@
   ) where
 
 import           Control.Applicative              as Applicative
+import           Control.Exception                as Exception
 import           Control.Lens.Internal
 import           Control.Monad (liftM, MonadPlus(..))
 import           Control.Monad.State.Class
@@ -174,15 +193,21 @@
 import           Data.Bits
 import           Data.ByteString.Lazy             as Lazy
 import           Data.ByteString                  as Strict
+import           Data.Complex
+import           Data.Dynamic
 import           Data.Foldable                    as Foldable
 import           Data.Functor.Identity
 import           Data.IntMap                      as IntMap hiding (adjust)
 import           Data.IntSet                      as IntSet
 import           Data.Map                         as Map    hiding (adjust)
+import           Data.Maybe
 import           Data.Monoid
 import           Data.Sequence                    as Seq    hiding (adjust)
 import           Data.Set                         as Set
+import           Data.Text                        as StrictText
+import           Data.Text.Lazy                   as LazyText
 import           Data.Traversable
+import           Data.Tree
 import           Data.Word (Word8)
 
 infixl 8 ^.
@@ -209,6 +234,8 @@
 --
 -- > identity :: Lens (Identity a) (Identity b) a b
 -- > identity f (Identity a) = Identity <$> f a
+
+-- > type Lens = forall f. Functor f => Traversing f a b c d
 type Lens a b c d = forall f. Functor f => (c -> f d) -> a -> f b
 
 -- | A @'Simple' 'Lens'@, @'Simple' 'Setter'@, or @'Simple' 'Traversal'@ can be used instead of a 'Lens' 'Setter' or 'Traversal' 
@@ -220,6 +247,16 @@
 -- > traverseHead :: Simple Traversal [a] a
 type Simple f a b = f a a b b
 
+-- |
+-- Many combinators that accept a 'Lens' can also accept a 'Traversal' in limited situations.
+--
+-- They do so by specializing the type of 'Functor' that they require of the caller.
+--
+-- If a function accepts a @'LensLike' f a b c d@ for some 'Functor' @f@, then they may be passed a 'Lens'.
+--
+-- Further, if @f@ is an 'Applicative', they may also be passed a 'Traversal'.
+type LensLike f a b c d = (c -> f d) -> a -> f b
+
 --------------------------
 -- Constructing Lenses
 --------------------------
@@ -252,6 +289,8 @@
 --
 -- In practice the @b@ and @d@ are left dangling and unused, and as such is no real point in
 -- using a @'Simple' 'Getter'@.
+--
+-- type Getter a b c d = forall z. LensLike (Const z) a b c d
 type Getter a b c d = forall z. (c -> Const z d) -> a -> Const z b
 
 -- | Build a 'Getter'
@@ -261,6 +300,17 @@
 to f g a = Const (getConst (g (f a)))
 {-# INLINE to #-}
 
+-- |
+-- Most 'Getter' combinators are able to be used with both a 'Getter' or a 'Fold' in
+-- limited situations, to do so, they need to be monomorphic in what we are going to
+-- extract with 'Const'.
+--
+-- If a function accepts a @Getting r a b c d@, then when @r@ is a Monoid, you can
+-- pass a 'Fold' (or 'Traversal'), otherwise you can only pass this a 'Getter' or 'Lens'.
+--
+-- > type Getting r a b c d = LensLike (Const r) a b c d
+type Getting r a b c d = (c -> Const r d) -> a -> Const r b
+
 -------------------------------
 -- Getting Values
 -------------------------------
@@ -274,7 +324,9 @@
 -- > view ::             Getter a b c d    -> a -> c
 -- > view :: Monoid m => Fold a b m d      -> a -> m
 -- > view :: Monoid m => Traversal a b m d -> a -> m
-view :: ((c -> Const c d) -> a -> Const c b) -> a -> c
+--
+-- > view :: ((c -> Const c d) -> a -> Const c b) -> a -> c
+view :: Getting c a b c d -> a -> c
 view l a = getConst (l Const a)
 {-# INLINE view #-}
 
@@ -287,7 +339,9 @@
 -- > views ::             Lens a b c d      -> (c -> d) -> a -> d
 -- > views :: Monoid m => Fold a b c d      -> (c -> m) -> a -> m
 -- > views :: Monoid m => Traversal a b c d -> (c -> m) -> a -> m
-views :: ((c -> Const m d) -> a -> Const m b) -> (c -> m) -> a -> m
+--
+-- > views :: ((c -> Const m d) -> a -> Const m b) -> (c -> m) -> a -> m
+views :: Getting m a b c d -> (c -> m) -> a -> m
 views l f = getConst . l (Const . f)
 {-# INLINE views #-}
 
@@ -300,7 +354,9 @@
 -- > (^$) ::             Getter a b c d    -> a -> c
 -- > (^$) :: Monoid m => Fold a b m d      -> a -> m
 -- > (^$) :: Monoid m => Traversal a b m d -> a -> m
-(^$) :: ((c -> Const c d) -> a -> Const c b) -> a -> c
+--
+-- > (^$) :: ((c -> Const c d) -> a -> Const c b) -> a -> c
+(^$) :: Getting c a b c d -> a -> c
 l ^$ a = getConst (l Const a)
 {-# INLINE (^$) #-}
 
@@ -315,11 +371,13 @@
 -- > ghci> ((0, 1 :+ 2), 3)^._1._2.to magnitude
 -- > 2.23606797749979
 --
--- > (^$) ::             a -> Lens a b c d      -> c
--- > (^$) ::             a -> Getter a b c d    -> c
--- > (^$) :: Monoid m => a -> Fold a b m d      -> m
--- > (^$) :: Monoid m => a -> Traversal a b m d -> m
-(^.) :: a -> ((c -> Const c d) -> a -> Const c b) -> c
+-- > (^.) ::             a -> Lens a b c d      -> c
+-- > (^.) ::             a -> Getter a b c d    -> c
+-- > (^.) :: Monoid m => a -> Fold a b m d      -> m
+-- > (^.) :: Monoid m => a -> Traversal a b m d -> m
+--
+-- > (^.) :: a -> ((c -> Const c d) -> a -> Const c b) -> c
+(^.) :: a -> Getting c a b c d -> c
 a ^. l = getConst (l Const a)
 {-# INLINE (^.) #-}
 
@@ -336,6 +394,8 @@
 --
 -- You can compose a 'Setter' with a 'Lens' or a 'Traversal' using @(.)@ from the Prelude
 -- and the result is always only a 'Setter' and nothing more.
+--
+-- > type Setter a b c d = LensLike Identity a b c d
 type Setter a b c d = (c -> Identity d) -> a -> Identity b
 
 -- | This setter can be used to map over all of the values in a container.
@@ -343,6 +403,7 @@
 mapped = sets fmap
 {-# INLINE mapped #-}
 
+
 -- | Build a Setter
 --
 -- > sets . adjust = id
@@ -360,8 +421,6 @@
 --
 -- > sets . adjust = id
 -- > adjust . sets = id
---
--- > adjust :: ((c -> Identity d) -> a -> Identity b) -> (c -> d) -> a -> b
 adjust :: Setter a b c d -> (c -> d) -> a -> b
 adjust l f a = runIdentity (l (Identity . f) a)
 {-# INLINE adjust #-}
@@ -370,8 +429,6 @@
 -- or 'Traversal' with a constant value.
 --
 -- > (<$) = set traverse
---
--- > set :: ((c -> Identity d) -> a -> Identity b) -> d -> a -> b
 set :: Setter a b c d -> d -> a -> b
 set l d a = runIdentity (l (\_ -> Identity d) a)
 {-# INLINE set #-}
@@ -382,8 +439,6 @@
 -- This is an infix version of 'adjust'
 --
 -- > fmap f = traverse =%= f
---
--- > (=%=) :: ((c -> Identity d) -> a -> Identity b) -> (c -> d) -> a -> b
 (=%=) :: Setter a b c d -> (c -> d) -> a -> b
 l =%= f = runIdentity . l (Identity . f)
 {-# INLINE (=%=) #-}
@@ -394,8 +449,6 @@
 -- This is an infix version of 'set'
 --
 -- > f <$ a = traverse =~= f $ a
---
--- > (=~=) :: ((c -> Identity d) -> a -> Identity b) -> d -> a -> b
 (=~=) :: Setter a b c d -> d -> a -> b
 l =~= v = runIdentity . l (Identity . const v)
 {-# INLINE (=~=) #-}
@@ -404,8 +457,6 @@
 --
 -- > ghci> _1 =+= 1 $ (1,2)
 -- > (2,2)
---
--- > (=+=) :: Num c => ((c -> Identity c) -> a -> Identity b) -> c -> a -> b
 (=+=) :: Num c => Setter a b c c -> c -> a -> b
 l =+= n = adjust l (+ n)
 {-# INLINE (=+=) #-}
@@ -414,8 +465,6 @@
 --
 -- > ghci> _2 =*= 4 $ (1,2)
 -- > (1,8)
---
--- > (=*=) :: Num c => ((c -> Identity c) -> a -> Identity b) -> c -> a -> b
 (=*=) :: Num c => Setter a b c c -> c -> a -> b
 l =*= n = adjust l (* n)
 {-# INLINE (=*=) #-}
@@ -424,42 +473,30 @@
 --
 -- > ghci> _1 =-= 2 $ (1,2)
 -- > (-1,2)
---
--- > (=-=) :: ((c -> Identity c) -> a -> Identity b) -> c -> a -> b
 (=-=) :: Num c => Setter a b c c -> c -> a -> b
 l =-= n = adjust l (subtract n)
 {-# INLINE (=-=) #-}
 
 -- | Divide the target(s) of a numerically valued 'Lens', 'Setter' or 'Traversal'
---
--- > (=/=) :: Fractional c => ((c -> Identity c) -> a -> Identity b) -> c -> a -> b
 (=/=) :: Fractional c => Setter a b c c -> c -> a -> b
 l =/= n = adjust l (/ n)
 
 -- | Logically '||' the target(s) of a 'Bool'-valued 'Lens' or 'Setter'
---
--- > (=||=):: ((Bool -> Identity Bool) -> a -> Identity b) -> Bool -> a -> b
 (=||=):: Setter a b Bool Bool -> Bool -> a -> b
 l =||= n = adjust l (|| n)
 {-# INLINE (=||=) #-}
 
 -- | Logically '&&' the target(s) of a 'Bool'-valued 'Lens' or 'Setter'
---
--- (=&&=) :: ((Bool -> Identity Bool) -> a -> Identity b) -> Bool -> a -> b
 (=&&=) :: Setter a b Bool Bool -> Bool -> a -> b
 l =&&= n = adjust l (&& n)
 {-# INLINE (=&&=) #-}
 
 -- | Bitwise '.|.' the target(s) of a 'Bool'-valued 'Lens' or 'Setter'
---
--- > (=|=):: Bits c => ((c -> Identity c) -> a -> Identity b) -> Bool -> a -> b
 (=|=):: Bits c => Setter a b c c -> c -> a -> b
 l =|= n = adjust l (.|. n)
 {-# INLINE (=|=) #-}
 
 -- | Bitwise '.&.' the target(s) of a 'Bool'-valued 'Lens' or 'Setter'
---
--- > (=&=) :: Bits c => ((b -> Identity b) -> a -> Identity a) -> c -> a -> b
 (=&=) :: Bits c => Setter a b c c -> c -> a -> b
 l =&= n = adjust l (.&. n)
 {-# INLINE (=&=) #-}
@@ -566,6 +603,28 @@
            | otherwise = a
 {-# INLINE resultAt #-}
 
+-- | Access the real part of a complex number
+--
+-- > real :: Functor f => (a -> f a) -> Complex a -> f (Complex a)
+real :: Simple Lens (Complex a) a
+real f (a :+ b) = (:+ b) <$> f a
+
+-- | Access the imaginary part of a complex number
+--
+-- > imaginary :: Functor f => (a -> f a) -> Complex a -> f (Complex a)
+imaginary :: Simple Lens (Complex a) a
+imaginary f (a :+ b) = (a :+) <$> f b
+
+-- | This isn't /quite/ a legal lens. Notably the @view l (set l b a) = b@ law
+-- is violated when you set a polar value with 0 magnitude and non-zero phase
+-- as the phase information is lost.
+--
+-- So don't do that. Otherwise this is a perfectly convenient lens.
+--
+-- polarize :: Functor f => ((a,a) -> f (a,a)) -> Complex a -> f (Complex a)
+polarize :: RealFloat a => Simple Lens (Complex a) (a,a)
+polarize f c = uncurry mkPolar <$> f (polar c)
+
 ------------------------------------------------------------------------------
 -- State
 ------------------------------------------------------------------------------
@@ -578,7 +637,9 @@
 -- > access :: MonadState a m             => Lens a b c d      -> m c
 -- > access :: (MonadState a m, Monoid c) => Fold a b c d      -> m c
 -- > access :: (MonadState a m, Monoid c) => Traversal a b c d -> m c
-access :: MonadState a m => ((c -> Const c d) -> a -> Const c b) -> m c
+--
+-- > access :: MonadState a m => ((c -> Const c d) -> a -> Const c b) -> m c
+access :: MonadState a m => Getting c a b c d -> m c
 access l = gets (^. l)
 {-# INLINE access #-}
 
@@ -593,12 +654,15 @@
   -- and a monoidal summary
   -- of the result is given.
   --
-  -- > focus :: Monad m => Simple Lens 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 Traversal a b -> st b m c -> st a m c
-  focus :: Monad m => ((b -> Focusing m c b) -> a -> Focusing m c a) -> 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
 
-  -- | 'focus', discarding any accumulated results as you go.
-  focus_ :: Monad m => ((b -> Focusing m () b) -> a -> Focusing m () a) -> st b m c -> st a m ()
+  -- | Like 'focus', but discarding any accumulated results as you go.
+  --
+  -- > focus_ :: Monad m             => Simple Lens a b      -> st b m c -> st a m ()
+  -- > focus_ :: (Monad m, Monoid c) => Simple 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 ()
 
 skip :: a -> ()
 skip _ = ()
@@ -629,9 +693,11 @@
 -- It may be useful to think of '(%%=)', instead, as having either of the following more restricted
 -- type signatures:
 --
--- > (%%=) :: MonadState a m => Simple Lens a b -> (b -> (c, b) -> m c
+-- > (%%=) :: MonadState a m             => Simple Lens a b      -> (b -> (c, b) -> m c
 -- > (%%=) :: (MonadState a m, Monoid c) => Simple Traversal a b -> (b -> (c, b) -> m c
-(%%=) :: MonadState a m => ((b -> (c,b)) -> a -> (c,a)) -> (b -> (c, b)) -> m c
+--
+-- > (%%=) :: MonadState a m => ((b -> (c,b)) -> a -> (c,a)) -> (b -> (c, b)) -> m c
+(%%=) :: MonadState a m => LensLike ((,) c) a a b b -> (b -> (c, b)) -> m c
 l %%= f = state (l f)
 {-# INLINE (%%=) #-}
 
@@ -704,18 +770,25 @@
 -- there are no lens laws that can be applied to it.
 --
 -- In practice the @b@ and @d@ are left dangling and unused, and as such is no real point in a @'Simple' 'Fold'@.
+--
+-- > type Fold a b c d = forall m. Monoid m => Getting m a b c d
 type Fold a b c d      = forall m. Monoid m => (c -> Const m d) -> a -> Const m b
 
--- | Building a Fold
-folding :: Foldable f => (a -> f c) -> Fold a b c d
-folding f g a = Const (foldMap (getConst . g) (f a))
-{-# INLINE folding #-}
-
 -- | Obtain a 'Fold' from any 'Foldable'
 folded :: Foldable f => Fold (f c) b c d
-folded = folding id
+folded g = Const . foldMap (getConst . g)
 {-# INLINE folded #-}
 
+-- | Obtain a 'Fold' by filtering a 'Lens', 'Getter, 'Fold' or 'Traversal'.
+filtered :: Monoid m => (c -> Bool) -> Getting m a b c d -> Getting m a b c d
+filtered p l f = l (\c -> if p c then f c else Const mempty)
+
+-- | Obtain a 'Fold' by reversing the order of traversal for a 'Lens', 'Getter', 'Fold' or 'Traversal'.
+--
+-- Of course, reversing a 'Fold' or 'Getter' has no effect.
+reversed :: Getting (Dual m) a b c d -> Getting m a b c d
+reversed l f = Const . getDual . getConst . l (Const .  Dual . getConst . f)
+
 --------------------------
 -- Fold/Getter combinators
 --------------------------
@@ -729,7 +802,7 @@
 -- > foldMapOf ::             Lens a b c d      -> (c -> m) -> a -> m
 -- > foldMapOf :: Monoid m => Fold a b c d      -> (c -> m) -> a -> m
 -- > foldMapOf :: Monoid m => Traversal a b c d -> (c -> m) -> a -> m
-foldMapOf :: ((c -> Const m d) -> a -> Const m b) -> (c -> m) -> a -> m
+foldMapOf :: Getting m a b c d -> (c -> m) -> a -> m
 foldMapOf l f = getConst . l (Const . f)
 {-# INLINE foldMapOf #-}
 
@@ -742,29 +815,131 @@
 -- > foldOf ::             Lens a b m d      -> a -> m
 -- > foldOf :: Monoid m => Fold a b m d      -> a -> m
 -- > foldOf :: Monoid m => Traversal a b m d -> a -> m
-foldOf :: ((m -> Const m d) -> a -> Const m b) -> a -> m
+foldOf :: Getting m a b m d -> a -> m
 foldOf l = getConst . l Const
 {-# INLINE foldOf #-}
 
 -- |
+-- Right-associative fold of parts of a structure that are viewed through a 'Lens', 'Getter', 'Fold' or 'Traversal'.
+--
 -- > foldr = foldrOf folded
 --
 -- > foldrOf :: Getter a b c d    -> (c -> e -> e) -> e -> a -> e
 -- > foldrOf :: Lens a b c d      -> (c -> e -> e) -> e -> a -> e
 -- > foldrOf :: Fold a b c d      -> (c -> e -> e) -> e -> a -> e
 -- > foldrOf :: Traversal a b c d -> (c -> e -> e) -> e -> a -> e
-foldrOf :: ((c -> Const (Endo e) d) -> a -> Const (Endo e) b) -> (c -> e -> e) -> e -> a -> e
+foldrOf :: Getting (Endo e) a b c d -> (c -> e -> e) -> e -> a -> e
 foldrOf l f z t = appEndo (foldMapOf l (Endo . f) t) z
 {-# INLINE foldrOf #-}
 
 -- |
+-- Left-associative fold of the parts of a structure that are viewed through a 'Lens', 'Getter', 'Fold' or 'Traversal'.
+--
+-- > foldl = foldlOf folded
+--
+-- > foldlOf :: Getter a b c d    -> (e -> c -> e) -> e -> a -> e
+-- > foldlOf :: Lens a b c d      -> (e -> c -> e) -> e -> a -> e
+-- > foldlOf :: Fold a b c d      -> (e -> c -> e) -> e -> a -> e
+-- > foldlOf :: Traversal a b c d -> (e -> c -> e) -> e -> a -> e
+foldlOf :: Getting (Dual (Endo e)) a b c d -> (e -> c -> e) -> e -> a -> e
+foldlOf l f z t = appEndo (getDual (foldMapOf l (Dual . Endo . flip f) t)) z
+{-# INLINE foldlOf #-}
+
+-- |
+-- A variant of 'foldrOf' that has no base case and thus may only be applied to lenses and structures 
+-- such that the lens views at least one element of the structure.
+--
+-- > foldr1Of l f = Prelude.foldr1 f . toListOf l
+--
+-- > foldr1 = foldr1Of folded
+--
+-- > foldr1Of :: Getter a b c d    -> (c -> c -> c) -> a -> c
+-- > foldr1Of :: Lens a b c d      -> (c -> c -> c) -> a -> c
+-- > foldr1Of :: Fold a b c d      -> (c -> c -> c) -> a -> c
+-- > foldr1Of :: Traversal a b c d -> (c -> c -> c) -> a -> c
+foldr1Of :: Getting (Endo (Maybe c)) a b c d -> (c -> c -> c) -> a -> c
+foldr1Of l f xs = fromMaybe (error "foldr1Of: empty structure") (foldrOf l mf Nothing xs) where
+  mf x Nothing = Just x
+  mf x (Just y) = Just (f x y)
+{-# INLINE foldr1Of #-}
+
+-- | A variant of 'foldlOf' that has no base case and thus may only be applied to lenses and strutures such
+-- that the lens views at least one element of the structure.
+--
+-- > foldl1Of l f = Prelude.foldl1Of l f . toList
+--
+-- > foldl1 = foldl1Of folded
+--
+-- > foldl1Of :: Getter a b c d    -> (c -> c -> c) -> a -> c
+-- > foldl1Of :: Lens a b c d      -> (c -> c -> c) -> a -> c
+-- > foldl1Of :: Fold a b c d      -> (c -> c -> c) -> a -> c
+-- > foldl1Of :: Traversal a b c d -> (c -> c -> c) -> a -> c
+foldl1Of :: Getting (Dual (Endo (Maybe c))) a b c d -> (c -> c -> c) -> a -> c
+foldl1Of l f xs = fromMaybe (error "foldl1Of: empty structure") (foldlOf l mf Nothing xs) where
+  mf Nothing y = Just y
+  mf (Just x) y = Just (f x y)
+{-# INLINE foldl1Of #-}
+
+-- | Strictly fold right over the elements of a structure.
+--
+-- > foldr' = foldrOf' folded
+--
+-- > foldrOf' :: Getter a b c d    -> (c -> e -> e) -> e -> a -> e
+-- > foldrOf' :: Lens a b c d      -> (c -> e -> e) -> e -> a -> e
+-- > foldrOf' :: Fold a b c d      -> (c -> e -> e) -> e -> a -> e
+-- > foldrOf' :: Traversal a b c d -> (c -> e -> e) -> e -> a -> e
+foldrOf' :: Getting (Dual (Endo (e -> e))) a b c d -> (c -> e -> e) -> e -> a -> e
+foldrOf' l f z0 xs = foldlOf l f' id xs z0
+  where f' k x z = k $! f x z
+{-# INLINE foldrOf' #-}
+
+-- | Fold over the elements of a structure, associating to the left, but strictly.
+--
+-- > foldl' = foldlOf' folded
+--
+-- > foldlOf' :: Getter a b c d    -> (e -> c -> e) -> e -> a -> e
+-- > foldlOf' :: Lens a b c d      -> (e -> c -> e) -> e -> a -> e
+-- > foldlOf' :: Fold a b c d      -> (e -> c -> e) -> e -> a -> e
+-- > foldlOf' :: Traversal a b c d -> (e -> c -> e) -> e -> a -> e
+foldlOf' :: Getting (Endo (e -> e)) a b c d -> (e -> c -> e) -> e -> a -> e
+foldlOf' l f z0 xs = foldrOf l f' id xs z0
+  where f' x k z = k $! f z x
+{-# INLINE foldlOf' #-}
+
+-- | Monadic fold over the elements of a structure, associating to the right, i.e. from right to left.
+--
+-- > foldrM = foldrMOf folded
+--
+-- > foldrMOf :: Monad m => Getter a b c d    -> (c -> e -> m e) -> e -> a -> m e
+-- > foldrMOf :: Monad m => Lens a b c d      -> (c -> e -> m e) -> e -> a -> m e
+-- > foldrMOf :: Monad m => Fold a b c d      -> (c -> e -> m e) -> e -> a -> m e
+-- > foldrMOf :: Monad m => Traversal a b c d -> (c -> e -> m e) -> e -> a -> m e
+foldrMOf :: Monad m => Getting (Dual (Endo (e -> m e))) a b c d -> (c -> e -> m e) -> e -> a -> m e
+foldrMOf l f z0 xs = foldlOf l f' return xs z0
+  where f' k x z = f x z >>= k
+{-# INLINE foldrMOf #-}
+
+-- | Monadic fold over the elements of a structure, associating to the left, i.e. from left to right.
+--
+-- > foldlM = foldlMOf folded
+--
+-- > foldlMOf :: Monad m => Getter a b c d    -> (e -> c -> m e) -> e -> a -> m e
+-- > foldlMOf :: Monad m => Lens a b c d      -> (e -> c -> m e) -> e -> a -> m e
+-- > foldlMOf :: Monad m => Fold a b c d      -> (e -> c -> m e) -> e -> a -> m e
+-- > foldlMOf :: Monad m => Traversal a b c d -> (e -> c -> m e) -> e -> a -> m e
+foldlMOf :: Monad m => Getting (Endo (e -> m e)) a b c d -> (e -> c -> m e) -> e -> a -> m e
+foldlMOf l f z0 xs = foldrOf l f' return xs z0
+  where f' x k z = f z x >>= k
+{-# INLINE foldlMOf #-}
+
+-- |
 -- > toList = toListOf folded
 --
 -- > toListOf :: Getter a b c d    -> a -> [c]
 -- > toListOf :: Lens a b c d      -> a -> [c]
 -- > toListOf :: Fold a b c d      -> a -> [c]
 -- > toListOf :: Traversal a b c d -> a -> [c]
-toListOf :: ((c -> Const [c] d) -> a -> Const [c] b) -> a -> [c]
+toListOf :: Getting [c] a b c d -> a -> [c]
 toListOf l = foldMapOf l return
 {-# INLINE toListOf #-}
 
@@ -775,7 +950,7 @@
 -- > andOf :: Lens a b Bool d     -> a -> Bool
 -- > andOf :: Fold a b Bool d     -> a -> Bool
 -- > andOf :: Traversl a b Bool d -> a -> Bool
-andOf :: ((Bool -> Const All d) -> a -> Const All b) -> a -> Bool
+andOf :: Getting All a b Bool d -> a -> Bool
 andOf l = getAll . foldMapOf l All
 {-# INLINE andOf #-}
 
@@ -786,7 +961,7 @@
 -- > orOf :: Lens a b Bool d      -> a -> Bool
 -- > orOf :: Fold a b Bool d      -> a -> Bool
 -- > orOf :: Traversal a b Bool d -> a -> Bool
-orOf :: ((Bool -> Const Any d) -> a -> Const Any b) -> a -> Bool
+orOf :: Getting Any a b Bool d -> a -> Bool
 orOf l = getAny . foldMapOf l Any
 {-# INLINE orOf #-}
 
@@ -797,7 +972,7 @@
 -- > anyOf :: Lens a b c d      -> (c -> Bool) -> a -> Bool
 -- > anyOf :: Fold a b c d      -> (c -> Bool) -> a -> Bool
 -- > anyOf :: Traversal a b c d -> (c -> Bool) -> a -> Bool
-anyOf :: ((c -> Const Any d) -> a -> Const Any b) -> (c -> Bool) -> a -> Bool
+anyOf :: Getting Any a b c d -> (c -> Bool) -> a -> Bool
 anyOf l f = getAny . foldMapOf l (Any . f)
 {-# INLINE anyOf #-}
 
@@ -808,7 +983,7 @@
 -- > allOf :: Lens a b c d      -> (c -> Bool) -> a -> Bool
 -- > allOf :: Fold a b c d      -> (c -> Bool) -> a -> Bool
 -- > allOf :: Traversal a b c d -> (c -> Bool) -> a -> Bool
-allOf :: ((c -> Const All d) -> a -> Const All b) -> (c -> Bool) -> a -> Bool
+allOf :: Getting All a b c d -> (c -> Bool) -> a -> Bool
 allOf l f = getAll . foldMapOf l (All . f)
 {-# INLINE allOf #-}
 
@@ -819,7 +994,7 @@
 -- > productOf ::          Lens a b c d      -> a -> c
 -- > productOf :: Num c => Fold a b c d      -> a -> c
 -- > productOf :: Num c => Traversal a b c d -> a -> c
-productOf :: ((c -> Const (Product c) d) -> a -> Const (Product c) b) -> a -> c
+productOf :: Getting (Product c) a b c d -> a -> c
 productOf l = getProduct . foldMapOf l Product
 {-# INLINE productOf #-}
 
@@ -833,7 +1008,7 @@
 -- > sumOf ::          Lens a b c d      -> a -> c
 -- > sumOf :: Num c => Fold a b c d      -> a -> c
 -- > sumOf :: Num c => Traversal a b c d -> a -> c
-sumOf ::  ((c -> Const (Sum c) d) -> a -> Const (Sum c) b) -> a -> c
+sumOf :: Getting (Sum c) a b c d -> a -> c
 sumOf l = getSum . foldMapOf l Sum
 {-# INLINE sumOf #-}
 
@@ -854,7 +1029,7 @@
 -- > traverseOf_ :: Functor f     => Lens a b c d      -> (c -> f e) -> a -> f ()
 -- > traverseOf_ :: Applicative f => Fold a b c d      -> (c -> f e) -> a -> f ()
 -- > traverseOf_ :: Applicative f => Traversal a b c d -> (c -> f e) -> a -> f ()
-traverseOf_ :: Functor f => ((c -> Const (Traversed f) d) -> a -> Const (Traversed f) b) -> (c -> f e) -> a -> f ()
+traverseOf_ :: Functor f => Getting (Traversed f) a b c d -> (c -> f e) -> a -> f ()
 traverseOf_ l f = getTraversed . foldMapOf l (Traversed . (() <$) . f)
 {-# INLINE traverseOf_ #-}
 
@@ -865,7 +1040,7 @@
 -- > forOf_ :: Functor f     => Lens a b c d      -> a -> (c -> f e) -> f ()
 -- > forOf_ :: Applicative f => Fold a b c d      -> a -> (c -> f e) -> f ()
 -- > forOf_ :: Applicative f => Traversal a b c d -> a -> (c -> f e) -> f ()
-forOf_ :: Functor f => ((c -> Const (Traversed f) d) -> a -> Const (Traversed f) b) -> a -> (c -> f e) -> f ()
+forOf_ :: Functor f => Getting (Traversed f) a b c d -> a -> (c -> f e) -> f ()
 forOf_ l a f = traverseOf_ l f a
 {-# INLINE forOf_ #-}
 
@@ -876,7 +1051,7 @@
 -- > sequenceAOf_ :: Functor f     => Lens a b (f ()) d      -> a -> f ()
 -- > sequenceAOf_ :: Applicative f => Fold a b (f ()) d      -> a -> f ()
 -- > sequenceAOf_ :: Applicative f => Traversal a b (f ()) d -> a -> f ()
-sequenceAOf_ :: Functor f => ((f () -> Const (Traversed f) d) -> a -> Const (Traversed f) b) -> a -> f ()
+sequenceAOf_ :: Functor f => Getting (Traversed f) a b (f ()) d -> a -> f ()
 sequenceAOf_ l = getTraversed . foldMapOf l (Traversed . (() <$))
 {-# INLINE sequenceAOf_ #-}
 
@@ -887,7 +1062,7 @@
 -- > mapMOf_ :: Monad m => Lens a b c d      -> (c -> m e) -> a -> m ()
 -- > mapMOf_ :: Monad m => Fold a b c d      -> (c -> m e) -> a -> m ()
 -- > mapMOf_ :: Monad m => Traversal a b c d -> (c -> m e) -> a -> m ()
-mapMOf_ :: Monad m => ((c -> Const (Traversed (WrappedMonad m)) d) -> a -> Const (Traversed (WrappedMonad m)) b) -> (c -> m e) -> a -> m ()
+mapMOf_ :: Monad m => Getting (Traversed (WrappedMonad m)) a b c d -> (c -> m e) -> a -> m ()
 mapMOf_ l f = unwrapMonad . traverseOf_ l (WrapMonad . f)
 {-# INLINE mapMOf_ #-}
 
@@ -898,7 +1073,7 @@
 -- > forMOf_ :: Monad m => Lens a b c d      -> a -> (c -> m e) -> m ()
 -- > forMOf_ :: Monad m => Fold a b c d      -> a -> (c -> m e) -> m ()
 -- > forMOf_ :: Monad m => Traversal a b c d -> a -> (c -> m e) -> m ()
-forMOf_ :: Monad m => ((c -> Const (Traversed (WrappedMonad m)) d) -> a -> Const (Traversed (WrappedMonad m)) b) -> a -> (c -> m e) -> m ()
+forMOf_ :: Monad m => Getting (Traversed (WrappedMonad m)) a b c d -> a -> (c -> m e) -> m ()
 forMOf_ l a f = mapMOf_ l f a
 {-# INLINE forMOf_ #-}
 
@@ -909,7 +1084,7 @@
 -- > sequenceOf_ :: Monad m => Lens a b (m b) d      -> a -> m ()
 -- > sequenceOf_ :: Monad m => Fold a b (m b) d      -> a -> m ()
 -- > sequenceOf_ :: Monad m => Traversal a b (m b) d -> a -> m ()
-sequenceOf_ :: Monad m => ((m c -> Const (Traversed (WrappedMonad m)) d) -> a -> Const (Traversed (WrappedMonad m)) b) -> a -> m ()
+sequenceOf_ :: Monad m => Getting (Traversed (WrappedMonad m)) a b (m c) d -> a -> m ()
 sequenceOf_ l = unwrapMonad . traverseOf_ l WrapMonad
 {-# INLINE sequenceOf_ #-}
 
@@ -921,7 +1096,7 @@
 -- > asumOf :: Alternative f => Lens a b c d      -> a -> f c
 -- > asumOf :: Alternative f => Fold a b c d      -> a -> f c
 -- > asumOf :: Alternative f => Traversal a b c d -> a -> f c
-asumOf :: Alternative f => ((f c -> Const (Endo (f c)) d) -> a -> Const (Endo (f c)) b) -> a -> f c
+asumOf :: Alternative f => Getting (Endo (f c)) a b (f c) d -> a -> f c
 asumOf l = foldrOf l (<|>) Applicative.empty
 {-# INLINE asumOf #-}
 
@@ -933,7 +1108,7 @@
 -- > msumOf :: MonadPlus m => Lens a b c d      -> a -> m c
 -- > msumOf :: MonadPlus m => Fold a b c d      -> a -> m c
 -- > msumOf :: MonadPlus m => Traversal a b c d -> a -> m c
-msumOf :: MonadPlus m => ((m c -> Const (Endo (m c)) d) -> a -> Const (Endo (m c)) b) -> a -> m c
+msumOf :: MonadPlus m => Getting (Endo (m c)) a b (m c) d -> a -> m c
 msumOf l = foldrOf l mplus mzero
 {-# INLINE msumOf #-}
 
@@ -944,7 +1119,7 @@
 -- > elemOf :: Eq c => Lens a b c d      -> c -> a -> Bool
 -- > elemOf :: Eq c => Fold a b c d      -> c -> a -> Bool
 -- > elemOf :: Eq c => Traversal a b c d -> c -> a -> Bool
-elemOf :: Eq c => ((c -> Const Any d) -> a -> Const Any b) -> c -> a -> Bool
+elemOf :: Eq c => Getting Any a b c d -> c -> a -> Bool
 elemOf l = anyOf l . (==)
 {-# INLINE elemOf #-}
 
@@ -955,18 +1130,18 @@
 -- > notElemOf :: Eq c => Fold a b c d      -> c -> a -> Bool
 -- > notElemOf :: Eq c => Lens a b c d      -> c -> a -> Bool
 -- > notElemOf :: Eq c => Traversal a b c d -> c -> a -> Bool
-notElemOf :: Eq c => ((c -> Const Any d) -> a -> Const Any b) -> c -> a -> Bool
-notElemOf l c = not . elemOf l c
+notElemOf :: Eq c => Getting All a b c d -> c -> a -> Bool
+notElemOf l = allOf l . (/=)
 {-# INLINE notElemOf #-}
 
 -- |
 -- > concatMap = concatMapOf folded
 --
--- > concatMapOf :: Getter a b c d     -> (c -> [e]) -> a -> [e]
+-- > concatMapOf :: Getter a b c d    -> (c -> [e]) -> a -> [e]
 -- > concatMapOf :: Lens a b c d      -> (c -> [e]) -> a -> [e]
 -- > concatMapOf :: Fold a b c d      -> (c -> [e]) -> a -> [e]
 -- > concatMapOf :: Traversal a b c d -> (c -> [e]) -> a -> [e]
-concatMapOf :: ((c -> Const [e] d) -> a -> Const [e] b) -> (c -> [e]) -> a -> [e]
+concatMapOf :: Getting [e] a b c d -> (c -> [e]) -> a -> [e]
 concatMapOf l ces a = getConst  (l (Const . ces) a)
 {-# INLINE concatMapOf #-}
 
@@ -977,10 +1152,117 @@
 -- > concatOf :: Lens a b [e] d -> a -> [e]
 -- > concatOf :: Fold a b [e] d -> a -> [e]
 -- > concatOf :: a b [e] d -> a -> [e]
-concatOf :: (([e] -> Const [e] d) -> a -> Const [e] b) -> a -> [e]
+concatOf :: Getting [e] a b [e] d -> a -> [e]
 concatOf = view
 {-# INLINE concatOf #-}
 
+-- |
+-- Note: this can be rather inefficient for large containers.
+--
+-- > length = lengthOf folded
+--
+-- > lengthOf _1 :: (a, b) -> Int
+-- > lengthOf _1 = 1
+-- > lengthOf (folded.folded) :: Foldable f => f (g a) -> Int
+--
+-- > lengthOf :: Getter a b c d    -> a -> Int
+-- > lengthOf :: Lens a b c d      -> a -> Int
+-- > lengthOf :: Fold a b c d      -> a -> Int
+-- > lengthOf :: Traversal a b c d -> a -> Int
+lengthOf :: Getting (Sum Int) a b c d -> a -> Int
+lengthOf l = getSum . foldMapOf l (\_ -> Sum 1)
+{-# INLINE lengthOf #-}
+
+-- |
+-- Returns 'True' if this 'Fold' or 'Traversal' has no targets in the given container.
+--
+--
+-- Note: nullOf on a valid 'Lens' or 'Getter' will always return 'False'
+--
+-- > null = nullOf folded
+--
+-- This may be rather inefficient compared to the 'null' check of many containers.
+--
+-- > nullOf _1 :: (a, b) -> Int
+-- > nullOf _1 = False
+-- > nullOf (folded._1.folded) :: Foldable f => f (g a, b) -> Bool
+--
+-- > nullOf :: Getter a b c d    -> a -> Bool
+-- > nullOf :: Lens a b c d      -> a -> Bool
+-- > nullOf :: Fold a b c d      -> a -> Bool
+-- > nullOf :: Traversal a b c d -> a -> Bool
+nullOf :: Getting All a b c d -> a -> Bool
+nullOf l = getAll . foldMapOf l (\_ -> All False)
+{-# INLINE nullOf #-}
+
+-- |
+-- Obtain the maximum element (if any) targeted by a 'Fold' or 'Traversal'
+--
+-- Note: maximumOf on a valid 'Lens' or 'Getter' will always return 'Just' a value.
+--
+-- > maximum = fromMaybe (error "empty") . maximumOf folded
+--
+-- > maximumOf ::          Getter a b c d    -> a -> Maybe c
+-- > maximumOf ::          Lens a b c d      -> a -> Maybe c
+-- > maximumOf :: Ord c => Fold a b c d      -> a -> Maybe c
+-- > maximumOf :: Ord c => Traversal a b c d -> a -> Maybe c
+maximumOf :: Getting (Max c) a b c d -> a -> Maybe c
+maximumOf l = getMax . foldMapOf l Max
+{-# INLINE maximumOf #-}
+
+
+-- |
+-- Obtain the minimum element (if any) targeted by a 'Fold' or 'Traversal'
+--
+-- Note: minimumOf on a valid 'Lens' or 'Getter' will always return 'Just' a value.
+--
+-- > minimum = fromMaybe (error "empty") . minimumOf folded
+--
+-- > minimumOf ::          Getter a b c d    -> a -> Maybe c
+-- > minimumOf ::          Lens a b c d      -> a -> Maybe c
+-- > minimumOf :: Ord c => Fold a b c d      -> a -> Maybe c
+-- > minimumOf :: Ord c => Traversal a b c d -> a -> Maybe c
+minimumOf :: Getting (Min c) a b c d -> a -> Maybe c
+minimumOf l = getMin . foldMapOf l Min
+{-# INLINE minimumOf #-}
+
+-- |
+-- Obtain the maximum element (if any) targeted by a 'Fold', 'Traversal', 'Lens'
+-- or 'Getter' according to a user supplied ordering.
+--
+-- > maximumBy cmp = fromMaybe (error "empty") . maximumByOf folded cmp
+--
+-- > maximumByOf :: Getter a b c d    -> (c -> c -> Ordering) -> a -> Maybe c
+-- > maximumByOf :: Lens a b c d      -> (c -> c -> Ordering) -> a -> Maybe c
+-- > maximumByOf :: Fold a b c d      -> (c -> c -> Ordering) -> a -> Maybe c
+-- > maximumByOf :: Traversal a b c d -> (c -> c -> Ordering) -> a -> Maybe c
+maximumByOf :: Getting (Endo (Maybe c)) a b c d -> (c -> c -> Ordering) -> a -> Maybe c
+maximumByOf l cmp = foldrOf l step Nothing where
+  step a Nothing  = Just a
+  step a (Just b) = Just (if cmp a b == GT then a else b)
+
+-- |
+-- Obtain the minimum element (if any) targeted by a 'Fold', 'Traversal', 'Lens'
+-- or 'Getter' according to a user supplied ordering.
+--
+-- > minimumBy cmp = fromMaybe (error "empty") . minimumByOf folded cmp
+--
+-- > minimumByOf :: Getter a b c d    -> (c -> c -> Ordering) -> a -> Maybe c
+-- > minimumByOf :: Lens a b c d      -> (c -> c -> Ordering) -> a -> Maybe c
+-- > minimumByOf :: Fold a b c d      -> (c -> c -> Ordering) -> a -> Maybe c
+-- > minimumByOf :: Traversal a b c d -> (c -> c -> Ordering) -> a -> Maybe c
+minimumByOf :: Getting (Endo (Maybe c)) a b c d -> (c -> c -> Ordering) -> a -> Maybe c
+minimumByOf l cmp = foldrOf l step Nothing where
+  step a Nothing  = Just a
+  step a (Just b) = Just (if cmp a b == GT then b else a)
+
+
+-- | The 'findOf' function takes a lens, a predicate and a structure and returns
+-- the leftmost element of the structure matching the predicate, or
+-- 'Nothing' if there is no such element.
+findOf :: Getting (First c) a b c d -> (c -> Bool) -> a -> Maybe c
+findOf l p = getFirst . foldMapOf l (\c -> if p c then First (Just c) else First Nothing)
+
 ------------------------------------------------------------------------------
 -- Traversals
 ------------------------------------------------------------------------------
@@ -999,12 +1281,19 @@
 -- Traversal combinators
 --------------------------
 
+-- | Provided for completeness, but this is just the identity function.
+--
+-- > traverseOf = id
+-- > traverse = traverseOf traverse
+traverseOf :: LensLike f a b c d -> (c -> f d) -> a -> f b
+traverseOf = id
+
 -- |
 -- > mapM = mapMOf traverse
 --
 -- > mapMOf :: Monad m => Lens a b c d      -> (c -> m d) -> a -> m b
 -- > mapMOf :: Monad m => Traversal a b c d -> (c -> m d) -> a -> m b
-mapMOf :: ((c -> WrappedMonad m d) -> a -> WrappedMonad m b) -> (c -> m d) -> a -> m b
+mapMOf :: LensLike (WrappedMonad m) a b c d -> (c -> m d) -> a -> m b
 mapMOf l cmd a = unwrapMonad (l (WrapMonad . cmd) a)
 {-# INLINE mapMOf #-}
 
@@ -1013,7 +1302,7 @@
 --
 -- > sequenceAOf :: Applicative f => Lens a b (f c) (f c)      -> a -> f b
 -- > sequenceAOf :: Applicative f => Traversal a b (f c) (f c) -> a -> f b
-sequenceAOf :: Applicative f => ((f c -> f (f c)) -> a -> f b) -> a -> f b
+sequenceAOf :: Applicative f => LensLike f a b (f c) (f c) -> a -> f b
 sequenceAOf l = l pure
 {-# INLINE sequenceAOf #-}
 
@@ -1022,20 +1311,20 @@
 --
 -- > sequenceOf :: Monad m => Lens a b (m c) (m c)      -> a -> m b
 -- > sequenceOf :: Monad m => Traversal a b (m c) (m c) -> a -> m b
-sequenceOf :: Monad m => ((m c -> WrappedMonad m (m c)) -> a -> WrappedMonad m b) -> a -> m b
+sequenceOf :: Monad m => LensLike (WrappedMonad m) a b (m c) (m c) -> a -> m b
 sequenceOf l = unwrapMonad . l pure
 {-# INLINE sequenceOf #-}
 
--- | A 'Traversal' of the nth element of another 'Traversal'
+-- | Yields a 'Traversal' of the nth element of another 'Traversal'
 --
 -- > traverseHead = elementOf traverse 0
-elementOf :: Applicative f => ((c -> AppliedState f c) -> a -> AppliedState f b) -> Int -> (c -> f c) -> a -> f b
+elementOf :: Applicative f => LensLike (AppliedState f) a b c c -> Int -> (c -> f c) -> a -> f b
 elementOf l = elementsOf l . (==)
 
 -- | A 'Traversal' of the elements in another 'Traversal' where their positions in that 'Traversal' satisfy a predicate
 --
 -- > traverseTail = elementsOf traverse (>0)
-elementsOf :: Applicative f => ((c -> AppliedState f c) -> a -> AppliedState f b) -> (Int -> Bool) -> (c -> f c) -> a -> f b
+elementsOf :: Applicative f => LensLike (AppliedState f) a b c c -> (Int -> Bool) -> (c -> f c) -> a -> f b
 elementsOf l p f ta = fst (runAppliedState (l go ta) 0) where
   go a = AppliedState $ \i -> (if p i then f a else pure a, i + 1)
 
@@ -1043,8 +1332,7 @@
 -- > transpose = transposeOf traverse -- modulo the ragged arrays support
 --
 -- > transposeOf _2 :: (b, [a]) -> [(b, a)]
-
-transposeOf :: (([c] -> ZipList c) -> a -> ZipList b) -> a -> [b]
+transposeOf :: LensLike ZipList a b [c] c -> a -> [b]
 transposeOf l = getZipList . l ZipList
 
 --------------------------
@@ -1069,7 +1357,9 @@
 traverseHead f (a:as) = (:as) <$> f a
 {-# INLINE traverseHead #-}
 
--- | > traverseTail :: Applicative f => ([a] -> f [a]) -> [a] -> f [a]
+-- | Traversal for editing the tail of a list.
+--
+-- > traverseTail :: Applicative f => ([a] -> f [a]) -> [a] -> f [a]
 traverseTail :: Simple Traversal [a] [a]
 traverseTail _ [] = pure []
 traverseTail f (a:as) = (a:) <$> f as
@@ -1147,9 +1437,29 @@
   go a = AppliedState $ \i -> (if p i then f a else pure a, i + 1)
 {-# INLINE traverseElements #-}
 
+-- |
+-- Traverse the typed value contained in a 'Dynamic' where the type required by your function matches that
+-- of the contents of the 'Dynamic'.
+--
+-- > traverseDynamic :: (Applicative f, Typeable a, Typeable b) => (a -> f b) -> Dynamic -> f Dynamic
+traverseDynamic :: (Typeable a, Typeable b) => Traversal Dynamic Dynamic a b
+traverseDynamic f dyn = case fromDynamic dyn of
+  Just a  -> toDyn <$> f a
+  Nothing -> pure dyn
+
+-- |
+-- Traverse the strongly typed 'Exception' contained in 'SomeException' where the type of your function matches
+-- the desired 'Exception'.
+--
+-- > traverseException :: (Applicative f, Exception a, Exception b) => (a -> f b) -> SomeException -> f SomeException
+traverseException :: (Exception a, Exception b) => Traversal SomeException SomeException a b
+traverseException f e = case fromException e of
+  Just a -> toException <$> f a
+  Nothing -> pure e
+
 -- | Provides ad hoc overloading for 'traverseByteString'
 class TraverseByteString t where
-  -- | Traverse the individual bytes in a ByteString
+  -- | Traverse the individual bytes in a 'ByteString'
   --
   -- > anyOf traverseByteString (==0x80) :: TraverseByteString b => b -> Bool
   traverseByteString :: Simple Traversal t Word8
@@ -1160,6 +1470,19 @@
 instance TraverseByteString Lazy.ByteString where
   traverseByteString f = fmap Lazy.pack . traverse f . Lazy.unpack
 
+-- | Provides ad hoc overloading for 'traverseText'
+class TraverseText t where
+  -- | Traverse the individual characters in a 'Text'
+  --
+  -- > anyOf traverseText (=='c') :: TraverseText b => b -> Bool
+  traverseText :: Simple Traversal t Char
+
+instance TraverseText StrictText.Text where
+  traverseText f = fmap StrictText.pack . traverse f . StrictText.unpack
+
+instance TraverseText LazyText.Text where
+  traverseText f = fmap LazyText.pack . traverse f . LazyText.unpack
+
 -- | Types that support traversal of the value of the minimal key
 --
 -- This is separate from 'TraverseValueAtMax' because a min-heap
@@ -1188,6 +1511,9 @@
     a :< as -> (<| as) <$> f a
     EmptyL -> pure m
 
+instance TraverseValueAtMin Tree where
+  traverseValueAtMin f (Node a as) = (`Node` as) <$> f a
+
 -- | Types that support traversal of the value of the maximal key
 --
 -- This is separate from 'TraverseValueAtMin' because a min-heap
@@ -1224,7 +1550,6 @@
 --
 -- > ghci> toListOf traverseBits 5
 -- > [True,False,True,False,False,False,False,False,False,False,False,False...
-
 traverseBits :: Bits b => Simple Traversal b Bool
 traverseBits f b = Prelude.foldr step 0 <$> traverse g bits
   where
@@ -1249,9 +1574,10 @@
 -- | Cloning a 'Lens' is one way to make sure you arent given
 -- something weaker, such as a 'Traversal' and can be used
 -- as a way to pass around lenses that have to be monomorphic in 'f'.
-clone :: Functor f =>
-   ((c -> IndexedStore c d d) -> a -> IndexedStore c d b) ->
-  (c -> f d) -> a -> f b
+--
+-- Note: This only accepts a proper 'Lens', because 'IndexedStore' lacks its
+-- (admissable) Applicative instance.
+clone :: 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
   IndexedStore db c -> db <$> cfd c
 {-# INLINE clone #-}
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,7 +1,3 @@
-{-# LANGUAGE CPP #-}
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704
-{-# LANGUAGE Safe #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Lens.Internal
@@ -24,6 +20,10 @@
   , Focusing(..)
   , Traversed(..)
   , AppliedState(..)
+  , Min(..)
+  , getMin
+  , Max(..)
+  , getMax
   ) where
 
 import Control.Applicative
@@ -75,3 +75,31 @@
 instance Applicative f => Monoid (Traversed f) where
   mempty = Traversed (pure ())
   Traversed ma `mappend` Traversed mb = Traversed (ma *> mb)
+
+-- | Used for 'minimumOf'
+data Min a = NoMin | Min a
+
+instance Ord a => Monoid (Min a) where
+  mempty = NoMin
+  mappend NoMin m = m
+  mappend m NoMin = m
+  mappend (Min a) (Min b) = Min (min a b)
+
+-- | Obtain the minimum
+getMin :: Min a -> Maybe a
+getMin NoMin   = Nothing
+getMin (Min a) = Just a
+
+-- | Used for 'maximumOf'
+data Max a = NoMax | Max a
+
+instance Ord a => Monoid (Max a) where
+  mempty = NoMax
+  mappend NoMax m = m
+  mappend m NoMax = m
+  mappend (Max a) (Max b) = Max (max a b)
+
+-- | Obtain the maximum
+getMax :: Max a -> Maybe a
+getMax NoMax   = Nothing
+getMax (Max a) = Just a
diff --git a/src/Control/Lens/Representable.hs b/src/Control/Lens/Representable.hs
--- a/src/Control/Lens/Representable.hs
+++ b/src/Control/Lens/Representable.hs
@@ -1,8 +1,4 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE RankNTypes #-}
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704
-{-# LANGUAGE Safe #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Control.Lens.Representable
