diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+# 1.4
+
+- Reorder class hierarchy. `Unzip` is now at the bottom, right above `Functor`.
+  There are two ways things may break:
+  - You may need to add `Unzip` instance if you haven't one already, for example:
+    `instance Unzip ((->) e) where unzip = unzipDefault` was added in this patch.
+  - `Unzip f` doesn't imply whole hierarchy, so you may need to change `Unzip f` to `Zip f`
+    in the constraints of some of your functions.
+- Relax laws of Unalign allowing list-like instances.
+  - Add `Unalign []` and `Unalign Vector` instances.
+
 # 1.3.1
 
 - Support GHC-8.6.5...GHC-9.10.1
diff --git a/semialign.cabal b/semialign.cabal
--- a/semialign.cabal
+++ b/semialign.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               semialign
-version:            1.3.1.1
+version:            1.4
 synopsis:
   Align and Zip type-classes from the common Semialign ancestor.
 
diff --git a/src/Data/Semialign/Internal.hs b/src/Data/Semialign/Internal.hs
--- a/src/Data/Semialign/Internal.hs
+++ b/src/Data/Semialign/Internal.hs
@@ -121,7 +121,7 @@
 --          ≡ mapMaybe justHere (toList (align x y))
 -- @
 --
-class Functor f => Semialign f where
+class Unzip f => Semialign f where
     -- | Analogous to @'zip'@, combines two structures by taking the union of
     --   their shapes and using @'These'@ to hold the elements.
     align :: f a -> f b -> f (These a b)
@@ -156,10 +156,18 @@
 -- == Laws
 --
 -- @
--- uncurry align (unalign xs) ≡ xs
 -- unalign (align xs ys) ≡ (xs, ys)
 -- @
 --
+-- Previously 'Unalign' included a right inverse law
+--
+-- @
+-- uncurry align (unalign xs) ≡ xs
+-- @
+--
+-- But this law was removed in 1.4 to allow list-like instances,
+-- where unalign necessarily loses some information.
+--
 -- == Compatibility note
 --
 -- In version 1 'unalign' was changed to return @(f a, f b)@ pair,
@@ -295,7 +303,7 @@
 --
 -- For sequence-like types this holds, but for Map-like it doesn't.
 --
-class Zip f => Unzip f where
+class Functor f => Unzip f where
     unzipWith :: (c -> (a, b)) -> f c -> (f a, f b)
     unzipWith f = unzip . fmap f
 
@@ -337,6 +345,12 @@
 -- base
 -------------------------------------------------------------------------------
 
+-- |
+--
+-- @since 1.4
+instance Unzip ((->) e) where
+    unzip = unzipDefault
+
 instance Semialign ((->) e) where
     align f g x = These (f x) (g x)
     alignWith h f g x = h (These (f x) (g x))
@@ -402,6 +416,16 @@
 instance Unzip [] where
     unzip = Prelude.unzip
 
+-- |
+--
+-- @since 1.4
+instance Unalign [] where
+    unalign = Prelude.foldr f ([], []) where
+        f :: These a b -> ([a], [b]) -> ([a], [b])
+        f (This x)    ~(xs, ys) = (x : xs,     ys)
+        f (That y)    ~(xs, ys) = (    xs, y : ys)
+        f (These x y) ~(xs, ys) = (x : xs, y : ys)
+
 instance SemialignWithIndex Int []
 instance ZipWithIndex Int []
 instance RepeatWithIndex Int []
@@ -423,6 +447,10 @@
     unzip (ZipList xs) = (ZipList ys, ZipList zs) where
         (ys, zs) = unzip xs
 
+instance Unalign ZipList where
+    unalign (ZipList xs) = (ZipList ys, ZipList zs) where
+        (ys, zs) = unalign xs
+
 instance SemialignWithIndex Int ZipList
 instance ZipWithIndex Int ZipList
 instance RepeatWithIndex Int ZipList
@@ -661,6 +689,13 @@
 -------------------------------------------------------------------------------
 
 -- Based on the Data.Vector.Fusion.Stream.Monadic zipWith implementation
+
+-- |
+--
+-- @since 1.4
+instance Monad m => Unzip (Stream m) where
+    unzip = unzipDefault
+
 instance Monad m => Align (Stream m) where
     nil = Stream.empty
 
@@ -688,9 +723,39 @@
                     _               -> Skip (sa, sb, Nothing, False)
 #endif
 
+-- |
+--
+-- @since 1.4
+instance Monad m => Unalign (Stream m) where
+    unalign (Stream stepa s) = (Stream stepb s, Stream stepc s)
+      where
+        stepb i = do
+            r <- stepa i
+            return $ case r of
+                Done                -> Done
+                Skip              j -> Skip j
+                Yield (This  x)   j -> Yield x j
+                Yield (These x _) j -> Yield x j
+                Yield (That    _) j -> Skip j
+
+        stepc i = do
+            r <- stepa i
+            return $ case r of
+                Done                -> Done
+                Skip              j -> Skip j
+                Yield (This  _)   j -> Skip j
+                Yield (These _ y) j -> Yield y j
+                Yield (That    y) j -> Yield y j
+
 instance Monad m => Zip (Stream m) where
     zipWith = Stream.zipWith
 
+-- |
+--
+-- @since 1.4
+instance Monad m => Unzip (Bundle m v) where
+    unzip = unzipDefault
+
 instance Monad m => Align (Bundle m v) where
     nil = Bundle.empty
 
@@ -701,6 +766,15 @@
 instance Monad m => Zip (Bundle m v) where
     zipWith = Bundle.zipWith
 
+-- |
+--
+-- @since 1.4
+instance Monad m => Unalign (Bundle m v) where
+    unalign Bundle { sElems = xys, sSize = n } =
+        (Bundle.fromStream xs (Bundle.toMax n), Bundle.fromStream ys (Bundle.toMax n))
+      where
+        ~(xs, ys) = unalign xys
+
 instance Semialign V.Vector where
     alignWith = alignVectorWith
 
@@ -712,6 +786,14 @@
 
 instance Unzip V.Vector where
     unzip = V.unzip
+
+-- |
+--
+-- @since 1.4
+instance Unalign V.Vector where
+    -- TODO: it would be more efficient to do unalign imperatively.
+    unalign xys = (unstream xs, unstream ys) where
+        ~(xs, ys) = unalign (stream xys)
 
 alignVectorWith :: (Vector v a, Vector v b, Vector v c)
         => (These a b -> c) -> v a -> v b -> v c
