diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,3 +3,5 @@
 [![CircleCI](https://circleci.com/gh/agrafix/superrecord.svg?style=svg)](https://circleci.com/gh/agrafix/superrecord)
 
 Supercharged anonymous records
+
+For a full introduction and explication please read [this blog post](https://www.athiemann.net/2017/07/02/superrecord.html).
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -1,14 +1,17 @@
+{-# LANGUAGE StandaloneDeriving #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE OverloadedLabels #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE BangPatterns #-}
 import Criterion
 import Criterion.Main
 
 import Control.DeepSeq
 import Data.Aeson
 import GHC.Generics
+import GHC.TypeLits
 import SuperRecord
 import qualified Bookkeeper as B
 import qualified Labels as L
@@ -16,7 +19,7 @@
 data Nested
     = Nested
     { n_f41 :: String
-    } deriving (Generic)
+    } deriving (Read, Generic)
 
 instance NFData Nested
 instance ToJSON Nested
@@ -28,12 +31,48 @@
     , n_f2 :: Int
     , n_f3 :: Bool
     , n_f4 :: Nested
-    } deriving (Generic)
+    } deriving (Read, Generic)
 
 instance NFData Native
 instance ToJSON Native
 instance FromJSON Native
 
+someIntList :: [Int]
+someIntList =
+    read "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]"
+
+data CList a
+    = CList
+    { cl_list :: !(Maybe (a, CList a))
+    } deriving (Show, Eq)
+
+toCList :: [a] -> CList a
+toCList [] = CList Nothing
+toCList (x : xs) = CList (Just (x, toCList xs))
+
+idxC :: Int -> CList a -> Maybe a
+idxC !i c
+    | i <= 0 = fst <$> cl_list c
+    | otherwise =
+          case cl_list c of
+            Just (_, xs) -> idxC (i - 1) xs
+            Nothing -> Nothing
+
+newtype RList a
+    = RList { unRlist :: Rec '[ "list" := Maybe (a, RList a) ] }
+
+toRList :: [a] -> RList a
+toRList [] = RList $ #list := Nothing & rnil
+toRList (x : xs) = RList $ #list := Just (x, toRList xs) & rnil
+
+idxR :: Int -> RList a -> Maybe a
+idxR !i (RList r)
+    | i <= 0 = fst <$> get #list r
+    | otherwise =
+          case get #list r of
+            Just (_, xs) -> idxR (i - 1) xs
+            Nothing -> Nothing
+
 type Ex1 =
     '[ "f1" := String
      , "f2" := Int
@@ -49,6 +88,9 @@
     & #f4 := (#f41 := "abc" & rnil)
     & rnil
 
+
+deriving instance (KnownSymbol a, Read b) => Read ((L.:=) a b )
+
 r1L ::
     ( "f1" L.:= String
     , "f2" L.:= Int
@@ -56,11 +98,9 @@
     , "f4" L.:= ("f41" L.:= String)
     )
 r1L =
-    ( #f1 L.:= "Hi"
-    , #f2 L.:= 213
-    , #f3 L.:= True
-    , #f4 L.:= (#f41 L.:= "abc")
-    )
+    -- needed to prevent unrealistic inlining (normally, data comes from the real world and is
+    -- not statically known at compile time)
+    read "(Proxy := \"Hi\", Proxy := 213, Proxy := True, Proxy := (Proxy := \"abc\"))"
 
 r1B ::
     B.Book
@@ -76,13 +116,11 @@
     B.& #f3 B.=: True
     B.& #f4 B.=: (B.emptyBook B.& #f41 B.=: "abc")
 
+r1N :: Native
 r1N =
-    Native
-    { n_f1 = "Hi"
-    , n_f2 = 213
-    , n_f3 = True
-    , n_f4 = Nested "abc"
-    }
+    -- needed to prevent unrealistic inlining (normally, data comes from the real world and is
+    -- not statically known at compile time)
+    read "Native { n_f1 = \"Hi\", n_f2 = 213, n_f3 = True, n_f4 = Nested { n_f41 = \"Hi\"} }"
 
 main :: IO ()
 main =
@@ -126,6 +164,10 @@
     , bgroup "json"
         [ bench "superrecord" $ nf @[Rec Ex1] (throwOnNone . decode' . encode) $ replicate 50 r1
         , bench "native" $ nf @[Native] (throwOnNone . decode' . encode) $ replicate 50 r1N
+        ]
+    , bgroup "dummy list"
+        [ bench "superrecord" $ nf (idxR 9 . toRList) someIntList
+        , bench "native" $ nf (idxC 9 . toCList) someIntList
         ]
     ]
 
diff --git a/src/SuperRecord.hs b/src/SuperRecord.hs
--- a/src/SuperRecord.hs
+++ b/src/SuperRecord.hs
@@ -21,7 +21,7 @@
 module SuperRecord
     ( -- * Basics
       (:=)(..)
-    , Rec, rnil, rcons, (&)
+    , Record, rnil, rcons, (&)
     , fld
     , Has, HasOf
     , get, (&.)
@@ -30,7 +30,7 @@
     , getPath, setPath, modifyPath, RecApplyPath, (:&), (&:), (&:-)
     , combine, (++:), RecAppend
       -- * Reflection
-    , reflectRec,  RecApply(..)
+    , reflectRec, reflectRecFold, RecApply(..)
       -- * Native type interop
     , FromNative, fromNative
     , ToNative, toNative
@@ -41,8 +41,10 @@
       -- * Lens interop
     , lens
       -- * Machinery
+    , Rec
+    , RecCopy
     , RecTyIdxH
-    , showRec, RecKeys(..)
+    , showRec, RecKeys(..), recKeys
     , RecEq(..)
     , recToValue, recToEncoding
     , recJsonParser, RecJsonParse(..)
@@ -99,7 +101,13 @@
 instance l ~ l' => IsLabel (l :: Symbol) (FldProxy l') where
     fromLabel _ = FldProxy
 
--- | The core record type.
+-- | The core record type. Prefer this type when manually writing type
+-- signatures
+type Record lts = Rec (Sort lts)
+
+-- | Internal record type. When manually writing an explicit type signature for
+-- a record, use 'Record' instead. For abstract type signatures 'Rec' will work
+-- well.
 data Rec (lts :: [*])
    = Rec { _unRec :: SmallArray# Any } -- Note that the values are physically in reverse order
 
@@ -127,8 +135,6 @@
 rnil = unsafeRnil 0
 {-# INLINE rnil #-}
 
--- newByteArray# :: Int# -> State# s -> (#State# s, MutableByteArray# s#)
-
 -- | An empty record with an initial size for the record
 unsafeRnil :: Int -> Rec '[]
 unsafeRnil (I# n#) =
@@ -137,31 +143,61 @@
       (# s'#, arr# #) ->
           case unsafeFreezeSmallArray# arr# s'# of
             (# s''#, a# #) -> (# s''# , Rec a# #)
-
-    -- (A.newArray initSize (error "No Value") >>= A.unsafeFreezeArray)
 {-# INLINE unsafeRnil #-}
 
 -- | Prepend a record entry to a record 'Rec'
 rcons ::
     forall l t lts s.
-    (RecSize lts ~ s, KnownNat s, KeyDoesNotExist l lts)
-    => l := t -> Rec lts -> Rec (l := t ': lts)
-rcons (_ := val) (Rec vec#) =
+    ( RecSize lts ~ s
+    , KnownNat s
+    , KnownNat (RecVecIdxPos l (Sort (l := t ': lts)))
+    , KeyDoesNotExist l lts
+    , RecCopy lts lts (Sort (l := t ': lts))
+    )
+    => l := t -> Rec lts -> Rec (Sort (l := t ': lts))
+rcons (_ := val) lts =
     unsafePerformIO $! IO $ \s# ->
     case newSmallArray# newSize# (error "No value") s# of
       (# s'#, arr# #) ->
-          case copySmallArray# vec# 0# arr# 0# size# s'# of
+          case recCopyInto (Proxy :: Proxy lts) lts (Proxy :: Proxy (Sort (l := t ': lts))) arr# s'# of
             s''# ->
-                case writeSmallArray# arr# size# (unsafeCoerce# val) s''# of
+                case writeSmallArray# arr# setAt# (unsafeCoerce# val) s''# of
                   s'''# ->
                       case unsafeFreezeSmallArray# arr# s'''# of
                         (# s''''#, a# #) -> (# s''''#, Rec a# #)
     where
-        !(I# newSize#) = size + 1
-        !(I# size#) = size
-        size = fromIntegral $ natVal' (proxy# :: Proxy# s)
+        !(I# setAt#) =
+            fromIntegral (natVal' (proxy# :: Proxy# (RecVecIdxPos l (Sort (l := t ': lts)))))
+        newSize# = size# +# 1#
+        !(I# size#) = fromIntegral $ natVal' (proxy# :: Proxy# s)
 {-# INLINE rcons #-}
 
+class RecCopy (pts :: [*]) (lts :: [*]) (rts :: [*]) where
+    recCopyInto ::
+        Proxy pts -> Rec lts -> Proxy rts
+        -> SmallMutableArray# RealWorld Any
+        -> State# RealWorld
+        -> State# RealWorld
+
+instance RecCopy '[] lts rts where
+    recCopyInto _ _ _ _ s# = s#
+
+instance
+    ( Has l rts t
+    , Has l lts t
+    , RecCopy (RemoveAccessTo l (l := t ': pts)) lts rts
+    ) => RecCopy (l := t ': pts) lts rts where
+    recCopyInto _ lts prxy tgt# s# =
+        let lbl :: FldProxy l
+            lbl = FldProxy
+            val = get lbl lts
+            pNext :: Proxy (RemoveAccessTo l (l := t ': pts))
+            pNext = Proxy
+            !(I# setAt#) =
+                fromIntegral (natVal' (proxy# :: Proxy# (RecVecIdxPos l rts)))
+        in case writeSmallArray# tgt# setAt# (unsafeCoerce# val) s# of
+             s'# -> recCopyInto pNext lts prxy tgt# s'#
+
 -- | Prepend a record entry to a record 'Rec'. Assumes that the record was created with
 -- 'unsafeRnil' and still has enough free slots, mutates the original 'Rec' which should
 -- not be reused after
@@ -184,13 +220,30 @@
 -- | Alias for 'rcons'
 (&) ::
     forall l t lts s.
-    (RecSize lts ~ s, KnownNat s, KeyDoesNotExist l lts)
-    => l := t -> Rec lts -> Rec (l := t ': lts)
+    ( RecSize lts ~ s
+    , KnownNat s
+    , KnownNat (RecVecIdxPos l (Sort (l := t ': lts)))
+    , KeyDoesNotExist l lts
+    , RecCopy lts lts (Sort (l := t ': lts))
+    )
+    => l := t -> Rec lts -> Rec (Sort (l := t ': lts))
 (&) = rcons
 {-# INLINE (&) #-}
 
 infixr 5 &
 
+type family Sort (lts :: [*]) where
+    Sort '[] = '[]
+    Sort (x := t ': xs) = SortInsert (x := t) (Sort xs)
+
+type family SortInsert (x :: *) (xs :: [*]) where
+    SortInsert x '[] = x ': '[]
+    SortInsert (x := t) ((y := u) ': ys) = SortInsert' (CmpSymbol x y) (x := t) (y := u) ys
+
+type family SortInsert' (b :: Ordering) (x :: *) (y :: *) (ys :: [*]) where
+    SortInsert' 'LT  x y ys = x ': (y ': ys)
+    SortInsert' _    x y ys = y ': SortInsert x ys
+
 type family KeyDoesNotExist (l :: Symbol) (lts :: [*]) :: Constraint where
     KeyDoesNotExist l '[] = 'True ~ 'True
     KeyDoesNotExist l (l := t ': lts) =
@@ -378,20 +431,24 @@
 -- | Combine two records
 combine ::
     forall lhs rhs.
-    (KnownNat (RecSize lhs), KnownNat (RecSize rhs), KnownNat (RecSize lhs + RecSize rhs))
+    ( KnownNat (RecSize lhs)
+    , KnownNat (RecSize rhs)
+    , KnownNat (RecSize lhs + RecSize rhs)
+    , RecCopy lhs lhs (Sort (RecAppend lhs rhs))
+    , RecCopy rhs rhs (Sort (RecAppend lhs rhs))
+    )
     => Rec lhs
     -> Rec rhs
-    -> Rec (RecAppend lhs rhs)
-combine (Rec l#) (Rec r#) =
-    let !(I# sizeL#) = fromIntegral $ natVal' (proxy# :: Proxy# (RecSize lhs))
-        !(I# sizeR#) = fromIntegral $ natVal' (proxy# :: Proxy# (RecSize rhs))
-        !(I# size#) = fromIntegral $ natVal' (proxy# :: Proxy# (RecSize lhs + RecSize rhs))
+    -> Rec (Sort (RecAppend lhs rhs))
+combine lts rts =
+    let !(I# size#) =
+            fromIntegral $ natVal' (proxy# :: Proxy# (RecSize lhs + RecSize rhs))
     in unsafePerformIO $! IO $ \s# ->
             case newSmallArray# size# (error "No value") s# of
               (# s'#, arr# #) ->
-                  case copySmallArray# r# 0# arr# 0# sizeR# s'# of
+                  case recCopyInto (Proxy :: Proxy lhs) lts (Proxy :: Proxy (Sort (RecAppend lhs rhs))) arr# s'# of
                     s''# ->
-                        case copySmallArray# l# 0# arr# sizeR# sizeL# s''# of
+                        case recCopyInto (Proxy :: Proxy rhs) rts (Proxy :: Proxy (Sort (RecAppend lhs rhs))) arr# s''# of
                           s'''# ->
                               case unsafeFreezeSmallArray# arr# s'''# of
                                 (# s''''#, a# #) -> (# s''''#, Rec a# #)
@@ -400,30 +457,48 @@
 -- | Alias for 'combine'
 (++:) ::
     forall lhs rhs.
-    (KnownNat (RecSize lhs), KnownNat (RecSize rhs), KnownNat (RecSize lhs + RecSize rhs))
+    ( KnownNat (RecSize lhs)
+    , KnownNat (RecSize rhs)
+    , KnownNat (RecSize lhs + RecSize rhs)
+    , RecCopy lhs lhs (Sort (RecAppend lhs rhs))
+    , RecCopy rhs rhs (Sort (RecAppend lhs rhs))
+    )
     => Rec lhs
     -> Rec rhs
-    -> Rec (RecAppend lhs rhs)
+    -> Rec (Sort (RecAppend lhs rhs))
 (++:) = combine
 {-# INLINE (++:) #-}
 
+data RecFields (flds :: [Symbol]) where
+    RFNil :: RecFields '[]
+    RFCons :: KnownSymbol f => FldProxy f -> RecFields xs -> RecFields (f ': xs)
+
+recKeys :: forall t (lts :: [*]). RecKeys lts => t lts -> [String]
+recKeys = recKeys' . recFields
+
+recKeys' :: RecFields lts -> [String]
+recKeys' x =
+    case x of
+      RFNil -> []
+      RFCons q qs -> symbolVal q : recKeys' qs
+
 -- | Get keys of a record on value and type level
 class RecKeys (lts :: [*]) where
     type RecKeysT lts :: [Symbol]
-    recKeys :: t lts -> [String]
+    recFields :: t lts -> RecFields (RecKeysT lts)
 
 instance RecKeys '[] where
     type RecKeysT '[] = '[]
-    recKeys _ = []
+    recFields _ = RFNil
 
 instance (KnownSymbol l, RecKeys lts) => RecKeys (l := t ': lts) where
     type RecKeysT (l := t ': lts) = (l ': RecKeysT lts)
-    recKeys (_ :: f (l := t ': lts)) =
+    recFields (_ :: f (l := t ': lts)) =
         let lbl :: FldProxy l
             lbl = FldProxy
             more :: Proxy lts
             more = Proxy
-        in (symbolVal lbl : recKeys more)
+        in (lbl `RFCons` recFields more)
 
 -- | Apply a function to each key element pair for a record
 reflectRec ::
@@ -433,9 +508,22 @@
     -> Rec lts
     -> [r]
 reflectRec _ f r =
-    recApply (\(Dict :: Dict (c a)) s v -> f s v) r (Proxy :: Proxy lts)
+    reverse $
+    recApply (\(Dict :: Dict (c a)) s v xs -> (f s v : xs)) r (Proxy :: Proxy lts) []
 {-# INLINE reflectRec #-}
 
+-- | Fold over all elements of a record
+reflectRecFold ::
+    forall c r lts. (RecApply lts lts c)
+    => Proxy c
+    -> (forall a. c a => String -> a -> r -> r)
+    -> Rec lts
+    -> r
+    -> r
+reflectRecFold _ f r =
+    recApply (\(Dict :: Dict (c a)) s v x -> f s v x) r (Proxy :: Proxy lts)
+{-# INLINE reflectRecFold #-}
+
 -- | Convert all elements of a record to a 'String'
 showRec :: forall lts. (RecApply lts lts Show) => Rec lts -> [(String, String)]
 showRec = reflectRec @Show Proxy (\k v -> (k, show v))
@@ -455,10 +543,10 @@
 
 -- | Machinery needed to implement 'reflectRec'
 class RecApply (rts :: [*]) (lts :: [*]) c where
-    recApply :: (forall a. Dict (c a) -> String -> a -> r) -> Rec rts -> Proxy lts -> [r]
+    recApply :: (forall a. Dict (c a) -> String -> a -> b -> b) -> Rec rts -> Proxy lts -> b -> b
 
 instance RecApply rts '[] c where
-    recApply _ _ _ = []
+    recApply _ _ _ b = b
 
 instance
     ( KnownSymbol l
@@ -466,14 +554,14 @@
     , Has l rts v
     , c v
     ) => RecApply rts (l := t ': lts) c where
-    recApply f r (_ :: Proxy (l := t ': lts)) =
+    recApply f r (_ :: Proxy (l := t ': lts)) b =
         let lbl :: FldProxy l
             lbl = FldProxy
             val = get lbl r
-            res = f Dict (symbolVal lbl) val
+            res = f Dict (symbolVal lbl) val b
             pNext :: Proxy (RemoveAccessTo l (l := t ': lts))
             pNext = Proxy
-        in (res : recApply f r pNext)
+        in recApply f r pNext res
 
 -- | Machinery to implement equality
 class RecEq (rts :: [*]) (lts :: [*]) where
@@ -558,7 +646,9 @@
 instance
     ( FromNative l lhs
     , FromNative r rhs
-    , lts ~ RecAppend lhs rhs
+    , lts ~ Sort (RecAppend lhs rhs)
+    , RecCopy lhs lhs lts
+    , RecCopy rhs rhs lts
     , KnownNat (RecSize lhs)
     , KnownNat (RecSize rhs)
     , KnownNat (RecSize lhs + RecSize rhs)
diff --git a/superrecord.cabal b/superrecord.cabal
--- a/superrecord.cabal
+++ b/superrecord.cabal
@@ -1,5 +1,5 @@
 name:                superrecord
-version:             0.2.0.0
+version:             0.3.0.0
 synopsis:            Supercharged anonymous records
 description:         Anonymous records with various useful utilities
 homepage:            https://github.com/agrafix/superrecord#readme
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -30,13 +30,13 @@
 type Ex1 =
     '["foo" := String, "int" := Int]
 
-r1 :: Rec Ex1
+r1 :: Record Ex1
 r1 =
     #foo := "Hi"
     & #int := 213
     & rnil
 
-r2 :: Rec '["foo" := String]
+r2 :: Record '["foo" := String]
 r2 = #foo := "He" & rnil
 
 polyFun :: Has "foo" lts String => Rec lts -> String
@@ -46,7 +46,7 @@
 polyFun2 r =
     get #foo r ++ " -> " ++ show (get #bar r)
 
-rNested :: Rec '["foo" := Rec '["bar" := Int] ]
+rNested :: Record '["foo" := Record '["bar" := Int] ]
 rNested =
     #foo := (#bar := 213 & rnil) & rnil
 
@@ -60,7 +60,7 @@
               get #bar (get #foo rNested) `shouldBe` 213
               rNested &. #foo &. #bar `shouldBe` 213
               getPath (#foo &:- #bar) rNested `shouldBe` 213
-       it "hasOf workds" $
+       it "hasOf works" $
            polyFun2 (#foo := "123" & #bar := True & #bim := False & rnil) `shouldBe` "123 -> True"
        it "setter works" $
            do let r1u = set #foo "Hey" r1
@@ -90,6 +90,15 @@
               toNative rb `shouldBe` SomeType "hello" 123
               let rc = (#other := True & #st_bar := 123 & #st_foo := "hello" & rnil)
               toNative rc `shouldBe` SomeType "hello" 123
+       it "can be constructed in any order" $
+           do let areEq =
+                      (#foo := True & #bar := False & rnil)
+                      == (#bar := False & #foo := True & rnil)
+              areEq `shouldBe` True
+              let areNotEq =
+                      (#foo := False & #bar := False & rnil)
+                      == (#bar := False & #foo := True & rnil)
+              areNotEq `shouldBe` False
        it "combine works" $
            do let rc = r1 ++: (#bar := True & rnil)
               rc &. #foo `shouldBe` "Hi"
