diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,8 @@
 # mixed-types-num change log
 
+* v 0.5.9 2021-08-04
+  * compatible with ghc 9.0.1
+  * separated module Mul from Ring
 * v 0.5.8 2021-06-02
   * add HasRationals to Field
 * v 0.5.7 2021-05-28
diff --git a/mixed-types-num.cabal b/mixed-types-num.cabal
--- a/mixed-types-num.cabal
+++ b/mixed-types-num.cabal
@@ -3,11 +3,9 @@
 -- This file has been generated from package.yaml by hpack version 0.34.4.
 --
 -- see: https://github.com/sol/hpack
---
--- hash: 577d524d309a29822adf0ad8117bd81096101b172ce94f23e11273dba5235297
 
 name:           mixed-types-num
-version:        0.5.8.0
+version:        0.5.9.0
 synopsis:       Alternative Prelude with numeric and logic expressions typed bottom-up
 description:    Please see the README on GitHub at <https://github.com/michalkonecny/mixed-types-num#readme>
 category:       Math
@@ -42,6 +40,7 @@
       Numeric.MixedTypes.Field
       Numeric.MixedTypes.Literals
       Numeric.MixedTypes.MinMaxAbs
+      Numeric.MixedTypes.Mul
       Numeric.MixedTypes.Ord
       Numeric.MixedTypes.Power
       Numeric.MixedTypes.PreludeHiding
diff --git a/src/Numeric/MixedTypes/Complex.hs b/src/Numeric/MixedTypes/Complex.hs
--- a/src/Numeric/MixedTypes/Complex.hs
+++ b/src/Numeric/MixedTypes/Complex.hs
@@ -32,7 +32,7 @@
 import Numeric.MixedTypes.Eq
 import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Mul
 import Numeric.MixedTypes.Div
 -- import Numeric.MixedTypes.Power
 -- import Numeric.MixedTypes.Field
diff --git a/src/Numeric/MixedTypes/Div.hs b/src/Numeric/MixedTypes/Div.hs
--- a/src/Numeric/MixedTypes/Div.hs
+++ b/src/Numeric/MixedTypes/Div.hs
@@ -44,7 +44,7 @@
 -- import Numeric.MixedTypes.Ord
 -- import Numeric.MixedTypes.MinMaxAbs
 -- import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Mul
 
 {---- Division -----}
 
diff --git a/src/Numeric/MixedTypes/Elementary.hs b/src/Numeric/MixedTypes/Elementary.hs
--- a/src/Numeric/MixedTypes/Elementary.hs
+++ b/src/Numeric/MixedTypes/Elementary.hs
@@ -44,7 +44,7 @@
 import Numeric.MixedTypes.Ord
 import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Mul
 import Numeric.MixedTypes.Field
 import Numeric.MixedTypes.Power
 -- import Numeric.MixedTypes.Round
diff --git a/src/Numeric/MixedTypes/Mul.hs b/src/Numeric/MixedTypes/Mul.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/MixedTypes/Mul.hs
@@ -0,0 +1,213 @@
+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-|
+    Module      :  Numeric.MixedType.Mul
+    Description :  Bottom-up typed multiplication with ring laws
+    Copyright   :  (c) Michal Konecny
+    License     :  BSD3
+
+    Maintainer  :  mikkonecny@gmail.com
+    Stability   :  experimental
+    Portability :  portable
+
+-}
+
+module Numeric.MixedTypes.Mul
+(
+  -- ** Multiplication
+  CanMul, CanMulAsymmetric(..), CanMulBy, CanMulSameType
+  , (*), product
+  -- ** Tests
+  , specCanMul, specCanMulNotMixed, specCanMulSameType
+)
+where
+
+import Utils.TH.DeclForTypes
+
+import Numeric.MixedTypes.PreludeHiding
+import qualified Prelude as P
+import Text.Printf
+
+import qualified Data.List as List
+
+import Test.Hspec
+import Test.QuickCheck
+
+import qualified Numeric.CollectErrors as CN
+import Numeric.CollectErrors ( CN )
+
+import Numeric.MixedTypes.Literals
+import Numeric.MixedTypes.Bool
+import Numeric.MixedTypes.Eq
+-- import Numeric.MixedTypes.MinMaxAbs
+import Numeric.MixedTypes.AddSub
+import Numeric.MixedTypes.Reduce
+
+{---- Multiplication -----}
+
+type CanMul t1 t2 =
+  (CanMulAsymmetric t1 t2, CanMulAsymmetric t2 t1,
+   MulType t1 t2 ~ MulType t2 t1)
+
+{-|
+  A replacement for Prelude's `P.*`.  If @t1 = t2@ and @Num t1@,
+  then one can use the default implementation to mirror Prelude's @*@.
+-}
+class CanMulAsymmetric t1 t2 where
+  type MulType t1 t2
+  type MulType t1 t2 = t1 -- default
+  mul :: t1 -> t2 -> MulType t1 t2
+  default mul :: (MulType t1 t2 ~ t1, t1~t2, P.Num t1) => t1 -> t2 -> MulType t1 t2
+  mul = (P.*)
+
+infixl 7  *
+
+(*) :: (CanMulAsymmetric t1 t2) => t1 -> t2 -> MulType t1 t2
+(*) = mul
+
+type CanMulBy t1 t2 =
+  (CanMul t1 t2, MulType t1 t2 ~ t1)
+type CanMulSameType t =
+  CanMulBy t t
+
+product :: (CanMulSameType t, ConvertibleExactly Integer t) => [t] -> t
+product xs = List.foldl' mul (convertExactly 1) xs
+
+{-|
+  HSpec properties that each implementation of CanMul should satisfy.
+ -}
+specCanMul ::
+  _ => T t1 -> T t2 -> T t3 -> Spec
+specCanMul (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =
+  describe (printf "CanMul %s %s, CanMul %s %s" typeName1 typeName2 typeName2 typeName3) $ do
+    it "absorbs 1" $ do
+      property $ \ (x :: t1) -> let one = (convertExactly 1 :: t2) in (x * one) ?==?$ x
+    it "is commutative" $ do
+      property $ \ (x :: t1) (y :: t2) -> (x * y) ?==?$ (y * x)
+    it "is associative" $ do
+      property $ \ (x :: t1) (y :: t2) (z :: t3) ->
+                      (x * (y * z)) ?==?$ ((x * y) * z)
+    it "distributes over addition" $ do
+      property $ \ (x :: t1) (y :: t2) (z :: t3) ->
+                      (x * (y + z)) ?==?$ (x * y) + (x * z)
+  where
+  infix 4 ?==?$
+  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
+  (?==?$) = printArgsIfFails2 "?==?" (?==?)
+
+{-|
+  HSpec properties that each implementation of CanMul should satisfy.
+ -}
+specCanMulNotMixed ::
+  _ => T t -> Spec
+specCanMulNotMixed (t :: T t) = specCanMul t t t
+
+{-|
+  HSpec properties that each implementation of CanMulSameType should satisfy.
+ -}
+specCanMulSameType ::
+  (Show t, ConvertibleExactly Integer t,
+   CanTestCertainly (EqCompareType t t), HasEqAsymmetric t t,
+   CanMulAsymmetric t t, MulType t t ~ t)
+   =>
+   T t -> Spec
+specCanMulSameType (T typeName :: T t) =
+  describe (printf "CanMulSameType %s" typeName) $ do
+    it "has product working over integers" $ do
+      property $ \ (xsi :: [Integer]) ->
+        (product $ (map convertExactly xsi :: [t])) ?==?$ (convertExactly (product xsi) :: t)
+    it "has product [] = 1" $ do
+        (product ([] :: [t])) ?==?$ (convertExactly 1 :: t)
+  where
+  infix 4 ?==?$
+  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
+  (?==?$) = printArgsIfFails2 "?==?" (?==?)
+
+instance CanMulAsymmetric Int Int where
+  type MulType Int Int = Integer -- do not risk overflow
+  mul a b = (integer a) P.* (integer b)
+instance CanMulAsymmetric Integer Integer
+instance CanMulAsymmetric Rational Rational
+instance CanMulAsymmetric Double Double
+
+instance CanMulAsymmetric Int Integer where
+  type MulType Int Integer = Integer
+  mul = convertFirst mul
+instance CanMulAsymmetric Integer Int where
+  type MulType Integer Int = Integer
+  mul = convertSecond mul
+
+instance CanMulAsymmetric Int Rational where
+  type MulType Int Rational = Rational
+  mul = convertFirst mul
+instance CanMulAsymmetric Rational Int where
+  type MulType Rational Int = Rational
+  mul = convertSecond mul
+
+instance CanMulAsymmetric Integer Rational where
+  type MulType Integer Rational = Rational
+  mul = convertFirst mul
+instance CanMulAsymmetric Rational Integer where
+  type MulType Rational Integer = Rational
+  mul = convertSecond mul
+
+instance CanMulAsymmetric Int Double where
+  type MulType Int Double = Double
+  mul n d = mul (double n) d
+instance CanMulAsymmetric Double Int where
+  type MulType Double Int = Double
+  mul d n = mul d (double n)
+
+instance CanMulAsymmetric Integer Double where
+  type MulType Integer Double = Double
+  mul n d = mul (double n) d
+instance CanMulAsymmetric Double Integer where
+  type MulType Double Integer = Double
+  mul d n = mul d (double n)
+
+instance CanMulAsymmetric Rational Double where
+  type MulType Rational Double = Double
+  mul n d = mul (double n) d
+instance CanMulAsymmetric Double Rational where
+  type MulType Double Rational = Double
+  mul d n = mul d (double n)
+
+instance (CanMulAsymmetric a b) => CanMulAsymmetric [a] [b] where
+  type MulType [a] [b] = [MulType a b]
+  mul (x:xs) (y:ys) = (mul x y) : (mul xs ys)
+  mul _ _ = []
+
+instance (CanMulAsymmetric a b) => CanMulAsymmetric (Maybe a) (Maybe b) where
+  type MulType (Maybe a) (Maybe b) = Maybe (MulType a b)
+  mul (Just x) (Just y) = Just (mul x y)
+  mul _ _ = Nothing
+
+instance
+  (CanMulAsymmetric a b, CanGiveUpIfVeryInaccurate (MulType a b))
+  =>
+  CanMulAsymmetric (CN a) (CN b)
+  where
+  type MulType (CN a) (CN b) = CN (MulType a b)
+  mul a b = giveUpIfVeryInaccurate $ CN.lift2 mul a b
+
+$(declForTypes
+  [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]
+  (\ t -> [d|
+
+    instance
+      (CanMulAsymmetric $t b, CanGiveUpIfVeryInaccurate (MulType $t b))
+      =>
+      CanMulAsymmetric $t (CN b)
+      where
+      type MulType $t (CN b) = CN (MulType $t b)
+      mul a b = giveUpIfVeryInaccurate $ CN.liftT1 mul a b
+
+    instance
+      (CanMulAsymmetric a $t, CanGiveUpIfVeryInaccurate (MulType a $t))
+      =>
+      CanMulAsymmetric (CN a) $t
+      where
+      type MulType (CN a) $t = CN (MulType a $t)
+      mul a b = giveUpIfVeryInaccurate $ CN.lift1T mul a b
+  |]))
diff --git a/src/Numeric/MixedTypes/Power.hs b/src/Numeric/MixedTypes/Power.hs
--- a/src/Numeric/MixedTypes/Power.hs
+++ b/src/Numeric/MixedTypes/Power.hs
@@ -44,7 +44,7 @@
 import Numeric.MixedTypes.Ord
 -- import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Mul
 -- import Numeric.MixedTypes.Div ()
 
 
diff --git a/src/Numeric/MixedTypes/Ring.hs b/src/Numeric/MixedTypes/Ring.hs
--- a/src/Numeric/MixedTypes/Ring.hs
+++ b/src/Numeric/MixedTypes/Ring.hs
@@ -1,9 +1,8 @@
 {-# OPTIONS_GHC -Wno-partial-type-signatures #-}
 {-# LANGUAGE PartialTypeSignatures #-}
-{-# LANGUAGE TemplateHaskell #-}
 {-|
     Module      :  Numeric.MixedType.Ring
-    Description :  Bottom-up typed multiplication with ring laws
+    Description :  Ring type classes
     Copyright   :  (c) Michal Konecny
     License     :  BSD3
 
@@ -15,28 +14,14 @@
 
 module Numeric.MixedTypes.Ring
 (
-  -- * Ring
   CanAddSubMulBy, Ring, OrderedRing, OrderedCertainlyRing
-  -- * Multiplication
-  , CanMul, CanMulAsymmetric(..), CanMulBy, CanMulSameType
-  , (*), product
-  -- ** Tests
-  , specCanMul, specCanMulNotMixed, specCanMulSameType
 )
 where
 
-import Utils.TH.DeclForTypes
-
 import Numeric.MixedTypes.PreludeHiding
-import qualified Prelude as P
-import Text.Printf
-
-import qualified Data.List as List
-
-import Test.Hspec
-import Test.QuickCheck
+-- import qualified Prelude as P
+-- import Text.Printf
 
-import qualified Numeric.CollectErrors as CN
 import Numeric.CollectErrors ( CN )
 
 import Numeric.MixedTypes.Literals
@@ -45,7 +30,7 @@
 import Numeric.MixedTypes.Ord
 -- import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Reduce
+import Numeric.MixedTypes.Mul
 
 {----- Ring -----}
 
@@ -90,171 +75,3 @@
 instance OrderedCertainlyRing (CN Integer)
 instance OrderedCertainlyRing Rational
 instance OrderedCertainlyRing (CN Rational)
-
-{---- Multiplication -----}
-
-type CanMul t1 t2 =
-  (CanMulAsymmetric t1 t2, CanMulAsymmetric t2 t1,
-   MulType t1 t2 ~ MulType t2 t1)
-
-{-|
-  A replacement for Prelude's `P.*`.  If @t1 = t2@ and @Num t1@,
-  then one can use the default implementation to mirror Prelude's @*@.
--}
-class CanMulAsymmetric t1 t2 where
-  type MulType t1 t2
-  type MulType t1 t2 = t1 -- default
-  mul :: t1 -> t2 -> MulType t1 t2
-  default mul :: (MulType t1 t2 ~ t1, t1~t2, P.Num t1) => t1 -> t2 -> MulType t1 t2
-  mul = (P.*)
-
-infixl 7  *
-
-(*) :: (CanMulAsymmetric t1 t2) => t1 -> t2 -> MulType t1 t2
-(*) = mul
-
-type CanMulBy t1 t2 =
-  (CanMul t1 t2, MulType t1 t2 ~ t1)
-type CanMulSameType t =
-  CanMulBy t t
-
-product :: (CanMulSameType t, ConvertibleExactly Integer t) => [t] -> t
-product xs = List.foldl' mul (convertExactly 1) xs
-
-{-|
-  HSpec properties that each implementation of CanMul should satisfy.
- -}
-specCanMul ::
-  _ => T t1 -> T t2 -> T t3 -> Spec
-specCanMul (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =
-  describe (printf "CanMul %s %s, CanMul %s %s" typeName1 typeName2 typeName2 typeName3) $ do
-    it "absorbs 1" $ do
-      property $ \ (x :: t1) -> let one = (convertExactly 1 :: t2) in (x * one) ?==?$ x
-    it "is commutative" $ do
-      property $ \ (x :: t1) (y :: t2) -> (x * y) ?==?$ (y * x)
-    it "is associative" $ do
-      property $ \ (x :: t1) (y :: t2) (z :: t3) ->
-                      (x * (y * z)) ?==?$ ((x * y) * z)
-    it "distributes over addition" $ do
-      property $ \ (x :: t1) (y :: t2) (z :: t3) ->
-                      (x * (y + z)) ?==?$ (x * y) + (x * z)
-  where
-  infix 4 ?==?$
-  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
-  (?==?$) = printArgsIfFails2 "?==?" (?==?)
-
-{-|
-  HSpec properties that each implementation of CanMul should satisfy.
- -}
-specCanMulNotMixed ::
-  _ => T t -> Spec
-specCanMulNotMixed (t :: T t) = specCanMul t t t
-
-{-|
-  HSpec properties that each implementation of CanMulSameType should satisfy.
- -}
-specCanMulSameType ::
-  (Show t, ConvertibleExactly Integer t,
-   CanTestCertainly (EqCompareType t t), HasEqAsymmetric t t,
-   CanMulAsymmetric t t, MulType t t ~ t)
-   =>
-   T t -> Spec
-specCanMulSameType (T typeName :: T t) =
-  describe (printf "CanMulSameType %s" typeName) $ do
-    it "has product working over integers" $ do
-      property $ \ (xsi :: [Integer]) ->
-        (product $ (map convertExactly xsi :: [t])) ?==?$ (convertExactly (product xsi) :: t)
-    it "has product [] = 1" $ do
-        (product ([] :: [t])) ?==?$ (convertExactly 1 :: t)
-  where
-  infix 4 ?==?$
-  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
-  (?==?$) = printArgsIfFails2 "?==?" (?==?)
-
-instance CanMulAsymmetric Int Int where
-  type MulType Int Int = Integer -- do not risk overflow
-  mul a b = (integer a) P.* (integer b)
-instance CanMulAsymmetric Integer Integer
-instance CanMulAsymmetric Rational Rational
-instance CanMulAsymmetric Double Double
-
-instance CanMulAsymmetric Int Integer where
-  type MulType Int Integer = Integer
-  mul = convertFirst mul
-instance CanMulAsymmetric Integer Int where
-  type MulType Integer Int = Integer
-  mul = convertSecond mul
-
-instance CanMulAsymmetric Int Rational where
-  type MulType Int Rational = Rational
-  mul = convertFirst mul
-instance CanMulAsymmetric Rational Int where
-  type MulType Rational Int = Rational
-  mul = convertSecond mul
-
-instance CanMulAsymmetric Integer Rational where
-  type MulType Integer Rational = Rational
-  mul = convertFirst mul
-instance CanMulAsymmetric Rational Integer where
-  type MulType Rational Integer = Rational
-  mul = convertSecond mul
-
-instance CanMulAsymmetric Int Double where
-  type MulType Int Double = Double
-  mul n d = mul (double n) d
-instance CanMulAsymmetric Double Int where
-  type MulType Double Int = Double
-  mul d n = mul d (double n)
-
-instance CanMulAsymmetric Integer Double where
-  type MulType Integer Double = Double
-  mul n d = mul (double n) d
-instance CanMulAsymmetric Double Integer where
-  type MulType Double Integer = Double
-  mul d n = mul d (double n)
-
-instance CanMulAsymmetric Rational Double where
-  type MulType Rational Double = Double
-  mul n d = mul (double n) d
-instance CanMulAsymmetric Double Rational where
-  type MulType Double Rational = Double
-  mul d n = mul d (double n)
-
-instance (CanMulAsymmetric a b) => CanMulAsymmetric [a] [b] where
-  type MulType [a] [b] = [MulType a b]
-  mul (x:xs) (y:ys) = (mul x y) : (mul xs ys)
-  mul _ _ = []
-
-instance (CanMulAsymmetric a b) => CanMulAsymmetric (Maybe a) (Maybe b) where
-  type MulType (Maybe a) (Maybe b) = Maybe (MulType a b)
-  mul (Just x) (Just y) = Just (mul x y)
-  mul _ _ = Nothing
-
-instance
-  (CanMulAsymmetric a b, CanGiveUpIfVeryInaccurate (MulType a b))
-  =>
-  CanMulAsymmetric (CN a) (CN b)
-  where
-  type MulType (CN a) (CN b) = CN (MulType a b)
-  mul a b = giveUpIfVeryInaccurate $ CN.lift2 mul a b
-
-$(declForTypes
-  [[t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]
-  (\ t -> [d|
-
-    instance
-      (CanMulAsymmetric $t b, CanGiveUpIfVeryInaccurate (MulType $t b))
-      =>
-      CanMulAsymmetric $t (CN b)
-      where
-      type MulType $t (CN b) = CN (MulType $t b)
-      mul a b = giveUpIfVeryInaccurate $ CN.liftT1 mul a b
-
-    instance
-      (CanMulAsymmetric a $t, CanGiveUpIfVeryInaccurate (MulType a $t))
-      =>
-      CanMulAsymmetric (CN a) $t
-      where
-      type MulType (CN a) $t = CN (MulType a $t)
-      mul a b = giveUpIfVeryInaccurate $ CN.lift1T mul a b
-  |]))
diff --git a/src/Numeric/MixedTypes/Round.hs b/src/Numeric/MixedTypes/Round.hs
--- a/src/Numeric/MixedTypes/Round.hs
+++ b/src/Numeric/MixedTypes/Round.hs
@@ -47,7 +47,7 @@
 import Numeric.MixedTypes.Ord
 -- import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Mul
 
 {----  rounded division + modulo -----}
 
diff --git a/src/Utils/Test/EnforceRange.hs b/src/Utils/Test/EnforceRange.hs
--- a/src/Utils/Test/EnforceRange.hs
+++ b/src/Utils/Test/EnforceRange.hs
@@ -25,7 +25,7 @@
 import Numeric.MixedTypes.Ord
 import Numeric.MixedTypes.MinMaxAbs
 import Numeric.MixedTypes.AddSub
-import Numeric.MixedTypes.Ring
+import Numeric.MixedTypes.Mul
 import Numeric.MixedTypes.Field
 import Numeric.MixedTypes.Round
 
