diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 0.2.0
+* Type-changing updates
+* Reimplemented the `Record.Types` API
+
+# 0.1.5
+* Fix the range of supported "attoparsec" versions (#6)
+
 # 0.1.4
 * Fix tuples parsing
 
diff --git a/demo/Main.hs b/demo/Main.hs
--- a/demo/Main.hs
+++ b/demo/Main.hs
@@ -28,19 +28,19 @@
 setPersonBirthdayYear =
   set [lens|birthday.year|]
 
-personBirthdayYearLens :: Lens Person Int
+personBirthdayYearLens :: Lens Person Person Int Int
 personBirthdayYearLens =
   [lens|birthday.year|]
 
-personBirthdayYearLens' :: Lens Person Int
+personBirthdayYearLens' :: Lens Person Person Int Int
 personBirthdayYearLens' =
   [lens|birthday|] . [lens|year|]
 
-tupleLens :: Lens (Int, Char, String) String
+tupleLens :: Lens (Int, Char, String) (Int, Char, a) String a
 tupleLens =
   [lens|3|]
 
-mapThirdElement :: (Char -> Char) -> (Int, String, Char) -> (Int, String, Char)
+mapThirdElement :: (Char -> b) -> (Int, String, Char) -> (Int, String, b)
 mapThirdElement =
   over [lens|3|]
 
diff --git a/library/Record.hs b/library/Record.hs
--- a/library/Record.hs
+++ b/library/Record.hs
@@ -106,7 +106,7 @@
 
 renderSingleLens :: T.Text -> Exp
 renderSingleLens =
-  AppE (VarE 'Types.lens) .
+  AppE (VarE 'Types.fieldLens) .
   SigE (ConE 'Types.Field) .
   AppT (ConT ''Types.Field) .
   LitT . StrTyLit . T.unpack
diff --git a/library/Record/Lens.hs b/library/Record/Lens.hs
--- a/library/Record/Lens.hs
+++ b/library/Record/Lens.hs
@@ -11,28 +11,30 @@
 
 
 -- |
--- A reference from a datastructure @s@ to some part @a@,
+-- A reference from a datastructure @s@ to its some part @a@,
 -- which can be used to manipulate that particular part.
-type Lens s a = 
-  forall f. Functor f => (a -> f a) -> (s -> f s)
+-- It is possible to change the part to another type @a'@ during updates.
+-- In such case the whole datastructure will change the type to @s'@ as well.
+type Lens s s' a a' = 
+  forall f. Functor f => (a -> f a') -> (s -> f s')
 
 -- |
 -- Given a lens to a subpart and a datastructure,
 -- produce the value of the referred subpart.
-view :: Lens s a -> s -> a
+view :: Lens s s' a a' -> s -> a
 view l =
   getConst . l Const
 
 -- |
 -- Given a lens to a subpart, a new value for it and a datastructure,
 -- produce an updated datastructure.
-set :: Lens s a -> a -> s -> s
+set :: Lens s s' a a' -> a' -> s -> s'
 set l a =
   runIdentity . l (Identity . const a)
 
 -- |
 -- Given a lens to a subpart, and an update function for it,
 -- produce a function, which updates the datastructure.
-over :: Lens s a -> (a -> a) -> s -> s
+over :: Lens s s' a a' -> (a -> a') -> s -> s'
 over l f =
   runIdentity . l (Identity . f)
diff --git a/library/Record/Types.hs b/library/Record/Types.hs
--- a/library/Record/Types.hs
+++ b/library/Record/Types.hs
@@ -17,30 +17,29 @@
 import Language.Haskell.TH
 
 
+-- *
+-------------------------
+
+
 -- |
--- Defines a way to access some value of a type as a field,
+-- Defines a lens to manipulate some value of a type by a type-level name,
 -- using the string type literal functionality.
 -- 
 -- Instances are provided for all records and for tuples of arity of up to 24.
 -- 
 -- Here's how you can use it with tuples:
 -- 
--- >trd :: FieldOwner "3" v a => a -> v
--- >trd = getField (Field :: Field "3")
--- 
+-- >trd :: FieldLens "3" v v' a' a => a -> v
+-- >trd = view . fieldLens (Field :: Field "3")
 -- The function above will get you the third item of any tuple, which has it.
-class FieldOwner (n :: Symbol) v a | n a -> v where
-  setField :: Field n -> v -> a -> a
-  getField :: Field n -> a -> v
+class FieldLens (n :: Symbol) a a' v v' | n a -> v, n a' -> v', n a v' -> a', n a' v -> a where
+  -- |
+  -- A polymorphic lens. E.g.:
+  -- 
+  -- >ageLens :: FieldLens "age" v v' a' a => Lens a a' v v'
+  -- >ageLens = fieldLens (Field :: Field "age") 
+  fieldLens :: Field n -> Lens a a' v v'
 
--- |
--- Generate a lens using the 'FieldOwner' instance.
--- 
--- >ageLens :: FieldOwner "age" v a => Lens a v
--- >ageLens = lens (Field :: Field "age") 
-lens :: FieldOwner n v a => Field n -> Lens a v
-lens n =
-  \f a -> fmap (\v -> setField n v a) (f (getField n a))
 
 -- |
 -- A specialised version of "Data.Proxy.Proxy".
@@ -48,6 +47,7 @@
 -- since @Proxy@ was only defined in \"base-4.7\".
 data Field (t :: Symbol) = Field
 
+
 -- * Record Types
 -------------------------
 
@@ -77,7 +77,9 @@
       DataD [] typeName varBndrs [NormalC typeName conTypes] derivingNames
 
 
--- Generate Record FieldOwner instances
+-- *
+-------------------------
+
 return $ do
   arity <- [1 .. 24]
   nIndex <- [1 .. arity]
@@ -89,50 +91,58 @@
         mkName $ "n" <> show nIndex
       selectedVVarName =
         mkName $ "v" <> show nIndex
+      selectedV'VarName =
+        mkName $ "v" <> show nIndex <> "'"
       recordType =
         foldl (\a i -> AppT (AppT a (VarT (mkName ("n" <> show i))))
                             (VarT (mkName ("v" <> show i))))
               (ConT typeName)
               [1 .. arity]
-      setFieldLambda =
-        LamE [VarP vVarName, ConP typeName (fmap VarP indexedVVarNames)] exp
+      record'Type =
+        foldl (\a i -> AppT (AppT a (VarT (mkName ("n" <> show i))))
+                            (VarT (if i == nIndex then selectedV'VarName 
+                                                  else mkName ("v" <> show i))))
+              (ConT typeName)
+              [1 .. arity]
+      fieldLensLambda =
+        LamE [VarP fVarName, ConP typeName (fmap VarP indexedVVarNames)] exp
         where
-          vVarName =
-            mkName "v"
+          fVarName =
+            mkName "f"
           indexedVVarNames =
             fmap (\i -> mkName ("v" <> show i)) [1..arity]
           exp =
-            foldl (\a i -> AppE a (VarE (mkName (if i == nIndex then "v" else "v" <> show i))))
-                  (ConE typeName)
-                  [1 .. arity]
-      getFieldLambda =
-        LamE [ConP typeName vPatterns] (VarE (vVarName))
-        where
-          vVarName =
-            mkName "v"
-          vPatterns =
-            flip map [1 .. arity] $ \i ->
-              if i == nIndex
-                then VarP vVarName
-                else WildP
+            AppE (AppE (VarE 'fmap) (consLambda))
+                 (AppE (VarE fVarName) (VarE selectedVVarName))
+            where
+              consLambda =
+                LamE [VarP selectedV'VarName] exp
+                where
+                  exp =
+                    foldl AppE (ConE typeName) $
+                    map VarE $
+                    map (\(i, n) -> if i == nIndex then selectedV'VarName 
+                                                   else mkName ("v" <> show i)) $
+                    zip [1 .. arity] indexedVVarNames
       in
         head $ unsafePerformIO $ runQ $
         [d|
-          instance FieldOwner $(varT selectedNVarName)
-                              $(varT selectedVVarName)
+          instance FieldLens $(varT selectedNVarName)
                               $(pure recordType)
+                              $(pure record'Type)
+                              $(varT selectedVVarName)
+                              $(varT selectedV'VarName)
                               where
-            setField = const $ $(pure setFieldLambda)
-            getField = const $ $(pure getFieldLambda)
+            {-# INLINE fieldLens #-}
+            fieldLens = const $(pure fieldLensLambda)
         |]
 
         
-instance FieldOwner "1" v1 (Identity v1) where
-  setField _ v _ = Identity v
-  getField _ = runIdentity
+instance FieldLens "1" (Identity v1) (Identity v1') v1 v1' where
+  fieldLens = const $ \f -> fmap Identity . f . runIdentity
 
 
--- Generate FieldOwner instances for tuples
+-- Generate FieldLens instances for tuples
 return $ do
   arity <- [2 .. 24]
   nIndex <- [1 .. arity]
@@ -144,38 +154,46 @@
         tupleDataName arity
       selectedVVarName =
         mkName $ "v" <> show nIndex
+      selectedV'VarName =
+        mkName $ "v" <> show nIndex <> "'"
       tupleType =
         foldl (\a i -> AppT a (VarT (mkName ("v" <> show i))))
               (ConT typeName)
               [1 .. arity]
-      setFieldLambda =
-        LamE [VarP vVarName, ConP conName (fmap VarP indexedVVarNames)] exp
+      tuple'Type =
+        foldl (\a i -> AppT a (VarT (if i == nIndex then selectedV'VarName 
+                                                    else mkName ("v" <> show i))))
+              (ConT typeName)
+              [1 .. arity]
+      fieldLensLambda =
+        LamE [VarP fVarName, ConP conName (fmap VarP indexedVVarNames)] exp
         where
-          vVarName =
-            mkName "v"
+          fVarName =
+            mkName "f"
           indexedVVarNames =
             fmap (\i -> mkName ("v" <> show i)) [1..arity]
           exp =
-            foldl (\a i -> AppE a (VarE (mkName (if i == nIndex then "v" else "v" <> show i))))
-                  (ConE conName)
-                  [1 .. arity]
-      getFieldLambda =
-        LamE [ConP conName vPatterns] (VarE (vVarName))
-        where
-          vVarName =
-            mkName "v"
-          vPatterns =
-            flip map [1 .. arity] $ \i ->
-              if i == nIndex
-                then VarP vVarName
-                else WildP
+            AppE (AppE (VarE 'fmap) (consLambda))
+                 (AppE (VarE fVarName) (VarE selectedVVarName))
+            where
+              consLambda =
+                LamE [VarP selectedV'VarName] exp
+                where
+                  exp =
+                    foldl AppE (ConE conName) $
+                    map VarE $
+                    map (\(i, n) -> if i == nIndex then selectedV'VarName 
+                                                   else mkName ("v" <> show i)) $
+                    zip [1 .. arity] indexedVVarNames
       in
         head $ unsafePerformIO $ runQ $
         [d|
-          instance FieldOwner $(pure (LitT (StrTyLit (show nIndex))))
-                              $(varT selectedVVarName)
+          instance FieldLens $(pure (LitT (StrTyLit (show nIndex))))
                               $(pure tupleType)
+                              $(pure tuple'Type)
+                              $(varT selectedVVarName)
+                              $(varT selectedV'VarName)
                               where
-            setField = const $ $(pure setFieldLambda)
-            getField = const $ $(pure getFieldLambda)
+            {-# INLINE fieldLens #-}
+            fieldLens = const $(pure fieldLensLambda)
         |]
diff --git a/record.cabal b/record.cabal
--- a/record.cabal
+++ b/record.cabal
@@ -1,7 +1,7 @@
 name:
   record
 version:
-  0.1.5
+  0.2.0
 synopsis:
   First class records implemented with quasi-quotation
 description:
@@ -45,6 +45,16 @@
     git://github.com/nikita-volkov/record.git
 
 
+flag doctest
+  description: Build Doctests
+  default: True
+  manual: True
+
+flag demo
+  description: Build Demo
+  default: False
+
+
 library
   hs-source-dirs:
     library
@@ -84,24 +94,22 @@
     -threaded
     "-with-rtsopts=-N"
     -funbox-strict-fields
-  build-depends:
-    doctest == 0.9.*,
-    directory == 1.2.*,
-    filepath == 1.3.*,
-    base-prelude,
-    base
   default-extensions:
     Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFunctor, DeriveGeneric, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, ImpredicativeTypes, LambdaCase, LiberalTypeSynonyms, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators
   default-language:
     Haskell2010
+  if !flag(doctest)
+    buildable: False
+  else
+    build-depends:
+      doctest == 0.9.*,
+      directory == 1.2.*,
+      filepath == 1.3.*,
+      base-prelude,
+      base
 
 
--- Well, it's not a benchmark actually, 
--- but in Cabal there's no better way to specify an executable, 
--- which is not intended for distribution.
-benchmark demo
-  type: 
-    exitcode-stdio-1.0
+executable demo
   hs-source-dirs:
     demo
   main-is:
@@ -114,6 +122,10 @@
     -ddump-splices
   default-language:
     Haskell2010
-  build-depends:
-    record,
-    base-prelude
+  if !flag(demo)
+    buildable: False
+  else
+    build-depends:
+      record,
+      base-prelude,
+      base
