diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+Version 1.5.5
+---------------
+* Added `Rank2.coerce`
+* Allow `markdown-unlit` 0.6, thanks to Felix Yan
+* Turned doctests from a testsuite into a named library, dropped cabal-doctest
+* Updated GitHub CI action
+
 Version 1.5.4
 ---------------
 * Deriving `Data` and `Typeable` for all declared data types.
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,6 +1,2 @@
-module Main where
-
-import Distribution.Extra.Doctest (defaultMainWithDoctests)
-
-main :: IO ()
-main = defaultMainWithDoctests "doctests"
+import Distribution.Simple
+main = defaultMain
diff --git a/rank2classes.cabal b/rank2classes.cabal
--- a/rank2classes.cabal
+++ b/rank2classes.cabal
@@ -1,5 +1,5 @@
 name:                rank2classes
-version:             1.5.4
+version:             1.5.5
 synopsis:            standard type constructor class hierarchy, only with methods of rank 2 types
 description:
   A mirror image of the standard type constructor class hierarchy rooted in 'Functor', except with methods of rank 2
@@ -14,18 +14,13 @@
 maintainer:          Mario Blažević <blamario@protonmail.com>
 copyright:           (c) 2017 Mario Blažević
 category:            Control, Data, Generics
-build-type:          Custom
-cabal-version:       >=1.10
-tested-with:         GHC==9.8.2, GHC==9.6.4, GHC==9.4.8, GHC==9.2.8, GHC==9.0.2, GHC==8.10.7
+build-type:          Simple
+cabal-version:       2.0
+tested-with:         GHC==9.12.2, GHC==9.10.2, GHC==9.8.4, GHC==9.6.7, GHC==9.4.8, GHC==9.2.8, GHC==9.0.2, GHC==8.10.7
 extra-source-files:  README.md, CHANGELOG.md, test/MyModule.lhs
 source-repository head
   type:              git
   location:          https://github.com/blamario/grampa
-custom-setup
- setup-depends:
-   base >= 4 && <5,
-   Cabal < 4,
-   cabal-doctest >= 1 && <1.1
 
 flag use-template-haskell
   description: Enable the compilation of the Rank2.TH module
@@ -47,15 +42,13 @@
     build-depends: template-haskell >= 2.11 && < 2.24
     exposed-modules: Rank2.TH
 
-test-suite doctests
-  type:                exitcode-stdio-1.0
+library doctests
   hs-source-dirs:      test
   default-language:    Haskell2010
-  main-is:             Doctest.hs
   other-modules:       MyModule
   ghc-options:         -threaded -pgmL markdown-unlit
-  build-depends:       base, rank2classes, doctest >= 0.8
-  build-tool-depends:  markdown-unlit:markdown-unlit >= 0.5 && < 0.6
+  build-depends:       base, rank2classes
+  build-tool-depends:  markdown-unlit:markdown-unlit >= 0.5 && < 0.7
 
 test-suite TH
   if !flag(use-template-haskell)
@@ -69,4 +62,4 @@
   build-depends:       base, rank2classes, distributive < 0.7,
                        tasty < 2, tasty-hunit < 1,
                        data-functor-logistic < 0.1
-  build-tool-depends:  markdown-unlit:markdown-unlit >= 0.5 && < 0.6
+  build-tool-depends:  markdown-unlit:markdown-unlit >= 0.5 && < 0.7, doctest:doctest >= 0.8 && < 1
diff --git a/src/Rank2.hs b/src/Rank2.hs
--- a/src/Rank2.hs
+++ b/src/Rank2.hs
@@ -9,6 +9,7 @@
 {-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE EmptyCase #-}
+{-# LANGUAGE QuantifiedConstraints #-}
 {-# LANGUAGE TypeApplications #-}
 module Rank2 (
 -- * Rank 2 classes
@@ -31,7 +32,7 @@
 import qualified Data.Functor.Contravariant as Rank1
 import qualified Data.Functor.Logistic as Rank1
 import qualified Data.Distributive as Rank1
-import Data.Coerce (coerce)
+import qualified Data.Coerce as Coerce
 import Data.Data (Data, Typeable)
 import Data.Semigroup (Semigroup(..))
 import Data.Monoid (Monoid(..))
@@ -41,6 +42,7 @@
 import Data.Kind (Type)
 import Data.Proxy (Proxy(..))
 import qualified GHC.Generics as Generics
+import Unsafe.Coerce (unsafeCoerce)
 
 import Prelude hiding (Foldable(..), Traversable(..), Functor(..), Applicative(..), ($), (<$>), fst, snd)
 
@@ -58,6 +60,9 @@
 -- > (p . q) <$> g == p <$> (q <$> g)
 class Functor g where
    (<$>) :: (forall a. p a -> q a) -> g p -> g q
+   -- | Equivalent to @(Data.Coerce.coerce <$>)@ but faster
+   coerce :: (forall a. Coerce.Coercible (p a) (q a)) => g p -> g q
+   coerce = unsafeCoerce
 infixl 4 <$>
 
 -- | Alphabetical synonym for '<$>'
@@ -262,13 +267,13 @@
    f <$> InR h = InR (f <$> h)
 
 instance Functor Generics.V1 where
-   (<$>) _ = coerce
+   (<$>) _ = Coerce.coerce
    
 instance Functor Generics.U1 where
-   (<$>) _ = coerce
+   (<$>) _ = Coerce.coerce
 
 instance Functor (Generics.K1 i c) where
-   (<$>) _ = coerce
+   (<$>) _ = Coerce.coerce
 
 instance Functor f => Functor (Generics.M1 i c f) where
    f <$> Generics.M1 x = Generics.M1 (f <$> x)
@@ -362,13 +367,13 @@
    traverse f (InR h) = InR Rank1.<$> traverse f h
 
 instance Traversable Generics.V1 where
-   traverse _ = Rank1.pure . coerce
+   traverse _ = Rank1.pure . Coerce.coerce
    
 instance Traversable Generics.U1 where
-   traverse _ = Rank1.pure . coerce
+   traverse _ = Rank1.pure . Coerce.coerce
 
 instance Traversable (Generics.K1 i c) where
-   traverse _ = Rank1.pure . coerce
+   traverse _ = Rank1.pure . Coerce.coerce
 
 instance Traversable f => Traversable (Generics.M1 i c f) where
    traverse f (Generics.M1 x) = Rank1.fmap Generics.M1 (traverse f x)
@@ -419,10 +424,10 @@
    liftA3 f (Pair g1 h1) ~(Pair g2 h2) ~(Pair g3 h3) = Pair (liftA3 f g1 g2 g3) (liftA3 f h1 h2 h3)
 
 instance Apply Generics.V1 where
-   (<*>) _ = coerce
+   (<*>) _ = Coerce.coerce
    
 instance Apply Generics.U1 where
-   (<*>) _ = coerce
+   (<*>) _ = Coerce.coerce
 
 instance Semigroup c => Apply (Generics.K1 i c) where
    Generics.K1 x <*> Generics.K1 y = Generics.K1 (x <> y)
@@ -496,7 +501,7 @@
    cotraverse _ _ = Proxy
 
 instance Monoid x => DistributiveTraversable (Const x) where
-   cotraverseTraversable _ f = coerce (Rank1.fold f)
+   cotraverseTraversable _ f = Coerce.coerce (Rank1.fold f)
 
 instance Distributive (Only x) where
    cotraverse w f = Only (w (Rank1.fmap fromOnly f))
@@ -512,7 +517,7 @@
    cotraverse w f = Pair (cotraverse w (Rank1.fmap fst f)) (cotraverse w (Rank1.fmap snd f))
 
 instance Monoid c => DistributiveTraversable (Generics.K1 i c) where
-   cotraverseTraversable _ f = coerce (Rank1.foldMap Generics.unK1 f)
+   cotraverseTraversable _ f = Coerce.coerce (Rank1.foldMap Generics.unK1 f)
 
 instance Distributive f => Distributive (Generics.M1 i c f) where
    cotraverse w f = Generics.M1 (cotraverse w (Rank1.fmap Generics.unM1 f))
@@ -528,10 +533,10 @@
    deliver _ = Proxy
 
 instance Logistic (Only x) where
-   deliver f = Only (Rank1.Compose (Rank1.contramap coerce f))
+   deliver f = Only (Rank1.Compose (Rank1.contramap Coerce.coerce f))
 
 instance Logistic g => Logistic (Identity g) where
-   deliver f = Identity (deliver (Rank1.contramap coerce f))
+   deliver f = Identity (deliver (Rank1.contramap Coerce.coerce f))
 
 instance (Logistic g, Rank1.Logistic p) => Logistic (Compose g p) where
    deliver = Compose
diff --git a/test/Doctest.hs b/test/Doctest.hs
deleted file mode 100644
--- a/test/Doctest.hs
+++ /dev/null
@@ -1,5 +0,0 @@
-import Build_doctests (flags, pkgs, module_sources)
-import Test.DocTest (doctest)
-
-main = do doctest (flags ++ pkgs ++ module_sources)
-          doctest (flags ++ pkgs ++ ["-pgmL", "markdown-unlit", "test/MyModule.lhs"])
diff --git a/test/TH.hs b/test/TH.hs
--- a/test/TH.hs
+++ b/test/TH.hs
@@ -43,6 +43,8 @@
                              wrapSingle= pure (pure ["a", "b", "ab"]),
                              wrapWhole= pure (pure Test0)}
             id Rank2.<$> test @?= test
+            Rank2.coerce test @?= test
+            Rank2.coerce (Compose . Identity Rank2.<$> test) @?= test
             Rank2.pure (Rank2.Arrow id) Rank2.<*> test @?= test
             Rank2.liftA2 (++) test test @?= Test1{single= [3, 4, 5, 3, 4, 5],
                                                   whole= Test0,
