diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 0.12.0 (2025-03-29)
+* rename `WeakenN` to `SWChain`
+* remove `SWN`, don't like
+* export previous `SWChain` internals `weakenN` and `strengthenN` for magical
+  strongweak chaining (!)
+  * no need to write `weaken . weaken . weaken` when `weakenN @3` will do!
+
+## 0.11.0 (2024-10-17)
+* add `WeakenN` and `SWN` for chaining weakenings
+* clarify instance design: even zero-invariant coercible newtypes aren't allowed
+  to recursively weaken their inner type!
+
+## 0.10.0 (2024-10-13)
+* rename `Weak` to `Weakened`, to separate from `Weak :: Strength`
+* update rerefined dependency
+
 ## 0.9.1 (2024-10-01)
 * update rerefined dependency
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -37,8 +37,8 @@
 
 Let's formalize the above as a pair of types `S` and `W`.
 
-  * Given a `strong :: S`, we can always turn it into a `weak :: W`.
-  * Given a `weak :: W`, we can only turn it into a `strong :: S` if it passes
+  * given a `strong :: S`, we can always turn it into a `weak :: W`
+  * given a `weak :: W`, we can only turn it into a `strong :: S` if it passes
     all the checks
 
 We can write these as pure functions.
@@ -57,8 +57,8 @@
   * `Word8` is a bounded natural number. `Natural` can represent any natural
     number. So `Natural` is a weak type, which can be strengthened into `Word8`
     (or `Word16`, `Word32`, ...) by asserting well-boundedness.
-  * `[a]` doesn't have state any predicates. But we could weaken every `a` in
-    the list. So `[a]` is a strong type, which can be weakened to `[Weak a]`.
+  * `[a]` doesn't state any predicates. But we could weaken every `a` in the
+    list. So `[a]` is a strong type, which can be weakened to `[Weak a]`.
   * `NonEmpty a` *does* have a predicate. For useability and other reasons, we
     only handle this predicate, and don't also weaken each `a` like above.
     `NonEmpty a` weakens to `[a]`.
@@ -77,13 +77,11 @@
 
 ```haskell
 class Weaken a where
-    type Weak a :: Type
+    type Weakened a :: Type
     weaken :: a :: Weak a
 
-type Result = Validation Fails
-type Fails = NeAcc Fail
 class Weaken a => Strengthen a where
-    strengthen :: Weak a -> Result a
+    strengthen :: Weakened a -> Either Failure a
 ```
 
 Note that a strong type may have only one associated weak type. The same weak
@@ -139,6 +137,10 @@
 strengthening may fail while weakening cannot. For safe conversion enumeration
 via typeclasses, consider Taylor Fausak's
 [witch](https://hackage.haskell.org/package/witch) library.
+
+### Not a generic `coerce`
+strongweak isn't intended for automatic `coerce`ing between pairs of types.
+For that, check out `gcoerce` at Lysxia's generic-data package.
 
 ### Not particularly speedy
 The emphasis is on safety, which may come at the detriment of performance:
diff --git a/src/Strongweak.hs b/src/Strongweak.hs
--- a/src/Strongweak.hs
+++ b/src/Strongweak.hs
@@ -10,9 +10,13 @@
 
   -- * Classes
     Weaken(..)
+  , weakenN
   , Strengthen(..)
+  , strengthenN
 
   -- * Other definitions
+  , SWChain(..)
+  , SWCoercibly(..)
   , liftWeakF
 
   -- * Strength switch wrapper
@@ -23,10 +27,12 @@
 
 import Strongweak.Weaken
 import Strongweak.Strengthen
+import Strongweak.Strength
+import Strongweak.Chain
 
 {- $strongweak-instance-design
 
-A given strong type @a@ has exactly one associated weak type @'Weak' a@.
+A given strong type @a@ has exactly one associated weak type @'Weakened' a@.
 Multiple strong types may weaken to the same weak type.
 
 The following laws must hold:
@@ -43,6 +49,12 @@
   * Most (all?) instances should handle (relax or assert) a single invariant.
   * Most instances should not have a recursive context.
 
+If you want to handle multiple invariants, chain the weakens/strengthens.
+You may do this by nesting 'SW' uses, but you will then have to write your own
+instances, as the generics cannot handle such chaining. Alternatively, you may
+use 'WeakenN'. This will add another newtype layer to the strong representation,
+but the generics are happy with it.
+
 Some types may not have any invariants which may be usefully relaxed e.g.
 @'Either' a b@. For these, you may write a recursive instance that
 weakens/strengthens "through" the type e.g. @('Weak' a, 'Weak' b) => Weak
@@ -56,5 +68,4 @@
 a @'Weak' a = a, weaken = id@ overlapping instance, which I do not want. On the
 other hand, @[a]@ /does/ weaken to @['Weak' a]@, because there are no invariants
 present to remove, so decomposing is all the user could hope to do.
-
 -}
diff --git a/src/Strongweak/Chain.hs b/src/Strongweak/Chain.hs
new file mode 100644
--- /dev/null
+++ b/src/Strongweak/Chain.hs
@@ -0,0 +1,45 @@
+module Strongweak.Chain ( SWChain(..), strengthenN ) where
+
+import Strongweak.Weaken ( Weaken(..), WeakenN(weakenN), type WeakenedN )
+import Strongweak.Strengthen ( Strengthen(..), StrengthenN(strengthenN) )
+import GHC.TypeNats ( type Natural )
+
+{- | When weakening (or strengthening), chain the operation @n@ times.
+
+You may achieve this without extra newtypes by nesting uses of
+'Strongweak.Strength.SW'. However, strongweak generics can't handle this,
+forcing you to write manual instances.
+
+'SWChain' provides this nesting behaviour in a type. In return for adding a
+boring newtype layer to the strong representation, you can chain weakening and
+strengthenings without having to write them manually.
+
+The type works as follows:
+
+@
+'Weakened' ('SWChain' 0 a) = a
+'Weakened' ('SWChain' 1 a) = 'Weakened' a
+'Weakened' ('SWChain' 2 a) = 'Weakened' ('Weakened' a)
+'Weakened' ('SWChain' n a) = 'WeakenedN' n a
+@
+
+And so on. (This type is only much use from @n = 2@ onwards.)
+
+You may also use this as a "via" type:
+
+@
+newtype A (s :: 'Strength') = A { a1 :: 'SW' s (Identity ('SW' s Word8)) }
+deriving via 'SWChain' 2 (Identity Word8) instance     'Weaken' (A 'Strong')
+deriving via 'SWChain' 2 (Identity Word8) instance 'Strengthen' (A 'Strong')
+@
+-}
+newtype SWChain (n :: Natural) a = SWChain { unSWChain :: a }
+    deriving stock Show
+    deriving (Ord, Eq) via a
+
+instance WeakenN n a => Weaken (SWChain n a) where
+    type Weakened (SWChain n a) = WeakenedN n a
+    weaken = weakenN @n . unSWChain
+
+instance StrengthenN n a => Strengthen (SWChain n a) where
+    strengthen = fmap SWChain . strengthenN @n
diff --git a/src/Strongweak/Generic.hs b/src/Strongweak/Generic.hs
--- a/src/Strongweak/Generic.hs
+++ b/src/Strongweak/Generic.hs
@@ -11,18 +11,21 @@
     weakenGeneric
   , strengthenGeneric
 
-  -- * Generic wrapper
+  -- * Generic deriving via wrappers
   , GenericallySW(..)
+  , GenericallySW0(..)
   ) where
 
 import Strongweak.Weaken.Generic
 import Strongweak.Strengthen.Generic
 
-import Strongweak.Weaken ( Weaken(Weak, weaken) )
+import Strongweak.Weaken ( Weaken(Weakened, weaken) )
 import Strongweak.Strengthen ( Strengthen(strengthen) )
 import GHC.Generics
 import Data.Kind ( Type )
 
+import Strongweak.Strength
+
 {- $generic-derivation-compatibility
 
 The 'Strengthen' and 'Weaken' generic derivers allow you to derive instances
@@ -30,11 +33,9 @@
 
   * Both types' generic representation (the SOP tree structure) match exactly.
   * For each leaf pair of types, either the types are identical, or the
-  appropriate instance exists to transform from source to target.
+    appropriate instance exists to transform from source to target.
 
-If they aren't compatible, the derivation will fail with a type error. I'm
-fairly certain that if it succeeds, your instance is guaranteed correct
-(assuming the instances it uses internally are all OK!).
+If they aren't compatible, the derivation will fail with a type error.
 
 I don't think GHC strongly guarantees the SOP property, so if you receive
 surprising derivation errors, the types might have differing generic
@@ -46,6 +47,11 @@
 types: for the datatype, constructors and selectors. GHC will always add this
 metadata for you, but manually-derived Generic instances (which are usually a
 bad idea) do not require it.
+
+Note that the generics only handle one "layer" at a time. If you have a data
+type with nested 'Strongweak.Strengthen.SW' uses, these generics will fail with
+a type error. Either use 'Strongweak.WeakenN.WeakenN', or write the instances
+manually.
 -}
 
 {- | @DerivingVia@ wrapper for strongweak instances.
@@ -67,19 +73,15 @@
 deriving via (GenericallySW (XYZ 'Strong) (XYZ 'Weak)) instance Strengthen (XYZ 'Strong)
 @
 
-TODO can't figure out a way around multiple standalone deriving declarations :(
-
-TODO maybe GenericallySW1? but even so instances differ between weaken and
-strengthen (weaken needs nothing) so it's kinda better this way. :)
+Regrettably, use of this requires UndecidableInstances.
 -}
-
 newtype GenericallySW s (w :: Type) = GenericallySW { unGenericallySW :: s }
 
 instance
   ( Generic s, Generic w
   , GWeaken (Rep s) (Rep w)
   ) => Weaken (GenericallySW s w) where
-    type Weak (GenericallySW s w) = w
+    type Weakened (GenericallySW s w) = w
     weaken = weakenGeneric . unGenericallySW
 
 instance
@@ -88,3 +90,25 @@
   , Weaken (GenericallySW s w)
   ) => Strengthen (GenericallySW s w) where
     strengthen = fmap GenericallySW . strengthenGeneric
+
+-- | 'GenericallySW' where the type takes a 'Strength' in its last type var.
+--
+-- Shorter instances for types of a certain shape.
+--
+-- Regrettably, use of this requires UndecidableInstances.
+newtype GenericallySW0 (f :: Strength -> Type)
+  = GenericallySW0 { unGenericallySW0 :: f Strong }
+
+instance
+  ( Generic (f Strong), Generic (f Weak)
+  , GWeaken (Rep (f Strong)) (Rep (f Weak))
+  ) => Weaken (GenericallySW0 f) where
+    type Weakened (GenericallySW0 f) = f Weak
+    weaken = weakenGeneric . unGenericallySW0
+
+instance
+  ( Generic (f Strong), Generic (f Weak)
+  , GStrengthenD (Rep (f Weak)) (Rep (f Strong))
+  , Weaken (GenericallySW0 f)
+  ) => Strengthen (GenericallySW0 f) where
+    strengthen = fmap GenericallySW0 . strengthenGeneric
diff --git a/src/Strongweak/Strength.hs b/src/Strongweak/Strength.hs
new file mode 100644
--- /dev/null
+++ b/src/Strongweak/Strength.hs
@@ -0,0 +1,28 @@
+-- | Definitions using a type-level strength switch.
+
+module Strongweak.Strength where
+
+import Strongweak.Weaken ( type Weakened )
+import Data.Kind ( type Type )
+
+-- | Strength enumeration: it's either strong, or weak.
+--
+-- Primarily interesting at the type level (using DataKinds).
+data Strength = Strong | Weak
+
+{- | Get either the strong or weak representation of a type, depending on the
+     type-level "switch" provided.
+
+This is intended to be used in data types that take a 'Strength' type. Define
+your type using strong fields wrapped in @SW s@. You then get the weak
+representation for free, using the same definition.
+
+@
+data A (s :: Strength) = A
+  { a1 :: SW s Word8
+  , a2 :: String }
+@
+-}
+type family SW (s :: Strength) a :: Type where
+    SW Strong a =          a
+    SW Weak   a = Weakened a
diff --git a/src/Strongweak/Strengthen.hs b/src/Strongweak/Strengthen.hs
--- a/src/Strongweak/Strengthen.hs
+++ b/src/Strongweak/Strengthen.hs
@@ -1,11 +1,14 @@
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE AllowAmbiguousTypes #-} -- StrengthenN, and typeRep'
+-- StrengthenN type families in constraints
+{-# LANGUAGE UndecidableInstances #-}
 
 module Strongweak.Strengthen
   (
   -- * 'Strengthen' class
     Strengthen(..)
   , restrengthen
+  , StrengthenN(strengthenN)
 
   -- ** Helpers
   , strengthenBounded
@@ -17,11 +20,16 @@
   , failStrengthen
 
   -- * Re-exports
-  , Strongweak.Weaken.Weak
+  , Strongweak.Weaken.Weakened
   ) where
 
+import Strongweak.Weaken ( Weaken(Weakened) )
+
+import Strongweak.Weaken ( Weaken(weaken) )
+
+import Strongweak.Weaken ( SWCoercibly(..) )
+
 import Strongweak.Util.TypeNats ( natVal'' )
-import Strongweak.Weaken ( Weaken(..) )
 
 import GHC.TypeNats ( KnownNat )
 import Data.Word
@@ -41,8 +49,13 @@
 
 import Data.Typeable ( Typeable, TypeRep, typeRep, Proxy(Proxy) )
 
-{- | Attempt to strengthen some @'Weak' a@, asserting certain invariants.
+-- for strengthenN
+import GHC.TypeNats ( type Natural, type (-) )
+import Strongweak.Weaken ( type WeakenedN, WeakenN )
+import Unsafe.Coerce ( unsafeCoerce )
 
+{- | Attempt to strengthen some @'Weakened' a@, asserting certain invariants.
+
 We take 'Weaken' as a superclass in order to maintain strong/weak type pair
 consistency. We choose this dependency direction because we treat the strong
 type as the "canonical" one, so 'Weaken' is the more natural (and
@@ -52,9 +65,9 @@
 See "Strongweak" for class design notes and laws.
 -}
 class Weaken a => Strengthen a where
-    -- | Attempt to strengthen some @'Weak' a@ to its associated strong type
+    -- | Attempt to strengthen some @'Weakened' a@ to its associated strong type
     --   @a@.
-    strengthen :: Weak a -> Either StrengthenFailure' a
+    strengthen :: Weakened a -> Either StrengthenFailure' a
 
 -- | Weaken a strong value, then strengthen it again.
 --
@@ -101,6 +114,15 @@
 failStrengthen1 :: [text] -> Either (StrengthenFailure text) a
 failStrengthen1 t = failStrengthen t []
 
+-- TODO add a via type for obtaining strengthen via unsafestrengthen :)
+-- should be permitted only for non-failing, zero invariant strengthens
+
+instance Strengthen (SWCoercibly a) where
+    strengthen = Right . SWCoercibly
+
+deriving via SWCoercibly a instance Strengthen (Identity a)
+deriving via SWCoercibly a instance Strengthen (Const a b)
+
 -- | Strengthen a type by refining it with a predicate.
 instance Refine p a => Strengthen (Refined p a) where
     strengthen = refine .> \case
@@ -140,14 +162,6 @@
             , "fail: wrong length (got "<>TBL.fromDec (length as)<>")" ]
       where n = natVal'' @n
 
--- | Add wrapper.
-instance Strengthen (Identity a) where
-    strengthen = Right . Identity
-
--- | Add wrapper.
-instance Strengthen (Const a b) where
-    strengthen = Right . Const
-
 {- TODO controversial. seems logical, but also kinda annoying.
 instance (Show a, Typeable a) => Strengthen (Maybe a) where
     strengthen = \case [a] -> pure $ Just a
@@ -199,7 +213,7 @@
     strengthen = strengthenList
 
 -- TODO using reverse, SLOW!! >:(
-strengthenList :: Strengthen a => [Weak a] -> Either StrengthenFailure' [a]
+strengthenList :: Strengthen a => [Weakened a] -> Either StrengthenFailure' [a]
 strengthenList = goR (0 :: Int) [] . map strengthen
   where
     goR i as = \case
@@ -244,3 +258,22 @@
 
 typeRep' :: forall a. Typeable a => TypeRep
 typeRep' = typeRep (Proxy @a)
+
+class WeakenN n a => StrengthenN (n :: Natural) a where
+    strengthenN :: WeakenedN n a -> Either StrengthenFailure' a
+
+instance {-# OVERLAPPING #-} StrengthenN 0 a where
+    strengthenN = Right
+
+instance (Strengthen a, StrengthenN (n-1) (Weakened a))
+  => StrengthenN n a where
+    strengthenN a =
+        case strengthenN @(n-1) @(Weakened a) (weakenedNLR1 @n @a a) of
+          Left  e  -> Left e
+          Right sa -> strengthen sa
+
+-- | Inductive 'WeakenedN' case.
+--
+-- @n@ must not be 0.
+weakenedNLR1 :: forall n a. WeakenedN n a -> WeakenedN (n-1) (Weakened a)
+weakenedNLR1 = unsafeCoerce
diff --git a/src/Strongweak/Strengthen/Generic.hs b/src/Strongweak/Strengthen/Generic.hs
--- a/src/Strongweak/Strengthen/Generic.hs
+++ b/src/Strongweak/Strengthen/Generic.hs
@@ -131,7 +131,7 @@
 
 -- | Strengthen a field using the existing 'Strengthen' instance.
 instance
-  ( Weak s ~ w -- has to be here, else "illegal typesym family app in instance"
+  ( Weakened s ~ w -- required, else "illegal typesym family app in instance"
   , Strengthen s
   , ReifySelector i wmr smr
   ) => GStrengthenS i
diff --git a/src/Strongweak/Strengthen/Unsafe.hs b/src/Strongweak/Strengthen/Unsafe.hs
--- a/src/Strongweak/Strengthen/Unsafe.hs
+++ b/src/Strongweak/Strengthen/Unsafe.hs
@@ -1,19 +1,21 @@
 module Strongweak.Strengthen.Unsafe where
 
-import Strongweak.Weaken
+import Strongweak.Weaken ( Weaken(Weakened) )
 import Data.Word
 import Data.Int
 import Rerefined.Refine
 import Data.Vector.Generic.Sized qualified as VGS -- Shazbot!
 import Data.Vector.Generic qualified as VG
 import Data.Vector.Generic.Sized.Internal qualified
-import Data.Functor.Identity
-import Data.Functor.Const
 import Data.List.NonEmpty qualified as NonEmpty
 import Data.List.NonEmpty ( NonEmpty )
 
-{- | Unsafely transform a @'Weak' a@ to an @a@, without asserting invariants.
+import Strongweak.Weaken ( SWCoercibly(..) )
+import Data.Functor.Identity
+import Data.Functor.Const
 
+{- | Unsafely transform a @'Weakened' a@ to an @a@, without asserting invariants.
+
 Naturally, you must only even /consider/ using this if you have a guarantee that
 your value is safe to treat as strong.
 
@@ -31,9 +33,15 @@
 See "Strongweak" for class design notes and laws.
 -}
 class Weaken a => UnsafeStrengthen a where
-    -- | Unsafely transform a @'Weak' a@ to its associated strong type @a@.
-    unsafeStrengthen :: Weak a -> a
+    -- | Unsafely transform a @'Weakened' a@ to its associated strong type @a@.
+    unsafeStrengthen :: Weakened a -> a
 
+instance UnsafeStrengthen (SWCoercibly a) where
+    unsafeStrengthen = SWCoercibly
+
+deriving via SWCoercibly a instance UnsafeStrengthen (Identity a)
+deriving via SWCoercibly a instance UnsafeStrengthen (Const a b)
+
 -- | Add a refinement to a type without checking the associated predicate.
 instance UnsafeStrengthen (Refined p a) where
     unsafeStrengthen = unsafeRefine
@@ -46,14 +54,6 @@
 instance VG.Vector v a => UnsafeStrengthen (VGS.Vector v n a) where
     unsafeStrengthen =
         Data.Vector.Generic.Sized.Internal.Vector . VG.fromList
-
--- | Add wrapper.
-instance UnsafeStrengthen (Identity a) where
-    unsafeStrengthen = Identity
-
--- | Add wrapper.
-instance UnsafeStrengthen (Const a b) where
-    unsafeStrengthen = Const
 
 {- TODO controversial. seems logical, but also kinda annoying.
 -- | Unsafely grab either 0 or 1 elements from a list.
diff --git a/src/Strongweak/Weaken.hs b/src/Strongweak/Weaken.hs
--- a/src/Strongweak/Weaken.hs
+++ b/src/Strongweak/Weaken.hs
@@ -1,15 +1,13 @@
-{-# LANGUAGE UndecidableInstances #-} -- for SWDepth
+{-# LANGUAGE UndecidableInstances #-} -- for WeakenedN
+{-# LANGUAGE AllowAmbiguousTypes #-} -- for weakenN
 
 module Strongweak.Weaken
   (
-  -- * 'Weaken' class
-    Weaken(..)
+    Weaken(Weakened, weaken)
+  , type WeakenedN
+  , WeakenN(weakenN)
   , liftWeakF
-
-  -- * Strength switch helper
-  , Strength(..)
-  , type SW
-  , type SWDepth
+  , SWCoercibly(..)
   ) where
 
 import Rerefined
@@ -24,128 +22,143 @@
 import Data.List.NonEmpty ( NonEmpty )
 import GHC.TypeNats
 
+import Unsafe.Coerce ( unsafeCoerce )
+
 {- | Weaken some @a@, relaxing certain invariants.
 
 See "Strongweak" for class design notes and laws.
 -}
 class Weaken a where
     -- | The weakened type for some type.
-    type Weak a :: Type
-
-    -- | Weaken some @a@ to its associated weak type @'Weak' a@.
-    weaken :: a -> Weak a
+    type Weakened a :: Type
 
--- | Strength enumeration: is it strong, or weak?
---
--- Primarily interesting at the type level (using DataKinds).
-data Strength = Strong | Weak
+    -- | Weaken some @a@ to its associated weak type @'Weakened' a@.
+    weaken :: a -> Weakened a
 
 -- | Lift a function on a weak type to the associated strong type by weakening
 --   first.
-liftWeakF :: Weaken a => (Weak a -> b) -> (a -> b)
+liftWeakF :: Weaken a => (Weakened a -> b) -> a -> b
 liftWeakF f = f . weaken
 
-{- | Get either the strong or weak representation of a type, depending on the
-     type-level "switch" provided.
+-- | The type of @a@ after weakening @n@ times.
+type family WeakenedN (n :: Natural) a :: Type where
+    WeakenedN 0 a = a
+    WeakenedN n a = Weakened (WeakenedN (n-1) a)
 
-This is intended to be used in data types that take a 'Strength' type. Define
-your type using strong fields wrapped in @SW s@. You then get the weak
-representation for free, using the same definition.
+{- | A "via type" newtype for defining strongweak instances for zero-invariant,
+     coercible newtypes.
 
+Use like so:
+
 @
-data A (s :: Strength) = A
-  { a1 :: SW s Word8
-  , a2 :: String }
+deriving 'Weaken' via 'SWCoercibly' a
 @
+
+Or standalone:
+
+@
+via 'SWCoercibly' a instance 'Weaken' ('Identity' a)
+@
+
+Note that usage of this incurs UndecidableInstances. That's life. You can
+write the trivial instances this generates yourself if you so wish.
 -}
-type family SW (s :: Strength) a :: Type where
-    SW 'Strong a = a
-    SW 'Weak   a = Weak a
+newtype SWCoercibly a = SWCoercibly { unSWCoercibly :: a }
+instance Weaken (SWCoercibly a) where
+    type Weakened (SWCoercibly a) = a
+    weaken = unSWCoercibly
 
--- | Track multiple levels of weakening. Silly thought I had, don't think it's
---   useful.
-type family SWDepth (n :: Natural) a :: Type where
-    SWDepth 0 a = a
-    SWDepth n a = Weak (SWDepth (n-1) a)
+deriving via SWCoercibly a instance Weaken (Identity a)
+deriving via SWCoercibly a instance Weaken (Const a b)
 
 -- | Strip refined type refinement.
-instance Weaken (Refined p a) where
-    type Weak (Refined p a) = a
+instance Weaken   (Refined p a) where
+    type Weakened (Refined p a) = a
     weaken = unrefine
 
 -- | Strip refined functor type refinement.
-instance Weaken (Refined1 p f a) where
-    type Weak (Refined1 p f a) = f a
+instance Weaken   (Refined1 p f a) where
+    type Weakened (Refined1 p f a) = f a
     weaken = unrefine1
 
 -- | Weaken non-empty lists into plain lists.
-instance Weaken (NonEmpty a) where
-    type Weak (NonEmpty a) = [a]
+instance Weaken   (NonEmpty a) where
+    type Weakened (NonEmpty a) = [a]
     weaken = NonEmpty.toList
 
 -- | Weaken sized vectors into plain lists.
 instance VG.Vector v a => Weaken (VGS.Vector v n a) where
-    type Weak (VGS.Vector v n a) = [a]
+    type Weakened (VGS.Vector v n a) = [a]
     weaken = VGS.toList
 
--- | Strip wrapper.
-instance Weaken (Identity a) where
-    type Weak (Identity a) = a
-    weaken = runIdentity
-
--- | Strip wrapper.
-instance Weaken (Const a b) where
-    type Weak (Const a b) = a
-    weaken = getConst
-
 {- TODO controversial. seems logical, but also kinda annoying.
 -- | Weaken 'Maybe' (0 or 1) into '[]' (0 to n).
 instance Weaken (Maybe a) where
-    type Weak (Maybe a) = [a]
+    type Weakened (Maybe a) = [a]
     weaken = \case Just a  -> [a]
                    Nothing -> []
 -}
 
 -- Weaken the bounded Haskell numeric types using 'fromIntegral'.
-instance Weaken Word8  where
-    type Weak Word8  = Natural
+instance Weaken   Word8  where
+    type Weakened Word8  = Natural
     weaken = fromIntegral
-instance Weaken Word16 where
-    type Weak Word16 = Natural
+instance Weaken   Word16 where
+    type Weakened Word16 = Natural
     weaken = fromIntegral
-instance Weaken Word32 where
-    type Weak Word32 = Natural
+instance Weaken   Word32 where
+    type Weakened Word32 = Natural
     weaken = fromIntegral
-instance Weaken Word64 where
-    type Weak Word64 = Natural
+instance Weaken   Word64 where
+    type Weakened Word64 = Natural
     weaken = fromIntegral
-instance Weaken Int8   where
-    type Weak Int8   = Integer
+instance Weaken   Int8   where
+    type Weakened Int8   = Integer
     weaken = fromIntegral
-instance Weaken Int16  where
-    type Weak Int16  = Integer
+instance Weaken   Int16  where
+    type Weakened Int16  = Integer
     weaken = fromIntegral
-instance Weaken Int32  where
-    type Weak Int32  = Integer
+instance Weaken   Int32  where
+    type Weakened Int32  = Integer
     weaken = fromIntegral
-instance Weaken Int64  where
-    type Weak Int64  = Integer
+instance Weaken   Int64  where
+    type Weakened Int64  = Integer
     weaken = fromIntegral
 
 --------------------------------------------------------------------------------
 
 -- | Decomposer. Weaken every element in a list.
 instance Weaken a => Weaken [a] where
-    type Weak [a] = [Weak a]
+    type Weakened [a] = [Weakened a]
     weaken = map weaken
 
 -- | Decomposer. Weaken both elements of a tuple.
 instance (Weaken a, Weaken b) => Weaken (a, b) where
-    type Weak (a, b) = (Weak a, Weak b)
+    type Weakened (a, b) = (Weakened a, Weakened b)
     weaken (a, b) = (weaken a, weaken b)
 
 -- | Decomposer. Weaken either side of an 'Either'.
 instance (Weaken a, Weaken b) => Weaken (Either a b) where
-    type Weak (Either a b) = Either (Weak a) (Weak b)
+    type Weakened (Either a b) = Either (Weakened a) (Weakened b)
     weaken = \case Left  a -> Left  $ weaken a
                    Right b -> Right $ weaken b
+
+class WeakenN (n :: Natural) a where
+    weakenN :: a -> WeakenedN n a
+
+-- | Zero case: return the value as-is.
+instance {-# OVERLAPPING #-} WeakenN 0 a where
+    weakenN = id
+
+-- | Inductive case. @n /= 0@, else this explodes.
+instance (Weaken a, WeakenN (n-1) (Weakened a))
+  => WeakenN n a where
+    weakenN a =
+        case weakenN @(n-1) @(Weakened a) (weaken a) of
+          x -> weakenedNRL1 @n @a x
+
+-- | Inverted inductive 'WeakenedN'case.
+--
+-- @n@ must not be 0.
+weakenedNRL1 :: forall n a. WeakenedN (n-1) (Weakened a) -> WeakenedN n a
+weakenedNRL1 = unsafeCoerce
diff --git a/src/Strongweak/Weaken/Generic.hs b/src/Strongweak/Weaken/Generic.hs
--- a/src/Strongweak/Weaken/Generic.hs
+++ b/src/Strongweak/Weaken/Generic.hs
@@ -32,7 +32,7 @@
     gweaken = id
 
 -- | Weaken a field using the existing 'Weaken' instance.
-instance (Weaken s, Weak s ~ w) => GWeaken (Rec0 s) (Rec0 w) where
+instance (Weaken s, Weakened s ~ w) => GWeaken (Rec0 s) (Rec0 w) where
     gweaken = K1 . weaken . unK1
 
 -- | Weaken product types by weakening left and right.
diff --git a/strongweak.cabal b/strongweak.cabal
--- a/strongweak.cabal
+++ b/strongweak.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           strongweak
-version:        0.9.1
+version:        0.12.0
 synopsis:       Convert between strong and weak representations of types
 description:    Please see README.md.
 category:       Data
@@ -30,7 +30,9 @@
 library
   exposed-modules:
       Strongweak
+      Strongweak.Chain
       Strongweak.Generic
+      Strongweak.Strength
       Strongweak.Strengthen
       Strongweak.Strengthen.Generic
       Strongweak.Strengthen.Unsafe
@@ -52,10 +54,10 @@
       TypeFamilies
       DataKinds
       MagicHash
-  ghc-options: -Wall -Wno-unticked-promoted-constructors
+  ghc-options: -fhide-source-paths -Wall
   build-depends:
       base >=4.18 && <5
-    , rerefined >=0.6.0 && <0.7
+    , rerefined >=0.8.0 && <0.9
     , text >=2.0 && <2.2
     , text-builder-linear >=0.1.3 && <0.2
     , vector >=0.12.3.1 && <0.14
@@ -82,7 +84,7 @@
       TypeFamilies
       DataKinds
       MagicHash
-  ghc-options: -Wall -Wno-unticked-promoted-constructors
+  ghc-options: -fhide-source-paths -Wall
   build-tool-depends:
       hspec-discover:hspec-discover >=2.7 && <2.12
   build-depends:
@@ -91,7 +93,7 @@
     , generic-random >=1.5.0.1 && <1.6
     , hspec >=2.7 && <2.12
     , quickcheck-instances >=0.3.26 && <0.4
-    , rerefined >=0.6.0 && <0.7
+    , rerefined >=0.8.0 && <0.9
     , strongweak
     , text >=2.0 && <2.2
     , text-builder-linear >=0.1.3 && <0.2
diff --git a/test/Common.hs b/test/Common.hs
--- a/test/Common.hs
+++ b/test/Common.hs
@@ -14,42 +14,42 @@
 
 data DS (s :: Strength)
   = DS0 (SW s Word8) (SW s Word8) Word8 (SW s Word8) (SW s Word8)
-  | DS1 (SW s (Refined (CompareValue LT Pos 100) Natural))
+  | DS1 (SW s (Refined (CompareValue RelOpLT Pos 100) Natural))
     deriving stock (Generic)
 
-deriving stock instance Eq   (DS 'Strong)
-deriving stock instance Show (DS 'Strong)
-deriving via (GenericArbitraryU `AndShrinking` (DS 'Strong)) instance Arbitrary (DS 'Strong)
+deriving stock instance Eq   (DS Strong)
+deriving stock instance Show (DS Strong)
+deriving via (GenericArbitraryU `AndShrinking` (DS Strong)) instance Arbitrary (DS Strong)
 
-deriving stock instance Eq   (DS 'Weak)
-deriving stock instance Show (DS 'Weak)
-deriving via (GenericArbitraryU `AndShrinking` (DS 'Weak))   instance Arbitrary (DS 'Weak)
+deriving stock instance Eq   (DS Weak)
+deriving stock instance Show (DS Weak)
+deriving via (GenericArbitraryU `AndShrinking` (DS Weak))   instance Arbitrary (DS Weak)
 
-instance Weaken (DS 'Strong) where
-    type Weak   (DS 'Strong) = DS 'Weak
+instance Weaken   (DS Strong) where
+    type Weakened (DS Strong) = DS Weak
     weaken = weakenGeneric
-instance Strengthen (DS 'Strong) where strengthen = strengthenGeneric
+instance Strengthen (DS Strong) where strengthen = strengthenGeneric
 
 data DP (s :: Strength) = DP
   { dp1f0 :: SW s Word32
-  , dp1f1 :: SW s (Refined (CompareValue GT Pos 42) Natural)
+  , dp1f1 :: SW s (Refined (CompareValue RelOpGT Pos 42) Natural)
   , dp1f2 :: SW s Word8
   , dp1f3 :: Word8
   , dp1f4 :: SW s Word8
   } deriving stock (Generic)
 
-deriving stock instance Eq   (DP 'Strong)
-deriving stock instance Show (DP 'Strong)
-deriving via (GenericArbitraryU `AndShrinking` (DP 'Strong)) instance Arbitrary (DP 'Strong)
+deriving stock instance Eq   (DP Strong)
+deriving stock instance Show (DP Strong)
+deriving via (GenericArbitraryU `AndShrinking` (DP Strong)) instance Arbitrary (DP Strong)
 
-deriving stock instance Eq   (DP 'Weak)
-deriving stock instance Show (DP 'Weak)
-deriving via (GenericArbitraryU `AndShrinking` (DP 'Weak))   instance Arbitrary (DP 'Weak)
+deriving stock instance Eq   (DP Weak)
+deriving stock instance Show (DP Weak)
+deriving via (GenericArbitraryU `AndShrinking` (DP Weak))   instance Arbitrary (DP Weak)
 
-instance Weaken     (DP 'Strong) where
-    type Weak (DP 'Strong) = DP 'Weak
+instance Weaken   (DP Strong) where
+    type Weakened (DP Strong) = DP Weak
     weaken = weakenGeneric
-instance Strengthen (DP 'Strong) where strengthen = strengthenGeneric
+instance Strengthen (DP Strong) where strengthen = strengthenGeneric
 
 tryStrengthenSuccessEq :: Eq a => a -> Either StrengthenFailure' a -> Bool
 tryStrengthenSuccessEq a = \case Right a' -> a == a'; Left{} -> False
diff --git a/test/Strongweak/LawsSpec.hs b/test/Strongweak/LawsSpec.hs
--- a/test/Strongweak/LawsSpec.hs
+++ b/test/Strongweak/LawsSpec.hs
@@ -8,11 +8,11 @@
 spec :: Spec
 spec = modifyMaxSize (+1000) $ do
     prop "weaken-strengthen roundtrip isomorphism (generic)" $ do
-      \(d :: DS 'Strong) ->
+      \(d :: DS Strong) ->
         strengthen (weaken d) `shouldSatisfy` tryStrengthenSuccessEq d
     prop "strengthen-weaken-strengthen roundtrip partial isomorphism (generic)" $ do
-      \(dw :: DS 'Weak) ->
-        case strengthen @(DS 'Strong) dw of
+      \(dw :: DS Weak) ->
+        case strengthen @(DS Strong) dw of
           Right ds ->
             strengthen (weaken ds) `shouldSatisfy` tryStrengthenSuccessEq ds
           Left{}  -> pure ()
