diff --git a/dimensions.cabal b/dimensions.cabal
--- a/dimensions.cabal
+++ b/dimensions.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.24
 
--- This file has been generated from package.yaml by hpack version 0.31.1.
+-- This file has been generated from package.yaml by hpack version 0.33.0.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 02a12f73c300d1f3b4ea569d86f2222327243c0918b00236786ba647754dd7f2
+-- hash: a3d908cd322660cc66050ec6ff0cfebdacab86ed83cade5c01792c40bbe8c659
 
 name:           dimensions
-version:        2.1.0.0
+version:        2.1.1.0
 synopsis:       Safe type-level dimensionality for multidimensional data.
 description:    Safe type-level dimensionality for multidimensional data. Please see the README on GitHub at <https://github.com/achirkin/easytensor#readme>
 category:       math, geometry
diff --git a/src/Data/Type/List/Classes.hs b/src/Data/Type/List/Classes.hs
--- a/src/Data/Type/List/Classes.hs
+++ b/src/Data/Type/List/Classes.hs
@@ -410,7 +410,7 @@
       => BareConstraint (ReverseList (a ': as) (b ': bs))
     f | Dict <- unsafeEqTypes @(a ': as) @(Reverse (b ': bs))
       , Dict <- unsafeEqTypes @(b ': bs) @(Reverse (a ': as))
-      = dictToBare $ defineReverseList
+      = dictToBare defineReverseList
 
     {- Since both classes, ReverseList and SnocList actually bear no runtime references
        to their parameters, the only thing that matters is the length of the list
diff --git a/src/Data/Type/Lits.hs b/src/Data/Type/Lits.hs
--- a/src/Data/Type/Lits.hs
+++ b/src/Data/Type/Lits.hs
@@ -109,7 +109,7 @@
 type Min (a :: TN.Nat) (b :: TN.Nat) = Min' a b (TN.CmpNat a b)
 
 -- | Maximum among two type-level naturals.
-type Max (a :: TN.Nat) (b :: TN.Nat) = Min' a b (TN.CmpNat a b)
+type Max (a :: TN.Nat) (b :: TN.Nat) = Max' a b (TN.CmpNat a b)
 
 type family Min' (a :: TN.Nat) (b :: TN.Nat) (r :: Ordering) :: TN.Nat where
     Min' a _ 'LT = a
diff --git a/src/Numeric/Dimensions/Dim.hs b/src/Numeric/Dimensions/Dim.hs
--- a/src/Numeric/Dimensions/Dim.hs
+++ b/src/Numeric/Dimensions/Dim.hs
@@ -4,7 +4,6 @@
 {-# LANGUAGE DataKinds                 #-}
 {-# LANGUAGE DeriveDataTypeable        #-}
 {-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE ExplicitNamespaces        #-}
 {-# LANGUAGE FlexibleContexts          #-}
 {-# LANGUAGE FlexibleInstances         #-}
 {-# LANGUAGE GADTs                     #-}
@@ -119,7 +118,7 @@
 import           Data.Type.List
 import           Data.Type.List.Internal
 import           Data.Type.Lits
-import           GHC.Exts                 (Proxy#, RuntimeRep, TYPE, proxy#)
+import           GHC.Exts                 (Proxy#, RuntimeRep, TYPE, proxy#, type (~~))
 import qualified GHC.Generics             as G
 import           Numeric.Natural          (Natural)
 import           Numeric.TypedList
@@ -128,6 +127,19 @@
 import           Type.Reflection
 import           Unsafe.Coerce            (unsafeCoerce)
 
+{-
+COMPLETE pragmas on Dims and XDims let you avoid the boilerplate of catch-all cases
+when pattern-matching only to get the evidence brought by Dims. Unfortunately,
+there is a bug the pattern-match checker in GHC 8.10 and 9.0, which warns you incorrectly
+about redundant or inacessible patterns in some rare cases.
+To workaround those dangerous cases, I disable these pragmas for some compiler versions.
+(i.e. it's better to place a redundant wildcard case than to have a partial function at runtime).
+
+https://gitlab.haskell.org/ghc/ghc/-/issues/19622
+ -}
+#define IS_UNSOUND_MATCHING_810_900 (MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) && !MIN_VERSION_GLASGOW_HASKELL(9,1,0,0))
+
+
 -- | Either known or unknown at compile-time natural number
 data XNat = XN Nat | N Nat
 -- | Unknown natural number, known to be not smaller than the given Nat
@@ -203,6 +215,8 @@
 newtype Dim (x :: k) = DimSing Word
   deriving ( Typeable )
 
+type role Dim nominal
+
 -- | Same as `SomeNat`
 type SomeDim = Dim (XN 0)
 
@@ -224,7 +238,7 @@
 
 #define PLEASE_STYLISH_HASKELL \
   forall d . KnownDimType d => \
-  forall (n :: Nat) . (KindOf d ~ XNat, d ~ N n) => \
+  forall (n :: Nat) . (d ~~ N n) => \
   Dim n -> Dim d
 
 -- | Statically known `XNat`
@@ -236,7 +250,7 @@
 
 #define PLEASE_STYLISH_HASKELL \
   forall d . KnownDimType d => \
-  forall (m :: Nat) (n :: Nat) . (KindOf d ~ XNat, d ~ XN m, m <= n) => \
+  forall (m :: Nat) (n :: Nat) . (d ~~ XN m, m <= n) => \
   Dim n -> Dim d
 
 -- | `XNat` that is unknown at compile time.
@@ -248,8 +262,10 @@
     Dx k = coerce k
 #undef PLEASE_STYLISH_HASKELL
 
+#if !IS_UNSOUND_MATCHING_810_900
 {-# COMPLETE D #-}
 {-# COMPLETE Dn, Dx #-}
+#endif
 {-# COMPLETE D, Dn, Dx #-}
 
 -- | This class provides the `Dim` associated with a type-level natural.
@@ -434,9 +450,9 @@
               => ( (KnownDim (DimBound d), ExactDim d
                  , KnownDimType d, FixedDim d (DimBound d)) => r)
               -> r
-withKnownXDim
+withKnownXDim x
   | Dict <- unsafeEqTypes @d @(N (DimBound d))
-    = reifyDim @Nat @(DimBound d) (coerce (dim @d))
+    = reifyDim @Nat @(DimBound d) @rep @r (coerce (dim @d)) x
 {-# INLINE withKnownXDim #-}
 
 instance Class (KnownNat n) (KnownDim n) where
@@ -719,7 +735,7 @@
 
 #define PLEASE_STYLISH_HASKELL \
   forall ds . KnownDimKind (KindOfEl ds) => \
-  (KindOfEl ds ~ Nat, Dimensions ds) => \
+  forall (ns :: [Nat]) . (ds ~~ ns, Dimensions ns) => \
   Dims ds
 
 -- | @O(1)@ Pattern-matching against this constructor brings a `Dimensions`
@@ -735,7 +751,7 @@
 
 #define PLEASE_STYLISH_HASKELL \
   forall ds . KnownDimKind (KindOfEl ds) => \
-  forall (ns :: [Nat]) . (KindOfEl ds ~ XNat, FixedDims ds ns) => \
+  forall (ns :: [Nat]) . (FixedDims ds ns) => \
   Dims ns -> Dims ds
 
 -- | @O(n)@
@@ -750,10 +766,6 @@
     XDims = unsafeCastTL
 #undef PLEASE_STYLISH_HASKELL
 
-{-# COMPLETE Dims #-}
-{-# COMPLETE XDims #-}
-{-# COMPLETE Dims, XDims #-}
-
 -- | @O(Length ds)@ A heavy weapon against all sorts of type errors
 pattern KnownDims :: forall (ds :: [Nat]) . ()
                   => ( All KnownDim ds, All BoundedDim ds
@@ -762,6 +774,12 @@
 pattern KnownDims <- (patKDims -> PatKDims)
   where
     KnownDims = dims @ds
+
+#if !IS_UNSOUND_MATCHING_810_900
+{-# COMPLETE Dims #-}
+{-# COMPLETE XDims #-}
+#endif
+{-# COMPLETE Dims, XDims #-}
 {-# COMPLETE KnownDims #-}
 
 -- | Same as SomeNat, but for Dimensions:
@@ -820,6 +838,7 @@
     dsN :: Dims (DimsBound ds)
     dsN = unsafeCastTL (dims @ds)
 {-# INLINE withKnownXDims #-}
+{-# ANN withKnownXDims "HLint: ignore Use const" #-}
 
 -- | Minimal or exact bound of @Dims@.
 --   This is a plural form of `DimBound`.
@@ -908,7 +927,12 @@
       | _ :* TypeList <- tList @ds
       , Dict <- incohInstBoundedDims' ds' Dict
         -> defineBoundedDims dimsBound' constrainDims'
+#if __GLASGOW_HASKELL__ < 810
     _ -> error "incohInstBoundedDims': impossible pattern"
+#endif
+#if IS_UNSOUND_MATCHING_810_900
+  _ -> error "incohInstBoundedDims': impossible pattern"
+#endif
   where
     dimsBound' :: Dims (DimsBound ds)
     dimsBound' = unsafeCastTL ds
@@ -1081,7 +1105,7 @@
     Very unsafe operation.
     I rely here on the fact that FixedDim xn n has the same
     runtime rep as a single type equality.
-    If that changes, then the code is broke.
+    If that changes, then the code is broken.
      -}
   | Dict <- unsafeEqTypes @xns @(N n ': Tail xns)
   , Dict <- unsafeInferFixedDims @(Tail xns) ns = Dict
@@ -1098,7 +1122,7 @@
 {-# INLINE inferExactFixedDims #-}
 
 instance Typeable d => Data (Dim (d :: Nat)) where
-    gfoldl _ = id
+    gfoldl _ f = f
     gunfold _ z = const (z (typeableDim @d))
     toConstr = const $ dimNatConstr (dimVal (typeableDim @d))
     dataTypeOf = const $ dimDataType (dimVal (typeableDim @d))
@@ -1263,7 +1287,7 @@
   where
     reifyBoundedDim :: forall (d :: k) . Dim d -> Dict (BoundedDim d)
     reifyBoundedDim = case dimKind @k of
-      DimKNat -> \d -> reifyDim d Dict
+      DimKNat -> (`reifyDim` Dict)
       DimKXNat
         | Dict <- unsafeEqTypes @d @(N (DimBound d))
               -> \d -> reifyDim (coerce d :: Dim (DimBound d)) Dict
diff --git a/src/Numeric/Dimensions/Dim.hs-boot b/src/Numeric/Dimensions/Dim.hs-boot
--- a/src/Numeric/Dimensions/Dim.hs-boot
+++ b/src/Numeric/Dimensions/Dim.hs-boot
@@ -1,12 +1,14 @@
-{-# LANGUAGE DataKinds      #-}
-{-# LANGUAGE ExplicitForAll #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE TypeInType     #-}
-{-# LANGUAGE TypeOperators  #-}
+{-# LANGUAGE DataKinds       #-}
+{-# LANGUAGE ExplicitForAll  #-}
+{-# LANGUAGE KindSignatures  #-}
+{-# LANGUAGE RoleAnnotations #-}
+{-# LANGUAGE TypeInType      #-}
+{-# LANGUAGE TypeOperators   #-}
 -- This module recursively depends on Numeric.TypedList.
 -- I thought hs-boot is better than orphan instances.
 module Numeric.Dimensions.Dim ( Dim, dimVal, minusDimM ) where
 import Data.Type.Lits (type (-), Nat)
 newtype Dim (x :: k) = DimSing Word
+type role Dim nominal
 dimVal :: forall x . Dim x -> Word
 minusDimM :: forall (n :: Nat) (m :: Nat) . Dim n -> Dim m -> Maybe (Dim (n - m))
diff --git a/src/Numeric/Tuple/Lazy.hs b/src/Numeric/Tuple/Lazy.hs
--- a/src/Numeric/Tuple/Lazy.hs
+++ b/src/Numeric/Tuple/Lazy.hs
@@ -9,8 +9,6 @@
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GADTs                      #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE IncoherentInstances        #-}
-{-# LANGUAGE MagicHash                  #-}
 {-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE PatternSynonyms            #-}
 {-# LANGUAGE PolyKinds                  #-}
diff --git a/src/Numeric/Tuple/Strict.hs b/src/Numeric/Tuple/Strict.hs
--- a/src/Numeric/Tuple/Strict.hs
+++ b/src/Numeric/Tuple/Strict.hs
@@ -9,8 +9,6 @@
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GADTs                      #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE IncoherentInstances        #-}
-{-# LANGUAGE MagicHash                  #-}
 {-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE PatternSynonyms            #-}
 {-# LANGUAGE PolyKinds                  #-}
diff --git a/src/Numeric/TypedList.hs b/src/Numeric/TypedList.hs
--- a/src/Numeric/TypedList.hs
+++ b/src/Numeric/TypedList.hs
@@ -6,11 +6,11 @@
 {-# LANGUAGE FlexibleContexts          #-}
 {-# LANGUAGE FlexibleInstances         #-}
 {-# LANGUAGE GADTs                     #-}
-{-# LANGUAGE MagicHash                 #-}
 {-# LANGUAGE MultiParamTypeClasses     #-}
 {-# LANGUAGE PatternSynonyms           #-}
 {-# LANGUAGE PolyKinds                 #-}
 {-# LANGUAGE RankNTypes                #-}
+{-# LANGUAGE RoleAnnotations           #-}
 {-# LANGUAGE ScopedTypeVariables       #-}
 {-# LANGUAGE StandaloneDeriving        #-}
 {-# LANGUAGE TypeApplications          #-}
@@ -82,6 +82,9 @@
 -- | Type-indexed list
 newtype TypedList (f :: (k -> Type)) (xs :: [k]) = TypedList [Any]
   deriving (Typeable)
+
+type role TypedList representational representational
+
 {-# COMPLETE TypeList #-}
 {-# COMPLETE EvList #-}
 {-# COMPLETE U, (:*) #-}
diff --git a/test/Numeric/Dimensions/DimTest.hs b/test/Numeric/Dimensions/DimTest.hs
--- a/test/Numeric/Dimensions/DimTest.hs
+++ b/test/Numeric/Dimensions/DimTest.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP                       #-}
 {-# LANGUAGE ConstraintKinds           #-}
 {-# LANGUAGE DataKinds                 #-}
 {-# LANGUAGE ExistentialQuantification #-}
@@ -109,7 +110,9 @@
                                     ("stripSuffixDims with " ++ show (dxs, dys, dxsys)) False
                       Just Dict -> property True
                 -- .&&. dxsys === TL.concat dxs dys
+#if __GLASGOW_HASKELL__ < 900
   | otherwise = property False
+#endif
 
 
 prop_stripPrefixDims :: Int -> [Word] -> Property
diff --git a/test/Numeric/Dimensions/IdxTest.hs b/test/Numeric/Dimensions/IdxTest.hs
--- a/test/Numeric/Dimensions/IdxTest.hs
+++ b/test/Numeric/Dimensions/IdxTest.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP                       #-}
 {-# LANGUAGE ConstraintKinds           #-}
 {-# LANGUAGE DataKinds                 #-}
 {-# LANGUAGE ExistentialQuantification #-}
@@ -13,7 +14,7 @@
 module Numeric.Dimensions.IdxTest where
 
 import Control.Arrow
-import Data.List
+import Data.List       (mapAccumR)
 import Data.Maybe
 import Test.QuickCheck (quickCheckAll)
 
@@ -47,8 +48,9 @@
   , SomeDims (KnownDims :: Dims ds) <- someDimsVal ys
   , mIs <- idxsFromWords @ds xs
     = or (zipWith (==) xs ys) || isJust mIs
-  | otherwise
-    = error "Impossible arguments"
+#if __GLASGOW_HASKELL__ < 900
+  | otherwise = error "Impossible arguments"
+#endif
 
 -- | Check failing cases
 prop_idxsFromWords2 :: [(Word, Word)] -> Bool
@@ -57,8 +59,9 @@
   , SomeDims (KnownDims :: Dims ds) <- someDimsVal xs
   , mIs <- idxsFromWords @ds ys
     = null xs || isNothing mIs
-  | otherwise
-    = error "Impossible arguments"
+#if __GLASGOW_HASKELL__ < 900
+  | otherwise = error "Impossible arguments"
+#endif
 
 -- | Check if results of idxsFromWords are consistent with idxFromWord
 prop_idxsFromWords3 :: [(Word, Word)] -> Bool
@@ -67,8 +70,9 @@
   , SomeDims (ds@KnownDims :: Dims ds) <- someDimsVal ys
   , mIs <- idxsFromWords @ds xs
     = Just False /= (go xs ds <$> mIs)
-  | otherwise
-    = error "Impossible arguments"
+#if __GLASGOW_HASKELL__ < 900
+  | otherwise = error "Impossible arguments"
+#endif
   where
     go :: forall (ns :: [Nat]) . [Word] -> Dims ns -> Idxs ns -> Bool
     go [] U U = True
