diff --git a/Data/Vinyl.hs b/Data/Vinyl.hs
--- a/Data/Vinyl.hs
+++ b/Data/Vinyl.hs
@@ -4,7 +4,7 @@
   , module Data.Vinyl.Field
   , module Data.Vinyl.Rec
   , module Data.Vinyl.Relation
-  , module Data.Vinyl.Classes,
+  , module Data.Vinyl.Classes
   ) where
 
 import           Data.Vinyl.Classes
diff --git a/Data/Vinyl/Classes.hs b/Data/Vinyl/Classes.hs
--- a/Data/Vinyl/Classes.hs
+++ b/Data/Vinyl/Classes.hs
@@ -1,22 +1,25 @@
 {-# LANGUAGE KindSignatures        #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PolyKinds             #-}
-{-# LANGUAGE Safe                  #-}
 {-# LANGUAGE TypeOperators         #-}
 
 module Data.Vinyl.Classes where
 
 import           Control.Applicative
-import           Control.Monad.Identity
+import           Data.Functor.Identity
 
 -- | This class is a generalized, but non-pointed version of 'Applicative'. This
 -- is useful for types which range over functors rather than sets.
 class Apply (arr :: k -> k -> k) (f :: k -> *) where
   (<<*>>) :: f (arr a b) -> f a -> f b
 
--- | To accumulate effects distributed over a data type, you 'run' it.
-class Run t where
-  run :: Applicative f => t f -> f (t Identity)
+-- | To accumulate effects distributed over a data type, you 'dist' it.
+class Dist t where
+  dist :: Applicative f => t f -> f (t Identity)
+
+-- | If a record is homogenous, you can fold over it.
+class FoldRec r a where
+  foldRec :: (a -> b -> b) -> b -> r -> b
 
 -- | '(~>)' is a morphism between functors.
 newtype (f ~> g) x = NT { runNT :: f x -> g x }
diff --git a/Data/Vinyl/Field.hs b/Data/Vinyl/Field.hs
--- a/Data/Vinyl/Field.hs
+++ b/Data/Vinyl/Field.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE GADTs               #-}
 {-# LANGUAGE KindSignatures      #-}
@@ -7,11 +8,19 @@
 
 module Data.Vinyl.Field where
 
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
+import           Data.Proxy
+#endif
 import           GHC.TypeLits
 
 -- | A field contains a key and a type.
 data (:::) :: Symbol -> * -> * where
   Field :: sy ::: t
 
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
+instance KnownSymbol sy => Show (sy ::: t) where
+  show Field = symbolVal (Proxy :: Proxy sy)
+#else
 instance SingI sy => Show (sy ::: t) where
   show Field = fromSing (sing :: Sing sy)
+#endif
diff --git a/Data/Vinyl/Lens.hs b/Data/Vinyl/Lens.hs
--- a/Data/Vinyl/Lens.hs
+++ b/Data/Vinyl/Lens.hs
@@ -1,84 +1,80 @@
-{-# LANGUAGE DataKinds                 #-}
-{-# LANGUAGE FlexibleContexts          #-}
-{-# LANGUAGE GADTs                     #-}
-{-# LANGUAGE NoMonomorphismRestriction #-}
-{-# LANGUAGE RankNTypes                #-}
-{-# LANGUAGE TypeOperators             #-}
-{-# LANGUAGE ScopedTypeVariables       #-}
-
-module Data.Vinyl.Lens
-  ( module Control.Lens
-  , RLens
-  , rLens
-  , rGet
-  , rPut
-  , rMod
-  , RLens'
-  , rLens'
-  ) where
-
-import           Data.Vinyl.Field
-import           Data.Vinyl.Rec
-import           Data.Vinyl.Witnesses
-
-import           Control.Lens
-import           Control.Monad.Identity
-
-type RLens sy t = IElem (sy ::: t) rs => Lens' (PlainRec rs) t
-type RLens' f sy t = IElem (sy ::: t) rs => Lens' (Rec rs f) (f t)
-
--- | Generates a lens for a record in the 'Identity' functor.
-rLens :: (sy ::: t) -> RLens sy t
-rLens f = rLens' f . lens runIdentity (const Identity)
-{-# INLINE rLens #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeOperators         #-}
+-- | A small, /en passant/ lens implementation to provide accessors
+-- for record fields. Lenses produced with 'rLens' are fully
+-- compatible with the @lens@ package.
+module Data.Vinyl.Lens where
+import Control.Applicative
+import Data.Functor.Identity
+import Data.Vinyl.Field
+import Data.Vinyl.Rec
+import Data.Vinyl.Witnesses
 
--- | Generates a lens of a record in an arbitrary functor.
-rLens' :: (sy ::: t) -> RLens' f sy t
-rLens' f = rLensAux f implicitly
-{-# INLINE rLens' #-}
+-- | Project a field from a 'Rec'.
+rGet' :: IElem (sy ::: t) rs => (sy ::: t) -> Rec rs f -> f t
+rGet' r = getConst . rLens' r Const
+{-# INLINE rGet' #-}
 
-rGet = view . rLens
+-- | Project a field from a 'PlainRec'.
+rGet :: IElem (sy ::: t) rs => (sy ::: t) -> PlainRec rs -> t
+rGet = (runIdentity .) . rGet'
 {-# INLINE rGet #-}
 
-rPut = set . rLens
+-- | Set a field in a 'Rec' over an arbitrary functor.
+rPut' :: IElem (sy ::: t) rs => (sy ::: t) -> f t -> Rec rs f -> Rec rs f
+rPut' r x = runIdentity . rLens' r (Identity . const x)
+{-# INLINE rPut' #-}
+
+-- | Set a field in a 'PlainRec'.
+rPut :: IElem (sy:::t) rs => (sy:::t) -> t -> PlainRec rs -> PlainRec rs
+rPut r x = rPut' r (Identity x)
 {-# INLINE rPut #-}
 
-rMod = over . rLens
+-- | Modify a field.
+rMod :: (IElem (sy:::t) rs, Functor f)
+     => (sy:::t) -> (t -> t) -> Rec rs f -> Rec rs f
+rMod r f = runIdentity . rLens' r (Identity . fmap f)
 {-# INLINE rMod #-}
 
--- We manually unroll several levels of record traversal via 'Elem'
--- values to help GHC eliminate the 'Implicit' dictionaries at
--- runtime.
-
-{-# INLINE rLensAux #-}
-rLensAux :: forall f r sy t rs. (r ~ (sy ::: t))
-         => r -> Elem r rs -> Lens' (Rec rs f) (f t)
-rLensAux _ = go
-  where goHere :: Elem r rs' -> Lens' (Rec rs' f) (f t)
-        goHere Here = lens (\(x :& _) -> x) (\(_ :& xs) x -> x :& xs)
-        goHere _ = error "Unintended base case invocation"
+-- We manually unroll several levels of 'Elem' value traversal to help
+-- GHC statically index into small records.
 
-        go :: Elem r rs' -> Lens' (Rec rs' f) (f t)
-        go Here = goHere Here
-        go (There Here) = rLensPrepend $ goHere Here
-        go (There (There Here)) = rLensPrepend $ rLensPrepend $ goHere Here
-        go (There (There (There Here))) =
-          rLensPrepend $ rLensPrepend $ rLensPrepend $ goHere Here
-        go (There (There (There (There Here)))) =
-          rLensPrepend $ rLensPrepend $ rLensPrepend $ rLensPrepend $ goHere Here
-        go (There (There (There (There p)))) =
-          rLensPrepend $ rLensPrepend $ rLensPrepend $ rLensPrepend $ go' p
+-- | Provide a lens to a record field. Note that this implementation
+-- does not support polymorphic update. In the parlance of the @lens@
+-- package,
+--
+-- > rLens' :: IElem (sy:::t) rs => (sy:::t) -> Lens' (Rec rs f) (f t)
+rLens' :: forall r rs sy t f g. (r ~ (sy:::t), IElem r rs, Functor g)
+       => r -> (f t -> g (f t)) -> Rec rs f -> g (Rec rs f)
+rLens' _ f = go implicitly
+  where go :: Elem r rr -> Rec rr f -> g (Rec rr f)
+        go Here (x :& xs) = fmap (:& xs) (f x)
+        go (There Here) (a :& x :& xs) = fmap ((a :&) . (:& xs)) (f x)
+        go (There (There Here)) (a :& b :& x :& xs) =
+          fmap (\x' -> a :& b :& x' :& xs) (f x)
+        go (There (There (There Here))) (a :& b :& c :& x :& xs) =
+          fmap (\x' -> a :& b :& c :& x' :& xs) (f x)
+        go (There (There (There (There Here)))) (a :& b :& c :& d :& x :& xs) =
+          fmap (\x' -> a :& b :& c :& d :& x' :& xs) (f x)
+        go (There (There (There (There p)))) (a :& b :& c :& d :& xs) =
+          fmap (\xs' -> a :& b :& c :& d :& xs') (go' p xs)
         {-# INLINE go #-}
 
-        go' :: Elem r rs' -> Lens' (Rec rs' f) (f t)
-        go' Here = goHere Here
-        go' (There p) = rLensPrepend $ go p
+        go' :: Elem r rr -> Rec rr f -> g (Rec rr f)
+        go' Here (x :& xs) = fmap (:& xs) (f x)
+        go' (There p) (x :& xs) = fmap (x :&) (go p xs)
         {-# INLINABLE go' #-}
-
-rLensPrepend :: Lens' (Rec rs f) (f t) -> Lens' (Rec (l ': rs) f) (f t)
-rLensPrepend l = lens (\(_ :& xs) -> view l xs) (\(a :& xs) x -> a :& (set l x xs))
-{-# INLINE rLensPrepend #-}
-
--- rLens' _ Here = lens (\(x :& xs) -> runIdentity x) (\(_ :& xs) x -> Identity x :& xs)
--- rLens' f (There p) = rLensPrepend $ rLens' f p
+{-# INLINE rLens' #-}
 
+-- | A lens into a 'PlainRec' that smoothly interoperates with lenses
+-- from the @lens@ package. Note that polymorphic update is not
+-- supported. In the parlance of the @lens@ package,
+-- 
+-- > rLens :: IElem (sy:::t) rs => (sy:::t) -> Lens' (PlainRec rs) t
+rLens :: forall r rs sy t g. (r ~ (sy:::t), IElem r rs, Functor g)
+      => r -> (t -> g t) -> PlainRec rs -> g (PlainRec rs)
+rLens r = rLens' r . lenser runIdentity (const Identity)
+  where lenser sa sbt afb s = sbt s <$> afb (sa s)
+{-# INLINE rLens #-}
diff --git a/Data/Vinyl/Rec.hs b/Data/Vinyl/Rec.hs
--- a/Data/Vinyl/Rec.hs
+++ b/Data/Vinyl/Rec.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE BangPatterns              #-}
+{-# LANGUAGE CPP                       #-}
 {-# LANGUAGE ConstraintKinds           #-}
 {-# LANGUAGE DataKinds                 #-}
 {-# LANGUAGE FlexibleContexts          #-}
@@ -19,16 +20,18 @@
   , PlainRec
   , (=:)
   , (<+>)
+  , type (++)
   , fixRecord
   ) where
 
 import           Data.Vinyl.Classes
 import           Control.Applicative
-import           Control.Monad.Identity
+import           Data.Functor.Identity
 import           Data.Vinyl.Field
 import           Foreign.Ptr (castPtr, plusPtr)
 import           Foreign.Storable (Storable(..))
 import           GHC.TypeLits
+import           Data.Monoid
 
 -- | A record is parameterized by a list of fields and a functor
 -- to be applied to each of those fields.
@@ -63,7 +66,13 @@
 
 instance Show (Rec '[] f) where
   show RNil = "{}"
-instance (SingI sy, Show (g t), Show (Rec fs g)) => Show (Rec ((sy ::: t) ': fs) g) where
+instance (
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
+    KnownSymbol sy,
+#else
+    SingI sy,
+#endif
+    Show (g t), Show (Rec fs g)) => Show (Rec ((sy ::: t) ': fs) g) where
   show (x :& xs) = show (Field :: sy ::: t) ++ " :=: " ++ show x ++ ", " ++ show xs
 
 
@@ -72,15 +81,34 @@
 instance (Eq (g t), Eq (Rec fs g)) => Eq (Rec ((s ::: t) ': fs) g) where
   (x :& xs) == (y :& ys) = (x == y) && (xs == ys)
 
+
+instance Monoid (Rec '[] f) where
+  mempty = RNil
+  RNil `mappend` RNil = RNil
+instance (Monoid t, Monoid (Rec fs g), Applicative g) => Monoid (Rec ((s ::: t) ': fs) g) where
+  mempty = pure mempty :& mempty
+  (x :& xs) `mappend` (y :& ys) = liftA2 mappend x y :& (xs `mappend` ys)
+
+
 -- | Records can be applied to each other.
 instance Apply (~>) (Rec rs) where
   RNil <<*>> RNil = RNil
   (f :& fs) <<*>> (x :& xs) = runNT f x :& (fs <<*>> xs)
 
--- | Records may be 'run' to accumulate the effects of their fields.
-instance Run (Rec rs) where
-  run RNil      = pure RNil
-  run (x :& xs) = (:&) <$> (pure <$> x) <*> run xs
+-- | Records may be distributed to accumulate the effects of their fields.
+instance Dist (Rec rs) where
+  dist RNil      = pure RNil
+  dist (x :& xs) = (:&) <$> (pure <$> x) <*> dist xs
+
+instance FoldRec (Rec '[] f) a where
+  foldRec _ z RNil = z
+
+instance FoldRec (Rec fs g) (g t) => FoldRec (Rec ((s ::: t) ': fs) g) (g t) where
+  foldRec f z (x :& xs) = f x (foldRec f z xs)
+
+-- | Accumulates a homogenous record into a list
+recToList :: FoldRec (Rec fs g) (g t) => Rec fs g -> [g t]
+recToList = foldRec (\e a -> [e] ++ a) []
 
 -- | We provide a 'Show' instance for 'Identity'.
 instance Show a => Show (Identity a) where
diff --git a/Data/Vinyl/Relation.hs b/Data/Vinyl/Relation.hs
--- a/Data/Vinyl/Relation.hs
+++ b/Data/Vinyl/Relation.hs
@@ -14,14 +14,13 @@
   ( (<:)(..)
   , (:~:)
   , (~=)
-  , rIso
+  -- , rIso
   ) where
 
 import           Data.Vinyl.Field
 import           Data.Vinyl.Lens
 import           Data.Vinyl.Rec
 import           Data.Vinyl.Witnesses
-import           Control.Monad.Identity
 
 import           GHC.Prim             (Constraint)
 
@@ -45,14 +44,14 @@
 instance Rec xs f <: Rec '[] f where
   cast _ = RNil
 
-instance (y ~ (sy ::: t), IElem y xs, PlainRec xs <: PlainRec ys) => PlainRec xs <: PlainRec (y ': ys) where
-  cast r = Identity (rGet field r) :& cast r
+instance (y ~ (sy ::: t), IElem y xs, Rec xs f <: Rec ys f) => Rec xs f <: Rec (y ': ys) f where
+  cast r = rGet' field r :& cast r
     where field = lookupField (implicitly :: Elem y xs) r
 
 lookupField :: Elem x xs -> Rec xs f -> x
 lookupField Here      (_ :& _)  = Field
 lookupField (There p) (_ :& xs) = lookupField p xs
 
-rIso :: (r1 :~: r2) => Iso' r1 r2
-rIso = iso cast cast
+-- rIso :: (r1 :~: r2) => Iso' r1 r2
+-- rIso = iso cast cast
 
diff --git a/Data/Vinyl/Validation.hs b/Data/Vinyl/Validation.hs
--- a/Data/Vinyl/Validation.hs
+++ b/Data/Vinyl/Validation.hs
@@ -1,10 +1,9 @@
-{-# LANGUAGE Safe         #-}
 {-# LANGUAGE TypeOperators #-}
 
 module Data.Vinyl.Validation where
 
 import           Control.Applicative
-import           Control.Monad.Identity
+import           Data.Functor.Identity
 import           Data.Monoid
 import           Data.Vinyl.Classes
 
diff --git a/Data/Vinyl/Witnesses.hs b/Data/Vinyl/Witnesses.hs
--- a/Data/Vinyl/Witnesses.hs
+++ b/Data/Vinyl/Witnesses.hs
@@ -6,7 +6,6 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverlappingInstances  #-}
 {-# LANGUAGE PolyKinds             #-}
-{-# LANGUAGE Safe                  #-}
 {-# LANGUAGE TypeOperators         #-}
 
 module Data.Vinyl.Witnesses where
diff --git a/benchmarks/StorableBench.hs b/benchmarks/StorableBench.hs
--- a/benchmarks/StorableBench.hs
+++ b/benchmarks/StorableBench.hs
@@ -8,6 +8,8 @@
 -- record of "Linear" finite dimensional vector types, and a vinyl
 -- record of linear fields.
 import Control.Applicative
+import Control.Lens
+import Control.Monad (when)
 import qualified Data.Foldable as F
 import qualified Data.Vector.Storable as V
 import qualified Data.Vector.Storable.Mutable as VM
@@ -31,24 +33,32 @@
 type MyFields a = [ "pos" ::: V3 a, "tex" ::: V2 a, "normal" ::: V3 a ]
 type MyVertex a = PlainRec (MyFields a)
 
+doubleNviL :: V.Vector (MyVertex Float) -> V.Vector (MyVertex Float)
+doubleNviL = V.map (rLens vNorm . _y *~ (2::Float))
+
+vinylNSumL :: (Num a, Storable a) => V.Vector (MyVertex a) -> a
+vinylNSumL = V.sum . V.map (F.sum . view (rLens vNorm))
+
 doubleNvi :: V.Vector (MyVertex Float) -> V.Vector (MyVertex Float)
-doubleNvi = V.map (rLens vNorm . _y *~ (2::Float))
+doubleNvi = V.map (rMod vNorm (_y *~ (2::Float)))
 
 vinylNSum :: (Num a, Storable a) => V.Vector (MyVertex a) -> a
-vinylNSum = V.sum . V.map (F.sum . view (rLens vNorm))
+vinylNSum = V.sum . V.map (F.sum . rGet vNorm)
 
 main :: IO ()
 main = do vals <- randVecStd $ n * 8 :: IO (V.Vector Float)
           let vinylVerts = V.unsafeCast vals :: V.Vector (MyVertex Float)
               flatVerts = V.unsafeCast vals
               reasVerts = V.unsafeCast vals
-          putStrLn $ "Sanity: " ++ show (vinylNSum $ doubleNvi vinylVerts)
-                     ++ " ==? " ++
-                     show (flatNSum $ doubleNfl flatVerts)
-                     ++ " ==? " ++
-                     show (reasNSum $ doubleNre reasVerts)
+              vinylAns = vinylNSum $ doubleNvi vinylVerts
+              vinylLans = vinylNSumL $ doubleNviL vinylVerts
+              flatAns = flatNSum $ doubleNfl flatVerts
+              reasAns = reasNSum $ doubleNre reasVerts
+          when (any (/= vinylAns) [vinylLans, flatAns, reasAns])
+               (error "Not all versions compute the same answer")
           defaultMain [ bench "flat" $ whnf (flatNSum . doubleNfl) flatVerts
                       , bench "vinyl" $ whnf (vinylNSum . doubleNvi) vinylVerts
+                      , bench "vinyl-lens" $ whnf (vinylNSumL . doubleNviL) vinylVerts
                       , bench "reasonable" $
                         whnf (reasNSum . doubleNre) reasVerts ]
   where n = 1000
diff --git a/tests/Intro.lhs b/tests/Intro.lhs
--- a/tests/Intro.lhs
+++ b/tests/Intro.lhs
@@ -24,7 +24,8 @@
 > import Data.Vinyl.Unicode
 > import Data.Vinyl.Validation
 > import Control.Applicative
-> import Control.Monad.Identity
+> import Control.Lens
+> import Data.Functor.Identity
 > import Data.Char
 > import Test.DocTest
 
@@ -78,7 +79,7 @@
 > -- |
 > -- >>> tucker' ^. rLens sleeping
 > -- False
-> -- 
+> --
 > -- >>> tucker ^. rLens sleeping
 > -- True
 > --
@@ -163,7 +164,7 @@
 > validatePerson p = (\n a -> name =: n <+> age =: a) <$> vName <*> vAge where
 >   vName = validateName (rGet name p)
 >   vAge  = validateAge  (rGet age p)
-> 
+>
 >   validateName str | all isAlpha str = Success str
 >   validateName _ = Failure [ "name must be alphabetic" ]
 >   validateAge i | i >= 0 = Success i
@@ -229,18 +230,18 @@
 So now we have a partial record, and we can still do stuff with its
 contents. Next, we can even recover the original behavior of the
 validator (that is, to give us a value of type `Result [String]
-(PlainRec Person)`) using run:
+(PlainRec Person)`) using `dist`:
 
-> runGoodPerson = run goodPersonResult
-> runBadPerson  = run badPersonResult
+> distGoodPerson = dist goodPersonResult
+> distBadPerson  = dist badPersonResult
 
-`runGoodPerson === Success name :=: "Jon", age :=: 20, {}`
-`runBadPerson  === Failure ["name must be alphabetic"]``
+`distGoodPerson === Success name :=: "Jon", age :=: 20, {}`
+`distBadPerson  === Failure ["name must be alphabetic"]``
 
 > -- |
-> -- >>> isSuccess runGoodPerson
+> -- >>> isSuccess distGoodPerson
 > -- True
-> -- >>> isSuccess runBadPerson
+> -- >>> isSuccess distBadPerson
 > -- False
 
 Fixing a polymorphic record into the Identity Functor
diff --git a/vinyl.cabal b/vinyl.cabal
--- a/vinyl.cabal
+++ b/vinyl.cabal
@@ -1,5 +1,5 @@
 name:                vinyl
-version:             0.1.3
+version:             0.2
 synopsis:            Extensible Records
 -- description:
 license:             MIT
@@ -23,20 +23,20 @@
                        Data.Vinyl.Witnesses, Data.Vinyl.Rec,
                        Data.Vinyl.Relation, Data.Vinyl.Unicode,
                        Data.Vinyl.Classes, Data.Vinyl.Validation
-  build-depends:       base ==4.6.*, lens >=3.8, ghc-prim, mtl
+  build-depends:       base >=4.6 && <= 5, ghc-prim, transformers
   default-language:    Haskell2010
 
 benchmark bench-builder-all
   type:             exitcode-stdio-1.0
   hs-source-dirs:   benchmarks
   main-is:          StorableBench.hs
-  build-depends:    base, vector, criterion, vinyl, mwc-random, linear
+  build-depends:    base >= 4.6 && <= 5, vector, criterion, vinyl, mwc-random, lens, linear
   ghc-options:      -O2 -fllvm
-  default-language: Haskell2010                            
+  default-language: Haskell2010
 
 test-suite doctests
   type:             exitcode-stdio-1.0
   hs-source-dirs:   tests
   main-is:          Intro.lhs
-  build-depends:    base, mtl, vinyl, doctest >= 0.8
+  build-depends:    base >= 4.6 && <= 5, lens, transformers, vinyl, doctest >= 0.8
   default-language: Haskell2010
