diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,27 @@
+0.5.1
+---------
+
+Added utilities for working with the `FieldRec` type.
+
+Vinyl 0.5
+=========
+
+Vinyl 0.5 combines the generality of Vinyl 0.4 with the ease-of-use of previous
+versions by eschewing the defunctionalized type families and just using plain
+type constructors; Vinyl 0.4-style records can be recovered in most cases in a
+modular manner without baking it into the fabric of Vinyl itself.
+
+Also new in 0.5 is a unified lens-based approach to subtyping, coercion and
+projection.
+
+Vinyl 0.4
+=========
+
+Vinyl 0.4 is a big departure from previous versions, in that it introduces a
+universe encoding as a means to generalize the space of keys from strings to
+any arbitrary space. This means that you can have closed universes for your
+records.
+
+For details on how to use the new Vinyl, please see `tests/Intro.lhs` or view
+Jon's talk at BayHac 2014, [Programming in
+Vinyl](http://www.jonmsterling.com/posts/2014-05-19-programming-in-vinyl-bayhac.html).
diff --git a/Data/Vinyl/Core.hs b/Data/Vinyl/Core.hs
--- a/Data/Vinyl/Core.hs
+++ b/Data/Vinyl/Core.hs
@@ -119,6 +119,7 @@
   -> h (Rec g rs)
 rtraverse _ RNil      = pure RNil
 rtraverse f (x :& xs) = (:&) <$> f x <*> rtraverse f xs
+{-# INLINABLE rtraverse #-}
 
 -- | A record with uniform fields may be turned into a list.
 recordToList
@@ -154,7 +155,7 @@
 instance RecAll f rs Show => Show (Rec f rs) where
   show xs =
     (\str -> "{" <> str <> "}")
-      . intercalate "; "
+      . intercalate ", "
       . recordToList
       . rmap (\(Compose (Dict x)) -> Const $ show x)
       $ reifyConstraint (Proxy :: Proxy Show) xs
diff --git a/Data/Vinyl/Derived.hs b/Data/Vinyl/Derived.hs
--- a/Data/Vinyl/Derived.hs
+++ b/Data/Vinyl/Derived.hs
@@ -1,18 +1,63 @@
 {-# LANGUAGE DataKinds  #-}
+{-# LANGUAGE FlexibleInstances  #-}
 {-# LANGUAGE GADTs      #-}
 {-# LANGUAGE PolyKinds  #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
 
 module Data.Vinyl.Derived where
 
+import Data.Proxy
 import Data.Vinyl.Core
 import Data.Vinyl.Functor
-
+import Foreign.Ptr (castPtr)
+import Foreign.Storable
 import GHC.TypeLits
 
 data ElField (field :: (Symbol, *)) where
-  Field :: KnownSymbol s => t -> ElField '(s,t)
+  Field :: KnownSymbol s => !t -> ElField '(s,t)
 
 type FieldRec = Rec ElField
 type HList = Rec Identity
 type LazyHList = Rec Thunk
+
+deriving instance Eq t => Eq (ElField '(s,t))
+deriving instance Ord t => Ord (ElField '(s,t))
+
+instance Show t => Show (ElField '(s,t)) where
+  show (Field x) = (symbolVal (Proxy::Proxy s))++" :-> "++show x
+
+-- | Get the data payload of an 'ElField'.
+getField :: ElField '(s,t) -> t
+getField (Field x) = x
+
+-- | 'ElField' is isomorphic to a functor something like @Compose
+-- ElField ('(,) s)@.
+fieldMap :: (a -> b) -> ElField '(s,a) -> ElField '(s,b)
+fieldMap f (Field x) = Field (f x)
+{-# INLINE fieldMap #-}
+
+-- | Lens for an 'ElField''s data payload.
+rfield :: Functor f => (a -> f b) -> ElField '(s,a) -> f (ElField '(s,b))
+rfield f (Field x) = fmap Field (f x)
+{-# INLINE rfield #-}
+
+-- | Shorthand for a 'FieldRec' with a single field.
+(=:) :: KnownSymbol s => proxy '(s,a) -> a -> FieldRec '[ '(s,a) ]
+(=:) _ x = Field x :& RNil
+
+-- | A proxy for field types.
+data SField (field :: k) = SField
+
+instance Eq (SField a) where _ == _ = True
+instance Ord (SField a) where compare _ _ = EQ
+instance KnownSymbol s => Show (SField '(s,t)) where
+  show _ = "SField "++symbolVal (Proxy::Proxy s)
+
+instance forall s t. (KnownSymbol s, Storable t)
+    => Storable (ElField '(s,t)) where
+  sizeOf _ = sizeOf (undefined::t)
+  alignment _ = alignment (undefined::t)
+  peek ptr = Field `fmap` peek (castPtr ptr)
+  poke ptr (Field x) = poke (castPtr ptr) x
diff --git a/benchmarks/StorableBench.hs b/benchmarks/StorableBench.hs
--- a/benchmarks/StorableBench.hs
+++ b/benchmarks/StorableBench.hs
@@ -11,10 +11,10 @@
 import Control.Lens
 import Control.Monad (when)
 import qualified Data.Foldable as F
+import Data.Proxy
 import qualified Data.Vector.Storable as V
 import qualified Data.Vector.Storable.Mutable as VM
 import Data.Vinyl
-import Data.Vinyl.Universe.Field
 import Foreign.Ptr (castPtr)
 import Foreign.Storable (Storable(..))
 import Linear (V2, V3, _y)
@@ -28,23 +28,23 @@
 randVecStd :: (Storable a, Variate a) => Int -> IO (V.Vector a)
 randVecStd = withSystemRandom . randVec
 
-vNorm :: SField ("normal" ::: V3 a)
-vNorm = SField
+vNorm :: Proxy '("normal", V3 a)
+vNorm = Proxy
 
-type MyFields a = [ "pos" ::: V3 a, "tex" ::: V2 a, "normal" ::: V3 a ]
-type MyVertex a = PlainRec ElField (MyFields a)
+type MyFields a = [ '("pos", V3 a), '("tex", V2 a), '("normal", V3 a) ]
+type MyVertex a = FieldRec (MyFields a)
 
 doubleNviL :: V.Vector (MyVertex Float) -> V.Vector (MyVertex Float)
-doubleNviL = V.map (rLens vNorm . _y *~ (2::Float))
+doubleNviL = V.map (rlens vNorm . rfield . _y *~ (2::Float))
 
 vinylNSumL :: (Num a, Storable a) => V.Vector (MyVertex a) -> a
-vinylNSumL = V.sum . V.map (F.sum . view (rLens vNorm))
+vinylNSumL = V.sum . V.map (F.sum . view (rlens vNorm . rfield))
 
 doubleNvi :: V.Vector (MyVertex Float) -> V.Vector (MyVertex Float)
-doubleNvi = V.map (rMod vNorm (_y *~ (2::Float)))
+doubleNvi = V.map (rlens vNorm . rfield . _y *~ (2::Float))
 
 vinylNSum :: (Num a, Storable a) => V.Vector (MyVertex a) -> a
-vinylNSum = V.sum . V.map (F.sum . rGet vNorm)
+vinylNSum = V.sum . V.map (F.sum . view rfield . rget vNorm)
 
 main :: IO ()
 main = do vals <- randVecStd $ n * 8 :: IO (V.Vector Float)
diff --git a/tests/Intro.lhs b/tests/Intro.lhs
--- a/tests/Intro.lhs
+++ b/tests/Intro.lhs
@@ -47,31 +47,31 @@
 > instance Show (Attr Sleeping) where show (Attr x) = "sleeping: " ++ show x
 > instance Show (Attr Master) where show (Attr x) = "master: " ++ show x
 
-> (=:) :: sing f -> ElF f -> Attr f
-> _ =: x = Attr x
+> (=::) :: sing f -> ElF f -> Attr f
+> _ =:: x = Attr x
 
 > genSingletons [ ''Fields ]
 
 Now, let’s try to make an entity that represents a man:
 
-> jon = (SName =: "jon")
->    :& (SAge =: 23)
->    :& (SSleeping =: False)
+> jon = (SName =:: "jon")
+>    :& (SAge =:: 23)
+>    :& (SSleeping =:: False)
 >    :& RNil
 
 Automatically, we can show the record:
 
 > -- |
 > -- >>> show jon
-> -- "{name: \"jon\"; age: 23; sleeping: False}"
+> -- "{name: \"jon\", age: 23, sleeping: False}"
 
 And its types are all inferred with no problem. Now, make a dog! Dogs are
 life-forms, but unlike men, they have masters. So, let’s build my dog:
 
-> tucker = (SName =: "tucker")
->       :& (SAge =: 9)
->       :& (SSleeping =: True)
->       :& (SMaster =: jon)
+> tucker = (SName =:: "tucker")
+>       :& (SAge =:: 9)
+>       :& (SSleeping =:: True)
+>       :& (SMaster =:: jon)
 >       :& RNil
 
 Using Lenses
@@ -85,7 +85,7 @@
 
 
 > wakeUp :: (Sleeping ∈ fields) => Rec Attr fields -> Rec Attr fields
-> wakeUp = rput $ SSleeping =: False
+> wakeUp = rput $ SSleeping =:: False
 
 Now, the type annotation on wakeUp was not necessary; I just wanted to
 show how intuitive the type is. Basically, it takes as an input any
@@ -110,7 +110,7 @@
 update on a record:
 
 > masterSleeping = rlens SMaster . unAttr . rlens SSleeping
-> tucker'' = masterSleeping .~ (SSleeping =: True) $ tucker'
+> tucker'' = masterSleeping .~ (SSleeping =:: True) $ tucker'
 
 > -- | >>> tucker'' ^. masterSleeping
 > -- sleeping: True
@@ -169,18 +169,18 @@
 left-accumulating `Validation` type.
 
 > goodPerson :: Rec Attr Person
-> goodPerson = (SName =: "Jon")
->           :& (SAge =: 20)
+> goodPerson = (SName =:: "Jon")
+>           :& (SAge =:: 20)
 >           :& RNil
 
-> badPerson = (SName =: "J#@#$on")
->           :& (SAge =: 20)
+> badPerson = (SName =:: "J#@#$on")
+>           :& (SAge =:: 20)
 >           :& RNil
 
 We'll give validation a (rather poor) shot.
 
 > validatePerson :: Rec Attr Person -> Maybe (Rec Attr Person)
-> validatePerson p = (\n a -> (SName =: n) :& (SAge =: a) :& RNil) <$> vName <*> vAge where
+> validatePerson p = (\n a -> (SName =:: n) :& (SAge =:: a) :& RNil) <$> vName <*> vAge where
 >   vName = validateName $ p ^. rlens SName . unAttr
 >   vAge  = validateAge $ p ^. rlens SAge . unAttr
 >
diff --git a/vinyl.cabal b/vinyl.cabal
--- a/vinyl.cabal
+++ b/vinyl.cabal
@@ -1,5 +1,5 @@
 name:                vinyl
-version:             0.5
+version:             0.5.1
 synopsis:            Extensible Records
 -- description:
 license:             MIT
@@ -11,6 +11,7 @@
 stability:           Experimental
 build-type:          Simple
 cabal-version:       >=1.10
+extra-source-files:  CHANGELOG.md
 
 description: Extensible records for Haskell with lenses using modern GHC features.
 
