diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.4.0 (2023-02-22)
+  * redesign some instances to avoid the decomposer style
+    * alter `Identity`, `Const` instances
+    * remove `Maybe` instance
+  * expand sized vector instance
+
 ## 0.3.2 (2022-11-28)
   * support GHC 9.4
 
diff --git a/src/Strongweak.hs b/src/Strongweak.hs
--- a/src/Strongweak.hs
+++ b/src/Strongweak.hs
@@ -13,15 +13,19 @@
 
 {- $strongweak-instance-design
 
-We identify two distinct types of instances for strongweak classes:
+strongweak is largely a programmer convenience library. There is a lot of room
+to write instances which may seem useful on first glance, but are inconsistent
+with the overall design. Here is some relevant guidance.
 
-  * /invariant handler:/ removes or adds an invariant
-  * /decomposer:/ transforms through some structural type
+  * Weak types should have _simpler invariants to manage_ than strong ones.
+  * In general, weak types should be easier to use than strong ones.
+  * Most (all?) instances should handle (relax or assert) a single invariant.
+  * Most instances should not have a recursive context.
 
-In order to provide good behaviour and composability, we don't mix both in a
-single instance. The decomposers are really just convenience to ease instance
-derivation. In general, decomposers will have a recursive context, and invariant
-handlers won't.
+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
+('Either' a b)@). Don't combine the two instance types.
 
 An example is @'Data.List.NonEmpty.NonEmpty' a@. We could weaken this to @[a]@,
 but also to @['Weak' a]@. However, the latter would mean decomposing and
diff --git a/src/Strongweak/Strengthen.hs b/src/Strongweak/Strengthen.hs
--- a/src/Strongweak/Strengthen.hs
+++ b/src/Strongweak/Strengthen.hs
@@ -31,8 +31,8 @@
 import Data.Word
 import Data.Int
 import Refined ( Refined, refine, Predicate )
-import Data.Vector.Sized qualified as Vector
-import Data.Vector.Sized ( Vector )
+import Data.Vector.Generic.Sized qualified as VGS -- Shazbot!
+import Data.Vector.Generic qualified as VG
 import Data.Foldable qualified as Foldable
 import Control.Applicative ( liftA2 )
 import Data.Functor.Identity
@@ -122,27 +122,43 @@
 strengthenFailBase w msg = Failure (e :| [])
   where e = StrengthenFailBase (show $ typeRep @w) (show $ typeRep @s) (show w) msg
 
--- | Obtain a non-empty list by asserting non-emptiness of a plain list.
+-- | Assert a predicate to refine a type.
+instance (Predicate (p :: k) a, Typeable k, Typeable a, Show a) => Strengthen (Refined p a) where
+    strengthen a =
+        case refine a of
+          Left  err -> strengthenFailBase a (show err)
+          Right ra  -> Success ra
+
+-- | Strengthen a plain list into a non-empty list by asserting non-emptiness.
 instance (Typeable a, Show a) => Strengthen (NonEmpty a) where
     strengthen a =
         case NonEmpty.nonEmpty a of
           Just a' -> Success a'
           Nothing -> strengthenFailBase a "empty list"
 
--- | Obtain a sized vector by asserting the size of a plain list.
-instance (KnownNat n, Typeable a, Show a) => Strengthen (Vector n a) where
+-- | Strengthen a plain list into a sized vector by asserting length.
+instance (VG.Vector v a, KnownNat n, Typeable v, Typeable a, Show a)
+  => Strengthen (VGS.Vector v n a) where
     strengthen w =
-        case Vector.fromList w of
+        case VGS.fromList w of
           Nothing -> strengthenFailBase w "TODO bad size vector"
           Just s  -> Success s
 
--- | Obtain a refined type by applying its associated refinement.
-instance (Predicate (p :: k) a, Typeable k, Typeable a, Show a) => Strengthen (Refined p a) where
-    strengthen a =
-        case refine a of
-          Left  err -> strengthenFailBase a (show err)
-          Right ra  -> Success ra
+-- | Add wrapper.
+instance Strengthen (Identity a) where
+    strengthen = pure <$> Identity
 
+-- | Add wrapper.
+instance Strengthen (Const a b) where
+    strengthen = pure <$> Const
+
+{- TODO controversial. seems logical, but also kinda annoying.
+instance (Show a, Typeable a) => Strengthen (Maybe a) where
+    strengthen = \case [a] -> pure $ Just a
+                       []  -> pure Nothing
+                       x   -> strengthenFailBase x "list wasn't [a] or []"
+-}
+
 -- Strengthen 'Natural's into Haskell's bounded unsigned numeric types.
 instance Strengthen Word8  where strengthen = strengthenBounded
 instance Strengthen Word16 where strengthen = strengthenBounded
@@ -173,24 +189,11 @@
 instance Strengthen a => Strengthen [a] where
     strengthen = traverse strengthen
 
--- | Decomposer.
+-- | Decomposer. Strengthen both elements of a tuple.
 instance (Strengthen a, Strengthen b) => Strengthen (a, b) where
     strengthen (a, b) = liftA2 (,) (strengthen a) (strengthen b)
 
--- | Decomposer.
-instance Strengthen a => Strengthen (Maybe a) where
-    strengthen = \case Just a  -> Just <$> strengthen a
-                       Nothing -> pure Nothing
-
--- | Decomposer.
+-- | Decomposer. Strengthen either side of an 'Either'.
 instance (Strengthen a, Strengthen b) => Strengthen (Either a b) where
     strengthen = \case Left  a -> Left  <$> strengthen a
                        Right b -> Right <$> strengthen b
-
--- | Decomposer.
-instance Strengthen a => Strengthen (Identity a) where
-    strengthen = fmap Identity . strengthen . runIdentity
-
--- | Decomposer.
-instance Strengthen a => Strengthen (Const a b) where
-    strengthen = fmap Const . strengthen . getConst
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
@@ -5,9 +5,9 @@
 import Data.Int
 import Refined ( Refined )
 import Refined.Unsafe ( reallyUnsafeRefine )
-import Data.Vector.Sized ( Vector )
+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.Vector qualified
 import Data.Functor.Identity
 import Data.Functor.Const
 import Data.List.NonEmpty qualified as NonEmpty
@@ -37,18 +37,35 @@
     -- | Unsafely transform a weak value to its associated strong one.
     unsafeStrengthen :: Weak a -> a
 
--- | Unsafely assume a list is non-empty.
+-- | Add a refinement to a type without checking the associated predicate.
+instance UnsafeStrengthen (Refined p a) where
+    unsafeStrengthen = reallyUnsafeRefine
+
+-- | Assume a plain list is non-empty.
 instance UnsafeStrengthen (NonEmpty a) where
     unsafeStrengthen = NonEmpty.fromList
 
--- | Unsafely assume the size of a plain list.
-instance UnsafeStrengthen (Vector n a) where
-    unsafeStrengthen = Data.Vector.Generic.Sized.Internal.Vector . Data.Vector.fromList
+-- | Assume the size of a plain list.
+instance VG.Vector v a => UnsafeStrengthen (VGS.Vector v n a) where
+    unsafeStrengthen =
+        Data.Vector.Generic.Sized.Internal.Vector . VG.fromList
 
--- | Wrap a value to a refined one without checking the predicate.
-instance UnsafeStrengthen (Refined p a) where
-    unsafeStrengthen = reallyUnsafeRefine
+-- | 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.
+instance UnsafeStrengthen (Maybe a) where
+    unsafeStrengthen = \case [a] -> Just a
+                             []  -> Nothing
+                             _   -> error "your list wasn't [] or [a]"
+-}
+
 -- Coerce 'Natural's into Haskell's bounded unsigned numeric types. Poorly-sized
 -- values will safely overflow according to the type's behaviour.
 instance UnsafeStrengthen Word8  where unsafeStrengthen = fromIntegral
@@ -69,24 +86,13 @@
 instance UnsafeStrengthen a => UnsafeStrengthen [a] where
     unsafeStrengthen = map unsafeStrengthen
 
--- | Decomposer.
-instance (UnsafeStrengthen a, UnsafeStrengthen b) => UnsafeStrengthen (a, b) where
+-- | Decomposer. Unsafely strengthen both elements of a tuple.
+instance (UnsafeStrengthen a, UnsafeStrengthen b)
+  => UnsafeStrengthen (a, b) where
     unsafeStrengthen (a, b) = (unsafeStrengthen a, unsafeStrengthen b)
 
--- | Decomposer.
-instance UnsafeStrengthen a => UnsafeStrengthen (Maybe a) where
-    unsafeStrengthen = \case Just a  -> Just $ unsafeStrengthen a
-                             Nothing -> Nothing
-
--- | Decomposer.
-instance (UnsafeStrengthen a, UnsafeStrengthen b) => UnsafeStrengthen (Either a b) where
+-- | Decomposer. Unsafely strengthen either side of an 'Either'.
+instance (UnsafeStrengthen a, UnsafeStrengthen b)
+  => UnsafeStrengthen (Either a b) where
     unsafeStrengthen = \case Left  a -> Left  $ unsafeStrengthen a
                              Right b -> Right $ unsafeStrengthen b
-
--- | Decomposer.
-instance UnsafeStrengthen a => UnsafeStrengthen (Identity a) where
-    unsafeStrengthen = Identity . unsafeStrengthen . runIdentity
-
--- | Decomposer.
-instance UnsafeStrengthen a => UnsafeStrengthen (Const a b) where
-    unsafeStrengthen = Const . unsafeStrengthen . getConst
diff --git a/src/Strongweak/Weaken.hs b/src/Strongweak/Weaken.hs
--- a/src/Strongweak/Weaken.hs
+++ b/src/Strongweak/Weaken.hs
@@ -13,8 +13,8 @@
 import Numeric.Natural ( Natural )
 import Data.Word
 import Data.Int
-import Data.Vector.Sized qualified as Vector
-import Data.Vector.Sized ( Vector )
+import Data.Vector.Generic.Sized qualified as VGS -- Shazbot!
+import Data.Vector.Generic qualified as VG
 import Data.Kind ( Type )
 import Data.Functor.Identity
 import Data.Functor.Const
@@ -26,9 +26,14 @@
 A given strong type @a@ has exactly one associated weak type @'Weak' a@.
 Multiple strong types may weaken to the same weak type.
 
-Law: @a === b -> 'weaken' a === 'weaken' b@
+The following laws must hold:
 
-Instances should /either/ handle an invariant, or decompose. See "Strongweak"
+  * @a == b |= 'weaken' a == 'weaken' b@
+  * round-trip: @'strengthen' ('weaken' a) == 'pure' a@
+
+Most instances should strip an invariant, and not have a recursive context. Some
+types don't have an invariant
+/either/ handle an invariant, or decompose. See "Strongweak"
 for a discussion on this design.
 -}
 class Weaken a where
@@ -64,21 +69,39 @@
     SW 'Strong a = a
     SW 'Weak   a = Weak a
 
+-- | Strip refined type refinement.
+instance Weaken (Refined p a) where
+    type Weak (Refined p a) = a
+    weaken = unrefine
+
 -- | Weaken non-empty lists into plain lists.
 instance Weaken (NonEmpty a) where
     type Weak (NonEmpty a) = [a]
     weaken = NonEmpty.toList
 
 -- | Weaken sized vectors into plain lists.
-instance Weaken (Vector n a) where
-    type Weak (Vector n a) = [a]
-    weaken = Vector.toList
+instance VG.Vector v a => Weaken (VGS.Vector v n a) where
+    type Weak (VGS.Vector v n a) = [a]
+    weaken = VGS.toList
 
--- | Strip the refinement from refined types.
-instance Weaken (Refined p a) where
-    type Weak (Refined p a) = a
-    weaken = unrefine
+-- | 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]
+    weaken = \case Just a  -> [a]
+                   Nothing -> []
+-}
+
 -- Weaken the bounded Haskell numeric types using 'fromIntegral'.
 instance Weaken Word8  where
     type Weak Word8  = Natural
@@ -112,29 +135,13 @@
     type Weak [a] = [Weak a]
     weaken = map weaken
 
--- | Decomposer.
+-- | Decomposer. Weaken both elements of a tuple.
 instance (Weaken a, Weaken b) => Weaken (a, b) where
     type Weak (a, b) = (Weak a, Weak b)
     weaken (a, b) = (weaken a, weaken b)
 
--- | Decomposer.
-instance Weaken a => Weaken (Maybe a) where
-    type Weak (Maybe a) = Maybe (Weak a)
-    weaken = \case Just a  -> Just $ weaken a
-                   Nothing -> Nothing
-
--- | Decomposer.
+-- | 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)
     weaken = \case Left  a -> Left  $ weaken a
                    Right b -> Right $ weaken b
-
--- | Decomposer.
-instance Weaken a => Weaken (Identity a) where
-    type Weak (Identity a) = Identity (Weak a)
-    weaken = Identity . weaken . runIdentity
-
--- | Decomposer.
-instance Weaken a => Weaken (Const a b) where
-    type Weak (Const a b) = Const (Weak a) b
-    weaken = Const . weaken . getConst
diff --git a/strongweak.cabal b/strongweak.cabal
--- a/strongweak.cabal
+++ b/strongweak.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.35.0.
+-- This file has been generated from package.yaml by hpack version 0.35.2.
 --
 -- see: https://github.com/sol/hpack
 
 name:           strongweak
-version:        0.3.2
+version:        0.4.0
 synopsis:       Convert between strong and weak representations of types
 description:    Please see README.md.
 category:       Data
