diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@
 env:
   - GHCVER=7.4.2
   - GHCVER=7.6.3
+  - GHCVER=7.8.1
   - GHCVER=head
   # - >
   #   GHCVER=7.4.2
@@ -26,9 +27,9 @@
       export CABAL=cabal
     else
       # Install the GHC we want from hvr's PPA
-      sudo add-apt-repository -y ppa:hvr/ghc
-      sudo apt-get update
-      sudo apt-get install cabal-install-1.18 ghc-$GHCVER
+      travis_retry sudo add-apt-repository -y ppa:hvr/ghc
+      travis_retry sudo apt-get update
+      travis_retry sudo apt-get install cabal-install-1.18 ghc-$GHCVER happy
       export CABAL=cabal-1.18
       export PATH=/opt/ghc/$GHCVER/bin:$PATH
     fi
@@ -37,12 +38,11 @@
   - $CABAL update
 
   # Update happy when building with GHC head
-  - | 
-    if [ $GHCVER = "head" ]; then
-      $CABAL install happy
+  - |
+    if [ $GHCVER = "head" ] || [ $GHCVER = "7.8.1" ]; then
+      $CABAL install happy alex
       export PATH=$HOME/.cabal/bin:$PATH
     fi
-    
 
 install:
   - $CABAL install --dependencies-only --enable-tests
diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,9 @@
+4.0.5
+-----
+* Added `bimapping` to `Control.Lens.Iso`
+* Restored correct behavior of `makePrism` on types with a single constructor.
+* `makeLenses` now generates `Getter`s and `Fold`s on universally quantified fields.
+
 4.0.4
 -----
 * Made `declareFields` work again.
diff --git a/lens.cabal b/lens.cabal
--- a/lens.cabal
+++ b/lens.cabal
@@ -1,6 +1,6 @@
 name:          lens
 category:      Data, Lenses, Generics
-version:       4.0.4
+version:       4.0.5
 license:       BSD3
 cabal-version: >= 1.8
 license-file:  LICENSE
diff --git a/src/Control/Lens/At.hs b/src/Control/Lens/At.hs
--- a/src/Control/Lens/At.hs
+++ b/src/Control/Lens/At.hs
@@ -46,6 +46,7 @@
 import Control.Lens.Setter
 import Control.Lens.Type
 import Control.Lens.Internal.TupleIxedTH (makeAllTupleIxed)
+import Data.Aeson as Aeson
 import Data.Array.IArray as Array
 import Data.Array.Unboxed
 import Data.ByteString as StrictB
@@ -90,7 +91,7 @@
 type instance Index (IntMap a) = Int
 type instance Index (Map k a) = k
 type instance Index (HashMap k a) = k
-type instance Index (Array i e) = i
+type instance Index (Array.Array i e) = i
 type instance Index (UArray i e) = i
 type instance Index (Vector.Vector a) = Int
 type instance Index (Prim.Vector a) = Int
@@ -104,6 +105,7 @@
 type instance Index LazyT.Text = Int64
 type instance Index StrictB.ByteString = Int
 type instance Index LazyB.ByteString = Int64
+type instance Index Aeson.Value = StrictT.Text
 
 -- $setup
 -- >>> :set -XNoOverloadedStrings
@@ -274,13 +276,13 @@
      else pure m
   {-# INLINE ix #-}
 
-type instance IxValue (Array i e) = e
+type instance IxValue (Array.Array i e) = e
 -- |
 -- @
 -- arr '!' i ≡ arr 'Control.Lens.Getter.^.' 'ix' i
 -- arr '//' [(i,e)] ≡ 'ix' i 'Control.Lens.Setter..~' e '$' arr
 -- @
-instance Ix i => Ixed (Array i e) where
+instance Ix i => Ixed (Array.Array i e) where
   ix i f arr
     | inRange (bounds arr) i = f (arr Array.! i) <&> \e -> arr Array.// [(i,e)]
     | otherwise              = pure arr
@@ -358,6 +360,14 @@
        Nothing      -> pure s
        Just (c, xs) -> f c <&> \d -> LazyB.append l (LazyB.cons d xs)
   {-# INLINE ix #-}
+
+
+type instance IxValue Aeson.Value = Aeson.Value
+instance Ixed Aeson.Value where
+  ix i f (Object o) = Object <$> ix i f o
+  ix _ _ v          = pure v
+  {-# INLINE ix #-}
+
 
 
 -- | 'At' provides a 'Lens' that can be used to read,
diff --git a/src/Control/Lens/Empty.hs b/src/Control/Lens/Empty.hs
--- a/src/Control/Lens/Empty.hs
+++ b/src/Control/Lens/Empty.hs
@@ -38,7 +38,7 @@
 import Data.Vector.Unboxed as Unboxed
 import Data.Vector.Storable as Storable
 
-#ifndef mingw32_HOST_OS
+#if !defined(mingw32_HOST_OS) && !defined(ghcjs_HOST_OS)
 import GHC.Event
 #endif
 
@@ -59,7 +59,7 @@
 instance AsEmpty ()
 instance AsEmpty Any
 instance AsEmpty All
-#ifndef mingw32_HOST_OS
+#if !defined(mingw32_HOST_OS) && !defined(ghcjs_HOST_OS)
 instance AsEmpty Event
 #endif
 instance (Eq a, Num a) => AsEmpty (Product a)
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
@@ -432,7 +432,7 @@
 iuses l = uses l .# Indexed
 {-# INLINE iuses #-}
 
--- | View the value pointed to by a 'Getter' or 'Lens'.
+-- | View the index and value of an 'IndexedGetter' or 'IndexedLens'.
 --
 -- This is the same operation as 'iview' with the arguments flipped.
 --
diff --git a/src/Control/Lens/Internal/Exception.hs b/src/Control/Lens/Internal/Exception.hs
--- a/src/Control/Lens/Internal/Exception.hs
+++ b/src/Control/Lens/Internal/Exception.hs
@@ -40,8 +40,9 @@
 import Data.Proxy
 import Data.Typeable
 
+-- This is needed because ghc 7.8-rc2 has Typeable1 as a type alias.
 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
-type Typeable1 = Typeable
+#define Typeable1 Typeable
 #endif
 
 ------------------------------------------------------------------------------
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
@@ -58,6 +58,8 @@
   , dimapping
   , lmapping
   , rmapping
+  -- * Bifunctors
+  , bimapping
   ) where
 
 import Control.Lens.Fold
@@ -463,8 +465,8 @@
 -- dimapping :: 'Profunctor' p => 'Iso'' s a -> 'Iso'' s' a' -> 'Iso'' (p a s') (p s a')
 -- @
 dimapping :: Profunctor p => AnIso s t a b -> AnIso s' t' a' b' -> Iso (p a s') (p b t') (p s a') (p t b')
-dimapping f g = withIso f $ \ s'a' b't' -> withIso g $ \ sa bt ->
-  iso (dimap s'a' sa) (dimap b't' bt)
+dimapping f g = withIso f $ \ sa bt -> withIso g $ \ s'a' b't' ->
+  iso (dimap sa s'a') (dimap bt b't')
 {-# INLINE dimapping #-}
 
 -- | Lift an 'Iso' contravariantly into the left argument of a 'Profunctor'.
@@ -486,3 +488,18 @@
 rmapping :: Profunctor p => AnIso s t a b -> Iso (p x s) (p y t) (p x a) (p y b)
 rmapping g = withIso g $ \ sa bt -> iso (rmap sa) (rmap bt)
 {-# INLINE rmapping #-}
+
+------------------------------------------------------------------------------
+-- Bifunctor
+------------------------------------------------------------------------------
+
+-- | Lift two 'Iso's into both arguments of a 'Bifunctor'.
+--
+-- @
+-- bimapping :: 'Profunctor' p => 'Iso' s t a b -> 'Iso' s' t' a' b' -> 'Iso' (p s s') (p t t') (p a a') (p b b')
+-- bimapping :: 'Profunctor' p => 'Iso'' s a -> 'Iso'' s' a' -> 'Iso'' (p s s') (p a a')
+-- @
+bimapping :: Bifunctor f => AnIso s t a b -> AnIso s' t' a' b' -> Iso (f s s') (f t t') (f a a') (f b b')
+bimapping f g = withIso f $ \ sa bt -> withIso g $ \s'a' b't' ->
+  iso (bimap sa s'a') (bimap bt b't')
+{-# INLINE bimapping #-}
diff --git a/src/Control/Lens/Plated.hs b/src/Control/Lens/Plated.hs
--- a/src/Control/Lens/Plated.hs
+++ b/src/Control/Lens/Plated.hs
@@ -88,6 +88,7 @@
 import           Control.Lens.Setter
 import           Control.Lens.Traversal
 import qualified Language.Haskell.TH as TH
+import           Data.Aeson
 import           Data.Data
 import           Data.Data.Lens
 import           Data.Monoid
@@ -203,6 +204,12 @@
 
 instance Plated (Tree a) where
   plate f (Node a as) = Node a <$> traverse f as
+
+instance Plated Value where
+  plate f (Object o) = Object <$> traverse f o
+  plate f (Array a) = Array <$> traverse f a
+  plate _ xs = pure xs
+  {-# INLINE plate #-}
 
 {- Default uniplate instances -}
 instance Plated TH.Exp
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
@@ -60,6 +60,7 @@
   , buildTraversals
   , handleSingletons
   , singletonIso
+  , backwardIso
   , singletonRequired
   , createClass
   , createInstance
@@ -116,6 +117,7 @@
   | BuildTraversals
   | SingletonAndField
   | SingletonIso
+  | BackwardIso
   | HandleSingletons
   | SingletonRequired
   | CreateClass
@@ -154,6 +156,10 @@
 singletonIso      :: Lens' LensRules Bool
 singletonIso       = lensFlags.contains SingletonIso
 
+-- | When generating an 'Iso' put the field type as the "outer" type.
+backwardIso      :: Lens' LensRules Bool
+backwardIso       = lensFlags.contains BackwardIso
+
 -- | Expect a single constructor, single field newtype or data type.
 singletonRequired :: Lens' LensRules Bool
 singletonRequired  = lensFlags.contains SingletonRequired
@@ -282,6 +288,7 @@
   & handleSingletons  .~ True
   & singletonRequired .~ True
   & singletonAndField .~ True
+  & backwardIso       .~ True
 
 -- | Build lenses (and traversals) with a sensible default configuration.
 --
@@ -588,11 +595,15 @@
 makePrismsForCons dataDecl@(DataDecl _ _ _ _ [_]) = case constructors dataDecl of
   -- Iso promotion via tuples
   [NormalC dataConName xs] ->
-    makeIsoLenses isoRules dataDecl dataConName Nothing $ map (view _2) xs
+    makeIsoLenses rules dataDecl dataConName Nothing $ map (view _2) xs
   [RecC    dataConName xs] ->
-    makeIsoLenses isoRules dataDecl dataConName Nothing $ map (view _3) xs
+    makeIsoLenses rules dataDecl dataConName Nothing $ map (view _3) xs
   _                        ->
     fail "makePrismsForCons: A single-constructor data type is required"
+  where
+  rules = isoRules & lensIso     .~ (Just . ('_':))
+                   & backwardIso .~ False
+
 makePrismsForCons dataDecl =
   concat <$> mapM (makePrismOrReviewForCon dataDecl canModifyTypeVar ) (constructors dataDecl)
   where
@@ -826,8 +837,8 @@
   m <- freshMap $ setOf typeVars tyArgs
   let aty = List.foldl' AppT (TupleT $ length partTy) partTy
       bty = substTypeVars m aty
-      cty = fullType dataDecl $ map (VarT . view name) tyArgs
-      dty = substTypeVars m cty
+      sty = fullType dataDecl $ map (VarT . view name) tyArgs
+      tty = substTypeVars m sty
       quantified = ForallT (tyArgs ++ substTypeVars m tyArgs)
         (dataContext dataDecl ++ substTypeVars m (dataContext dataDecl))
       maybeIsoName = mkName <$> view lensIso cfg (nameBase dataConName)
@@ -839,13 +850,18 @@
       makeBody | lensOnly  = makeLensBody
                | otherwise = makeIsoBody
   isoDecls <- flip (maybe (return [])) maybeIsoName $ \isoName -> do
+    let backward = cfg^.backwardIso
     let decl = SigD isoName $ quantified $
-          if cfg^.simpleLenses || Map.null m
-          then isoCon' `apps` [aty,cty]
-          else isoCon `apps` [aty,bty,cty,dty]
+          case (cfg^.simpleLenses || Map.null m, backward) of
+            (True , False) -> isoCon' `apps` [sty,aty]
+            (False, False) -> isoCon  `apps` [sty,tty,aty,bty]
+            (True , True ) -> isoCon' `apps` [aty,sty]
+            (False, True ) -> isoCon  `apps` [aty,bty,sty,tty]
     (ns, f) <- makeIsoFrom aty dataConName
     t <- makeIsoTo ns dataConName
-    body <- makeBody isoName f t
+    body <- if backward
+             then makeBody isoName f t
+             else makeBody isoName t f
 #ifndef INLINING
     return $ if cfg^.generateSignatures then [decl, body] else [body]
 #else
@@ -857,8 +873,8 @@
       | (jfn /= maybeIsoName) && (isNothing maybeIsoName || cfg^.singletonAndField) -> do
       let decl = SigD lensName $ quantified $
             if cfg^.simpleLenses || Map.null m
-            then isoCon' `apps` [cty,aty]
-            else isoCon `apps` [cty,dty,aty,bty]
+            then isoCon' `apps` [sty,aty]
+            else isoCon `apps` [sty,tty,aty,bty]
       (ns, f) <- makeIsoFrom aty dataConName
       t <- makeIsoTo ns dataConName
       body <- makeBody lensName t f
@@ -871,6 +887,45 @@
     _ -> return []
   return $ isoDecls ++ accessorDecls
 
+makeFieldGetterBody :: Bool -> Name -> [(Con, [Name])] -> Maybe Name -> Q Dec
+makeFieldGetterBody isFold lensName conList maybeMethodName
+  = case maybeMethodName of
+      Just methodName -> do
+         go <- newName "go"
+         let expr = infixApp (varE methodName) (varE '(Prelude..)) (varE go)
+         funD lensName [ clause [] (normalB expr) [funD go clauses] ]
+      Nothing -> funD lensName clauses
+  where
+    clauses = map buildClause conList
+
+    buildClause (con@RecC{}, fields) = do
+      f <- newName "_f"
+      vars <- for (con^..conNamedFields._1) $ \fld ->
+          if fld `List.elem` fields
+        then Just  <$> newName ('_':(nameBase fld++""))
+        else return Nothing
+      let cpats = maybe wildP varP <$> vars               -- Deconstruction
+          fvals = map (appE (varE f) . varE) (catMaybes vars) -- Functor applications
+          conName = con^.name
+
+          expr
+            | not isFold && length fields /= 1
+              = appE (varE 'error) . litE . stringL
+              $ show lensName ++ ": expected a single matching field in " ++ show conName ++ ", found " ++ show (length fields)
+            | List.null fields
+              = [| coerce (pure ()) |]
+            | otherwise
+              = let add x y = [| $x *> $y |]
+                in [| coerce $(List.foldl1 add fvals) |]
+      clause [varP f, conP conName cpats] (normalB expr) []
+
+    -- Non-record are never the target of a generated field lens body
+    buildClause (con, _fields) =
+      -- clause:  _ c@Con{} = expr
+      -- expr:    pure c
+      clause [wildP, recP (con^.name) []] (normalB [| coerce (pure ()) |]) []
+
+
 makeFieldLensBody :: Bool -> Name -> [(Con, [Name])] -> Maybe Name -> Q Dec
 makeFieldLensBody isTraversal lensName conList maybeMethodName = case maybeMethodName of
     Just methodName -> do
@@ -991,15 +1046,20 @@
             else "The following constructors failed this criterion for the " ++ pprint lensName ++ " lens:"
           ] ++ map showCon conList
 
-    let decl = SigD lensName $ ForallT tvs' qs vars
-          where
-          vars
-            | aty == bty && cty == dty || cfg^.simpleLenses || isJust maybeClassName
-               = apps (ConT (if isTraversal then ''Traversal' else ''Lens')) [aty,cty]
-            | otherwise
-               = apps (ConT (if isTraversal then ''Traversal else ''Lens)) [aty,bty,cty,dty]
+    let decl = SigD lensName
+             $ case cty of
+                 ForallT innerTys innerCxt cty' ->
+                   ForallT (tvs'++innerTys) (qs++innerCxt)
+                    $ apps (ConT (if isTraversal then ''Fold else ''Getter)) [aty,cty']
+                 _ ->
+                   ForallT tvs' qs
+                    $ if aty == bty && cty == dty || cfg^.simpleLenses || isJust maybeClassName
+                      then apps (ConT (if isTraversal then ''Traversal' else ''Lens')) [aty,cty]
+                      else apps (ConT (if isTraversal then ''Traversal else ''Lens)) [aty,bty,cty,dty]
 
-    body <- makeFieldLensBody isTraversal lensName conList maybeMethodName
+    body <- case cty of
+              ForallT {} -> makeFieldGetterBody isTraversal lensName conList maybeMethodName
+              _          -> makeFieldLensBody isTraversal lensName conList maybeMethodName
 #ifndef INLINING
     return $ if cfg^.generateSignatures then [decl, body] else [body]
 #else
diff --git a/src/Data/Aeson/Lens.hs b/src/Data/Aeson/Lens.hs
--- a/src/Data/Aeson/Lens.hs
+++ b/src/Data/Aeson/Lens.hs
@@ -34,7 +34,6 @@
   , AsJSON(..)
   ) where
 
-import Control.Applicative
 import Control.Lens
 import Data.Aeson
 import Data.Scientific
@@ -329,20 +328,3 @@
     Success y -> Right y;
     _         -> Left x
   {-# INLINE _JSON #-}
-
-------------------------------------------------------------------------------
--- Orphan instances
-------------------------------------------------------------------------------
-
-type instance Index Value = Text
-type instance IxValue Value = Value
-
-instance Ixed Value where
-  ix i = _Object.ix i
-  {-# INLINE ix #-}
-
-instance Plated Value where
-  plate f (Object o) = Object <$> traverse f o
-  plate f (Array a) = Array <$> traverse f a
-  plate _ xs = pure xs
-  {-# INLINE plate #-}
diff --git a/tests/templates.hs b/tests/templates.hs
--- a/tests/templates.hs
+++ b/tests/templates.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE CPP #-}
 -----------------------------------------------------------------------------
 -- |
@@ -22,6 +23,7 @@
 module Main where
 
 import Control.Lens
+import Data.List (nub)
 -- import Test.QuickCheck (quickCheck)
 
 data Bar a b c = Bar { _baz :: (a, b) }
@@ -150,10 +152,13 @@
   data Banana = Banana Int String
   |]
 -- data Banana = Banana Int String
--- banana :: Iso' (Int, String) Banana
+-- _Banana :: Iso' Banana (Int, String)
 cavendish :: Banana
-cavendish = view banana (4, "Cavendish")
+cavendish = _Banana # (4, "Cavendish")
 
+banana :: Iso' (Int, String) Banana
+banana = from _Banana
+
 data family Family a b c
 
 #if __GLASGOW_HASKELL >= 706
@@ -178,6 +183,34 @@
 --   data Associated Int = AssociatedInt Double
 --   method = id
 -- mochi :: Iso' (Associated Int) Double
+
+declareFields [d|
+  data DeclaredFields f a
+    = DeclaredField1 { declaredFieldsA :: f a    , declaredFieldsB :: Int }
+    | DeclaredField2 { declaredFieldsC :: String , declaredFieldsB :: Int }
+    deriving (Show)
+  |]
+
+declaredFieldsUse1 :: [Bool]
+declaredFieldsUse1 = view fieldsA (DeclaredField1 [True] 0)
+
+declaredFieldsUse2 :: [DeclaredFields [] ()]
+declaredFieldsUse2 = over (traverse.fieldsB) (+1) [DeclaredField1 [()] 0, DeclaredField2 "" 1]
+
+data Rank2Tests
+  = C1 { _r2length :: forall a. [a] -> Int
+       , _r2nub    :: forall a. Eq a=> [a] -> [a]
+       }
+  | C2 { _r2length :: forall a. [a] -> Int }
+
+makeLenses ''Rank2Tests
+
+useFold1 :: Maybe [Bool]
+useFold1  = C1 length nub ^? r2nub . to ($ [False,True,True])
+useFold2 :: Maybe [Bool]
+useFold2  = C2 length     ^? r2nub . to ($ [False,True,True])
+useLength :: Int
+useLength = C1 length nub ^. r2length . to ($ [False,True,True])
 
 main :: IO ()
 main = putStrLn "test/templates.hs: ok"
