diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 0.2.1.0
+
+- Add `toORLazy` and `fromORLazy`, to clean up data types with strictness
+  annotations. (Thanks to blmage.)
+
 # 0.2.0.0
 
 - Compatibility with generic-data 0.4.0.0
diff --git a/generic-data-surgery.cabal b/generic-data-surgery.cabal
--- a/generic-data-surgery.cabal
+++ b/generic-data-surgery.cabal
@@ -1,5 +1,5 @@
 name:                generic-data-surgery
-version:             0.2.0.0
+version:             0.2.1.0
 synopsis:            Surgery for generic data types
 description:
   Transform data types before passing them to generic functions.
diff --git a/src/Generic/Data/Surgery.hs b/src/Generic/Data/Surgery.hs
--- a/src/Generic/Data/Surgery.hs
+++ b/src/Generic/Data/Surgery.hs
@@ -4,9 +4,9 @@
 -- Functions in this module are expected to be used with visible type
 -- applications. Surgeries have a lot of type parameters, but usually only the
 -- first one to three type arguments need to be passed via @TypeApplications@.
--- Functions are annotated with \"functional dependencies\", with a meaning
--- similar to the homonymous GHC extension for type classes (click on
--- \"Details\" under each function to see those).
+-- Functions are documented with informal \"functional dependencies\",
+-- clarifying which type parameters can be inferred from which others
+-- (click on \"Details\" under each function to see those).
 --
 -- Remember that not all parameters to the left of a functional dependency
 -- arrow need to be annotated explicitly to determine those on the right. Some
@@ -21,9 +21,9 @@
     -- has a "Generic.Data.Microsurgery" module (since 0.4.0.0) to modify some
     -- metadata of generic representations.
     --
-    -- See also the documentation in that module about surgeries using
-    -- <https://hackage.haskell.org/package/generic-data generic-lens>,
-    -- when you want to /update/ fields, rather than remove or insert them.
+    -- If you only want to /update/ fields, rather than remove or insert them,
+    -- see also the documentation in the above module, on making surgeries out of
+    -- <https://hackage.haskell.org/package/generic-data generic-lens>.
 
     -- * Synthetic data types
 
@@ -44,6 +44,11 @@
 
   , OROf
 
+  , toORLazy
+  , fromORLazy
+
+  , OROfLazy
+
     -- ** Unnamed fields
   , removeCField
   , insertCField
@@ -87,8 +92,12 @@
 
   , ToORRep
   , ToOR
+  , ToORRepLazy
+  , ToORLazy
   , FromORRep
   , FromOR
+  , FromORRepLazy
+  , FromORLazy
 
     -- ** Surgeries
 
diff --git a/src/Generic/Data/Surgery/Internal.hs b/src/Generic/Data/Surgery/Internal.hs
--- a/src/Generic/Data/Surgery/Internal.hs
+++ b/src/Generic/Data/Surgery/Internal.hs
@@ -48,12 +48,33 @@
 --
 -- @x@ corresponds to the last parameter of 'Rep', and is currently ignored by
 -- this module (no support for 'Generic1').
+--
+-- === General sketch
+--
+-- >
+-- >                toOR                       surgeries                    fromOR'
+-- > data MyType  -------->  OR (Rep MyType)  ---------->  OR alteredRep  --------->  Data alteredRep
+-- >                                                                                        |
+-- >                                                                                        | myGenericFun :: Generic a => a -> a
+-- >                fromOR                     surgeries                    toOR'           v
+-- > data MyType  <--------  OR (Rep MyType)  <----------  OR alteredRep  <---------  Data alteredRep
+-- >
+--
+-- If instead @myGenericFun@ is only a consumer of @a@ (resp. producer),
+-- then you only need the top half of the diagram (resp. bottom half).
+-- For example, in aeson:
+-- @genericToJSON@ (consumer), @genericParseJSON@ (producer).
 newtype OR (l :: k -> Type) (x :: k) = OR { unOR :: l x }
 
 -- | /Move fresh data to the Operating Room, where surgeries can be applied./
 --
 -- Convert a generic type to a generic representation.
 --
+-- When inserting or removing fields, there may be a mismatch with strict/unpacked fields.
+-- To work around this, you can switch to 'toORLazy', if your operations don't care about
+-- dealing with a normalized 'Rep' (in which all the strictness annotations have been
+-- replaced with lazy defaults).
+--
 -- === __Details__
 --
 -- ==== Type parameters
@@ -72,6 +93,32 @@
 toOR :: forall a l x. (Generic a, ToORRep a l) => a -> OR l x
 toOR = OR . gLinearize . from
 
+-- | /Move normalized data to the Operating Room, where surgeries can be applied./
+--
+-- Convert a generic type to a generic representation, in which all the strictness
+-- annotations have been normalized to lazy defaults.
+--
+-- This variant is useful when one needs to operate on fields whose 'Rep' has different
+-- strictness annotations than the ones used by 'DefaultMetaSel'.
+--
+-- === __Details__
+--
+-- ==== Type parameters
+--
+-- @
+-- a :: 'Type'       -- Generic type
+-- l :: k -> 'Type'  -- Generic representation (simplified and normalized)
+-- x :: k          -- Ignored
+-- @
+--
+-- ==== Functional dependencies
+--
+-- @
+-- a -> l
+-- @
+toORLazy :: forall a l x. (Generic a, ToORRepLazy a l) => a -> OR l x
+toORLazy = OR . gLinearize @(Arborify l) . coerce' . from
+
 -- | /Move altered data out of the Operating Room, to be consumed by/
 -- /some generic function./
 --
@@ -142,6 +189,11 @@
 -- 'fromOR' \@a  -- with TypeApplications
 -- @
 --
+-- When inserting or removing fields, there may be a mismatch with strict/unpacked fields.
+-- To work around this, you can switch to 'fromORLazy', if your operations don't care
+-- about dealing with a normalized 'Rep' (in which all the strictness annotations have
+-- been replaced with lazy defaults).
+--
 -- === __Details__
 --
 -- ==== Type parameters
@@ -160,10 +212,46 @@
 fromOR :: forall a l x. (Generic a, FromORRep a l) => OR l x -> a
 fromOR = to . gArborify . unOR
 
+-- | /Move normalized data out of the Operating Room and back to the real/
+-- /world./
+--
+-- The inverse of 'toORLazy'.
+--
+-- It may be useful to annotate the output type of 'fromORLazy',
+-- since the rest of the type depends on it and the only way to infer it
+-- otherwise is from the context. The following annotations are possible:
+--
+-- @
+-- 'fromORLazy' :: 'OROfLazy' a -> a
+-- 'fromORLazy' \@a  -- with TypeApplications
+-- @
+--
+-- === __Details__
+--
+-- ==== Type parameters
+--
+-- @
+-- a :: 'Type'       -- Generic type
+-- l :: k -> 'Type'  -- Generic representation (simplified and normalized)
+-- x :: k          -- Ignored
+-- @
+--
+-- ==== Functional dependencies
+--
+-- @
+-- a -> l
+-- @
+fromORLazy :: forall a l x. (Generic a, FromORRepLazy a l) => OR l x -> a
+fromORLazy = to . coerce' . gArborify @(Lazify (Rep a)) . unOR
+
 -- | The simplified generic representation type of type @a@,
 -- that 'toOR' and 'fromOR' convert to and from.
 type OROf a = OR (Linearize (Rep a)) ()
 
+-- | The simplified and normalized generic representation type of type @a@,
+-- that 'toORLazy' and 'fromORLazy' convert to and from.
+type OROfLazy a = OR (Linearize (Lazify (Rep a))) ()
+
 -- | This constraint means that @a@ is convertible /to/ its simplified
 -- generic representation. Implies @'OROf' a ~ 'OR' l ()@.
 type   ToORRep a l =   ToOR (Rep a) l
@@ -180,6 +268,26 @@
 -- generic representation of @a@ directly, @f ~ 'Rep' a@.
 type FromOR f l = (GArborify  f, Linearize f ~ l, f ~ Arborify l)
 
+-- | This constraint means that @a@ is convertible /to/ its simplified
+-- and normalized generic representation (i.e., with all its strictness
+-- annotations normalized to lazy defaults).
+-- Implies @'OROfLazy' a ~ 'OR' l ()@.
+type   ToORRepLazy a l =   ToORLazy (Rep a) l
+
+-- | This constraint means that @a@ is convertible /from/ its simplified
+-- and normalized generic representation (i.e., with all its strictness
+-- annotations normalized to lazy defaults).
+-- Implies @'OROfLazy' a ~ 'OR' l ()@.
+type FromORRepLazy a l = FromORLazy (Rep a) l
+
+-- | Similar to 'FromLazyORRep', but as a constraint on the standard
+-- generic representation of @a@ directly, @f ~ 'Rep' a@.
+type FromORLazy f l = (FromOR (Lazify f) l, Coercible (Arborify l) f)
+
+-- | Similar to 'ToORRepLazy', but as a constraint on the standard
+-- generic representation of @a@ directly, @f ~ 'Rep' a@.
+type   ToORLazy f l = (ToOR (Lazify f) l, Coercible f (Arborify l))
+
 --
 
 -- | @'removeCField' \@n \@t@: remove the @n@-th field, of type @t@, in a
@@ -865,6 +973,20 @@
    <=< Bimap (arb nDiv2) (arb (n-nDiv2))
    <=< SplitAt nDiv2
    ) (op f g)
+
+type family Lazify (f :: k -> *) :: k -> *
+type instance Lazify (M1 i m f) = M1 i (LazifyMeta m) (Lazify f)
+type instance Lazify (f :*: g) = Lazify f :*: Lazify g
+type instance Lazify (f :+: g) = Lazify f :+: Lazify g
+type instance Lazify (K1 i c) = K1 i c
+type instance Lazify U1 = U1
+type instance Lazify V1 = V1
+
+type family LazifyMeta (m :: Meta) :: Meta
+type instance LazifyMeta ('MetaData n m p nt) = 'MetaData n m p nt
+type instance LazifyMeta ('MetaCons n f s) = 'MetaCons n f s
+type instance LazifyMeta ('MetaSel mn su ss ds)
+  = 'MetaSel mn 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy
 
 data SplitAt :: Nat -> (k -> *) -> (k -> *, k -> *) -> *
 type instance Eval (SplitAt n (f :+: g)) =
diff --git a/test/surgery.hs b/test/surgery.hs
--- a/test/surgery.hs
+++ b/test/surgery.hs
@@ -25,6 +25,7 @@
 
 data P = P Int Int Int deriving (Eq, Show, Generic)
 data R = R { u, v, w :: Int } deriving (Eq, Show, Generic)
+data S = S { u' :: Int, v' :: !Int, w' :: {-# UNPACK #-} !Int } deriving (Eq, Show, Generic)
 
 main :: IO ()
 main = defaultMain test
@@ -56,6 +57,10 @@
       rt (R 1 2 3) (fromOR . insertRField @"u" . removeRField @"u" . toOR)
   , testCase "RField-ins-rmv" $
       rt ((), R 1 2 3) (fmap fromOR . removeRField @"t" . insertRField @"t" @1 . fmap toOR)
+  , testCase "SField-rmv-ins" $
+      rt (S 1 2 3) (fromORLazy . insertRField @"u'" . removeRField @"u'" . toORLazy)
+  , testCase "SField-ins-rmv" $
+      rt ((), S 1 2 3) (fmap fromORLazy . removeRField @"t" . insertRField @"t" @1 . fmap toORLazy)
 -- Type error on 8.0
 #if __GLASGOW_HASKELL__ >= 802
   , testCase "Constr-rmv-ins" $
@@ -76,6 +81,10 @@
       "R {u = 1, w = 3}" @?=
       (show' . fromOR' . snd . removeRField @"v" . toOR) (R 1 2 3)
 
+  , testCase "removeSField" $
+      "S {u' = 1, w' = 3}" @?=
+      (show' . fromOR' . snd . removeRField @"v'" . toORLazy) (S 1 2 3)
+
   , testCase "insertCField" $
       "P 1 () 2 3" @?=
       (show' . fromOR' . insertCField' @1 () . toOR) (P 1 2 3)
@@ -84,6 +93,10 @@
       "R {u = 1, n = (), v = 2, w = 3}" @?=
       (show' . fromOR' . insertRField' @"n" @1 () . toOR) (R 1 2 3)
 
+  , testCase "insertSField" $
+      "S {u' = 1, n' = (), v' = 2, w' = 3}" @?=
+      (show' . fromOR' . insertRField' @"n'" @1 () . toORLazy) (S 1 2 3)
+
 -- Loops on 8.0
 #if __GLASGOW_HASKELL__ >= 802
     -- N.B. Identity (for constructor B) is inferred.
@@ -107,13 +120,21 @@
       R 0 0 0 @?=
         (fromOR . snd . removeRField @"v" @1 @[Int] . toOR') def
 
+  , testCase "removeSField" $
+      S 0 0 0 @?=
+        (fromORLazy . snd . removeRField @"v'" @1 @[Int] . toOR') def
+
   , testCase "insertCField" $
       P 0 9 0 @?=
         (fromOR . insertCField' @1 9 . toOR') def
 
-  , testCase "insertCField" $
+  , testCase "insertRField" $
       R 0 9 0 @?=
         (fromOR . insertRField' @"v" 9 . toOR') def
+
+  , testCase "insertSField" $
+      S 0 9 0 @?=
+        (fromORLazy . insertRField' @"v'" 9 . toOR') def
 
   , testCase "removeConstr" $
       Right A @?=
