diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,26 @@
+# 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
+
+# 1.3
+
+- Depend on `bifunctor-classes-compat` instead of `bifunctors`
+  See changelog note in `bifunctors-5.6`: https://hackage.haskell.org/package/bifunctors-5.6/changelog
+  This is breaking change, but affects only GHC-8.0 and older users.
+  In that case you should check various combinations of newer/older
+  `bifunctors`, `these`, and `semialign` packages.
+
 # 1.2.0.1
 
 -  GHC-9.2 support
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.2.0.1
+version:            1.4
 synopsis:
   Align and Zip type-classes from the common Semialign ancestor.
 
@@ -21,19 +21,17 @@
   forming lattice-like structure.
 
 tested-with:
-    GHC ==7.4.2
-     || ==7.6.3
-     || ==7.8.4
-     || ==7.10.3
-     || ==8.0.2
-     || ==8.2.2
-     || ==8.4.4
-     || ==8.6.5
-     || ==8.8.4
-     || ==8.10.4
-     || ==9.0.1
-     || ==9.2.1
-  , GHCJS ==8.4
+  GHC ==8.6.5
+   || ==8.8.4
+   || ==8.10.7
+   || ==9.0.2
+   || ==9.2.8
+   || ==9.4.8
+   || ==9.6.6
+   || ==9.8.4
+   || ==9.10.1
+   || ==9.12.4
+   || ==9.14.1
 
 source-repository head
   type:     git
@@ -47,10 +45,8 @@
 
 library
   default-language: Haskell2010
-  ghc-options:      -Wall
+  ghc-options:      -Wall -Wno-trustworthy-safe
 
-  if impl(ghc >=8.0)
-    ghc-options: -Wno-trustworthy-safe
   if impl(ghc >=9.2)
     ghc-options: -Wno-noncanonical-monoid-instances
 
@@ -66,41 +62,20 @@
 
   -- ghc boot libs
   build-depends:
-      base          >=4.5.1.0 && <4.17
-    , containers    >=0.4.2.1 && <0.7
-    , transformers  >=0.3.0.0 && <0.7
+      base          >=4.12.0.0 && <4.23
+    , containers    >=0.6.0.1  && <0.9
 
   -- These
-  build-depends:    these >=1.1.1.1 && <1.2
+  build-depends:    these >=1.2.1 && <1.3
 
   -- other dependencies
   build-depends:
-      hashable                       >=1.2.7.0  && <1.5
-    , indexed-traversable            >=0.1.1    && <0.2
-    , indexed-traversable-instances  >=0.1      && <0.2
-    , tagged                         >=0.8.6    && <0.9
+      hashable                       >=1.4.4.0  && <1.6
+    , indexed-traversable            >=0.1.4    && <0.2
+    , indexed-traversable-instances  >=0.1.2    && <0.2
+    , tagged                         >=0.8.8    && <0.9
     , unordered-containers           >=0.2.8.0  && <0.3
-    , vector                         >=0.12.0.2 && <0.13
-
-  -- base shims
-  if !impl(ghc >=8.2)
-    build-depends: bifunctors >=5.5.4 && <5.6
-
-  if !impl(ghc >=8.0)
-    build-depends:
-        semigroups           >=0.18.5  && <0.20
-      , transformers         >=0.3.0.0 && <0.7
-      , transformers-compat  >=0.6.5   && <0.8
-
-    -- Ensure Data.Functor.Classes is always available
-    if impl(ghc >=7.10)
-      build-depends: transformers >=0.4.2.0
-
-  if !impl(ghc >=7.10)
-    build-depends: void >=0.7.3 && <0.8
-
-  if impl(ghc <7.5)
-    build-depends: ghc-prim
+    , vector                         >=0.13.0.0 && <0.14
 
   if flag(semigroupoids)
-    build-depends: semigroupoids >=5.3.2 && <5.4
+    build-depends: semigroupoids >=6.0.1 && <6.1
diff --git a/src/Data/Crosswalk.hs b/src/Data/Crosswalk.hs
--- a/src/Data/Crosswalk.hs
+++ b/src/Data/Crosswalk.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP         #-}
 {-# LANGUAGE Trustworthy #-}
 module Data.Crosswalk (
     -- * Crosswalk
@@ -42,9 +41,7 @@
     sequenceL :: (Align f) => t (f a) -> f (t a)
     sequenceL = crosswalk id
 
-#if __GLASGOW_HASKELL__ >= 707
     {-# MINIMAL crosswalk | sequenceL #-}
-#endif
 
 instance Crosswalk Identity where
     crosswalk f (Identity a) = fmap Identity (f a)
@@ -106,10 +103,7 @@
     bisequenceL :: (Align f) => t (f a) (f b) -> f (t a b)
     bisequenceL = bicrosswalk id id
 
-#if __GLASGOW_HASKELL__ >= 707
     {-# MINIMAL bicrosswalk | bisequenceL #-}
-#endif
-
 
 instance Bicrosswalk Either where
     bicrosswalk f _ (Left x)  = Left  <$> f x
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
@@ -2,18 +2,16 @@
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE FunctionalDependencies     #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE PolyKinds                  #-}
 {-# LANGUAGE StandaloneDeriving         #-}
 {-# LANGUAGE Trustworthy                #-}
 {-# LANGUAGE UndecidableInstances       #-}
-#if __GLASGOW_HASKELL__ >= 706
-{-# LANGUAGE PolyKinds                  #-}
-#endif
 module Data.Semialign.Internal where
 
 import Prelude
        (Bool (..), Either (..), Eq (..), Functor (fmap), Int, Maybe (..),
-       Monad (..), Ord (..), Ordering (..), String, error, flip, fst, id,
-       maybe, snd, uncurry, ($), (++), (.))
+       Monad (..), Ord (..), Ordering (..), String, error, flip, fst, id, maybe,
+       snd, uncurry, ($), (++), (.))
 
 import qualified Prelude as Prelude
 
@@ -45,38 +43,22 @@
 import qualified Data.Vector                       as V
 import qualified Data.Vector.Fusion.Stream.Monadic as Stream
 
-#if MIN_VERSION_vector(0,11,0)
 import           Data.Vector.Fusion.Bundle.Monadic (Bundle (..))
 import qualified Data.Vector.Fusion.Bundle.Monadic as Bundle
 import qualified Data.Vector.Fusion.Bundle.Size    as Bundle
-#else
-import qualified Data.Vector.Fusion.Stream.Size as Stream
-#endif
 
-#if MIN_VERSION_containers(0,5,0)
 import           Data.Map.Lazy (Map)
 import qualified Data.Map.Lazy as Map
 
 import           Data.IntMap.Lazy (IntMap)
 import qualified Data.IntMap.Lazy as IntMap
 
-#if MIN_VERSION_containers(0,5,9)
 import qualified Data.IntMap.Merge.Lazy as IntMap
 import qualified Data.Map.Merge.Lazy    as Map
-#endif
 
--- containers <0.5
-#else
-import           Data.Map (Map)
-import qualified Data.Map as Map
-
-import           Data.IntMap (IntMap)
-import qualified Data.IntMap as IntMap
-#endif
-
 #if !(MIN_VERSION_base(4,16,0))
 import Data.Semigroup (Option (..))
-#endif 
+#endif
 
 import Data.These
 import Data.These.Combinators
@@ -95,7 +77,7 @@
 -- The laws of 'align' and 'zip' resemble lattice laws.
 -- There is a plenty of laws, but they are simply satisfied.
 --
--- And an addition property if @f@ is 'Foldable',
+-- And an additional property if @f@ is 'Foldable',
 -- which tries to enforce 'align'-feel:
 -- neither values are duplicated nor lost.
 --
@@ -139,17 +121,7 @@
 --          ≡ mapMaybe justHere (toList (align x y))
 -- @
 --
---
--- And an addition property if @f@ is 'Foldable',
--- which tries to enforce 'align'-feel:
--- neither values are duplicated nor lost.
---
--- @
--- toList x = toListOf (folded . here) (align x y)
---          = 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)
@@ -160,9 +132,7 @@
     alignWith :: (These a b -> c) -> f a -> f b -> f c
     alignWith f a b = f <$> align a b
 
-#if __GLASGOW_HASKELL__ >= 707
     {-# MINIMAL (align | alignWith) #-}
-#endif
 
 -- | A unit of 'align'.
 --
@@ -186,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,
@@ -206,11 +184,8 @@
     unalignWith :: (c -> These a b) -> f c -> (f a, f b)
     unalignWith f fx = unalign (fmap f fx)
 
-#if __GLASGOW_HASKELL__ >= 707
     {-# MINIMAL unalignWith | unalign #-}
-#endif
 
-
 -- | Functors supporting a 'zip' operation that takes the intersection of
 -- non-uniform shapes.
 --
@@ -294,9 +269,7 @@
     zipWith :: (a -> b -> c) -> f a -> f b -> f c
     zipWith f a b = uncurry f <$> zip a b
 
-#if __GLASGOW_HASKELL__ >= 707
     {-# MINIMAL (zip | zipWith) #-}
-#endif
 
 -- | Zippable functors supporting left and right units
 --
@@ -330,16 +303,14 @@
 --
 -- 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
 
     unzip :: f (a, b) -> (f a, f b)
     unzip = unzipWith id
 
-#if __GLASGOW_HASKELL__ >= 707
     {-# MINIMAL unzipWith | unzip #-}
-#endif
 
 unzipDefault :: Functor f => f (a, b) -> (f a, f b)
 unzipDefault x = (fst <$> x, snd <$> x)
@@ -374,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))
@@ -439,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 []
@@ -460,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
@@ -529,12 +520,8 @@
     nil = Seq.empty
 
 instance Unzip Seq where
-#if MIN_VERSION_containers(0,5,11)
     unzip     = Seq.unzip
     unzipWith = Seq.unzipWith
-#else
-    unzip = unzipDefault
-#endif
 
 instance Zip Seq where
     zip     = Seq.zip
@@ -563,17 +550,9 @@
 -------------------------------------------------------------------------------
 
 instance Ord k => Semialign (Map k) where
-#if MIN_VERSION_containers(0,5,9)
     alignWith f = Map.merge (Map.mapMissing (\_ x ->  f (This x)))
                             (Map.mapMissing (\_ y ->  f (That y)))
                             (Map.zipWithMatched (\_ x y -> f (These x y)))
-#elif MIN_VERSION_containers(0,5,0)
-    alignWith f = Map.mergeWithKey (\_ x y -> Just $ f $ These x y) (fmap (f . This)) (fmap (f . That))
-#else
-    align m n = Map.unionWith merge (Map.map This m) (Map.map That n)
-      where merge (This a) (That b) = These a b
-            merge _ _ = oops "Align Map: merge"
-#endif
 
 instance (Ord k) => Align (Map k) where
     nil = Map.empty
@@ -587,17 +566,9 @@
     zipWith = Map.intersectionWith
 
 instance Semialign IntMap where
-#if MIN_VERSION_containers(0,5,9)
     alignWith f = IntMap.merge (IntMap.mapMissing (\_ x ->  f (This x)))
                                (IntMap.mapMissing (\_ y ->  f (That y)))
                                (IntMap.zipWithMatched (\_ x y -> f (These x y)))
-#elif MIN_VERSION_containers(0,5,0)
-    alignWith f = IntMap.mergeWithKey (\_ x y -> Just $ f $ These x y) (fmap (f . This)) (fmap (f . That))
-#else
-    align m n = IntMap.unionWith merge (IntMap.map This m) (IntMap.map That n)
-      where merge (This a) (That b) = These a b
-            merge _ _ = oops "Align IntMap: merge"
-#endif
 
 instance Align IntMap where
     nil = IntMap.empty
@@ -718,17 +689,19 @@
 -------------------------------------------------------------------------------
 
 -- 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
 
 instance Monad m => Semialign (Stream m) where
-#if MIN_VERSION_vector(0,11,0)
     alignWith  f (Stream stepa ta) (Stream stepb tb)
       = Stream step (ta, tb, Nothing, False)
-#else
-    alignWith  f (Stream stepa ta na) (Stream stepb tb nb)
-      = Stream step (ta, tb, Nothing, False) (Stream.larger na nb)
-#endif
       where
         step (sa, sb, Nothing, False) = do
             r <- stepa sa
@@ -750,21 +723,58 @@
                     _               -> 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
 
-#if MIN_VERSION_vector(0,11,0)
+-- |
+--
+-- @since 1.4
+instance Monad m => Unzip (Bundle m v) where
+    unzip = unzipDefault
+
 instance Monad m => Align (Bundle m v) where
     nil = Bundle.empty
 
 instance Monad m => Semialign (Bundle m v) where
     alignWith f Bundle{sElems = sa, sSize = na} Bundle{sElems = sb, sSize = nb}
       = Bundle.fromStream (alignWith f sa sb) (Bundle.larger na nb)
-#endif
 
 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
 
@@ -776,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
diff --git a/src/Data/Zip.hs b/src/Data/Zip.hs
--- a/src/Data/Zip.hs
+++ b/src/Data/Zip.hs
@@ -50,6 +50,4 @@
     Zippy f <*> Zippy x = Zippy $ zipWith ($) f x
 #endif
 
-#if MIN_VERSION_base(4,10,0)
     liftA2 f (Zippy x) (Zippy y) = Zippy $ zipWith f x y
-#endif
