diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
-# 2.0.0
+# `scheduler`
 
+## 2.0.1
+
+* Add `Eq1` and `Show1` instances for `Result`
+* Add compatibility with older `primitive`
+
+## 2.0.0
+
 * Switch type parameter of `Scheduler` from monad `m` to state token `s`. Which
   also means that constraints on many functions got tighter (i.e. `MonadPrim`, `MonadPrimBase`)
 * Remove `m` type parameter for `SchedulerWS`, since it can only work in `IO` like monad anyways.
@@ -7,7 +14,7 @@
 * Swap order of arguments for `replicateWork` for consistency
 * Add `replicateWork_` that is slightly more efficient than `replicateWork`
 
-# 1.5.0
+## 1.5.0
 
 Despite that the major part of the version was bumped up, this release does not include
 any breaking changes, only improvements and additions.
@@ -24,7 +31,7 @@
 * Addition of `GlobalScheduler` that can be reused throughout the codebase, thus reducing
   initialization overhead.
 
-# 1.4.2
+## 1.4.2
 
 * Add `withTrivialScheduler`
 * Add `Results` data type as well as corresponding functions:
@@ -32,11 +39,11 @@
   * `withSchedulerWSR`
   * `withTrivialSchedulerR`
 
-# 1.4.1
+## 1.4.1
 
 * Add functions: `replicateWork`
 
-# 1.4.0
+## 1.4.0
 
 * Worker id has been promoted from `Int` to a `newtype` wrapper `WorkerId`.
 * Addition of `SchedulerWS` and `WorkerStates` data types. As well as the
@@ -51,18 +58,18 @@
   * `unwrapSchedulerWS`
 * Made internal modules accessible, but invisible.
 
-# 1.3.0
+## 1.3.0
 
 * Make sure internal `Scheduler` accessor functions are no longer exported, they only
   cause breakage.
 * Make sure number of capabilities does not change through out the program execution, as
   far as `scheduler` is concerned.
 
-# 1.2.0
+## 1.2.0
 
 * Addition of `scheduleWorkId` and `scheduleWorkId_`
 
-# 1.1.0
+## 1.1.0
 
 * Add functions: `replicateConcurrently` and `replicateConcurrently_`
 * Made `traverseConcurrently_` lazy, thus making it possible to apply to infinite lists and other such
@@ -70,6 +77,6 @@
 * Fix `Monoid` instance for `Comp`
 * Addition of `Par'` pattern
 
-# 1.0.0
+## 1.0.0
 
 Initial release.
diff --git a/scheduler.cabal b/scheduler.cabal
--- a/scheduler.cabal
+++ b/scheduler.cabal
@@ -1,8 +1,8 @@
 name:                scheduler
-version:             2.0.0.1
+version:             2.0.1.0
 synopsis:            Work stealing scheduler.
 description:         A work stealing scheduler that is designed for parallelization of heavy work loads. It was primarily developed for [massiv](https://github.com/lehins/massiv) array library, but it is general enough to be useful for any computation that fits the model of few workers and many jobs.
-homepage:            https://github.com/lehins/haskell-scheduler
+homepage:            https://github.com/lehins/scheduler
 license:             BSD3
 license-file:        LICENSE
 author:              Alexey Kuleshevich
@@ -13,6 +13,19 @@
 extra-source-files:  README.md
                    , CHANGELOG.md
 cabal-version:       >=1.10
+tested-with:          GHC == 8.0.2
+                    , GHC == 8.2.2
+                    , GHC == 8.4.4
+                    , GHC == 8.6.5
+                    , GHC == 8.8.6
+                    , GHC == 8.10.7
+                    , GHC == 9.0.2
+                    , GHC == 9.2.8
+                    , GHC == 9.4.8
+                    , GHC == 9.6.6
+                    , GHC == 9.8.4
+                    , GHC == 9.10.1
+                    , GHC == 9.12.1
 
 library
   hs-source-dirs:      src
@@ -26,8 +39,8 @@
                      , atomic-primops
                      , deepseq
                      , exceptions
-                     , unliftio-core
-                     , primitive      >= 0.7.1
+                     , unliftio-core  >= 0.1.1
+                     , primitive      >= 0.6.4
                      , pvar           < 2.0
   default-language:    Haskell2010
   ghc-options:         -Wall -Wno-simplifiable-class-constraints
@@ -40,12 +53,12 @@
   other-modules:      Spec
                     , Control.SchedulerSpec
   build-tool-depends: hspec-discover:hspec-discover
-  build-depends:      base
+  build-depends:      base           >= 4.9 && < 5
                     , deepseq
-                    , genvalidity-hspec
                     , scheduler
                     , hspec
                     , QuickCheck
+                    , quickcheck-classes >= 0.6
                     , unliftio
 
   default-language:   Haskell2010
@@ -55,12 +68,7 @@
   type:             exitcode-stdio-1.0
   hs-source-dirs:   tests
   main-is:          doctests.hs
-  build-depends: base
-  if impl(ghc >= 8.2) && impl(ghc < 8.10)
-    build-depends: doctest           >=0.15
-                 , mwc-random
-                 , scheduler
-                 , vector
+  build-depends:    base           >= 4.9 && < 5
   default-language:    Haskell2010
 
 source-repository head
diff --git a/src/Control/Scheduler.hs b/src/Control/Scheduler.hs
--- a/src/Control/Scheduler.hs
+++ b/src/Control/Scheduler.hs
@@ -1,8 +1,8 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE MonoLocalBinds #-}
-{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 -- |
 -- Module      : Control.Scheduler
 -- Copyright   : (c) Alexey Kuleshevich 2018-2021
@@ -162,7 +162,7 @@
 -- | Schedule a job that will get a worker state passed as an argument
 --
 -- @since 1.4.0
-scheduleWorkState :: MonadPrimBase RealWorld m => SchedulerWS ws a -> (ws -> m a) -> m ()
+scheduleWorkState :: (PrimBase m, RealWorld ~ PrimState m) => SchedulerWS ws a -> (ws -> m a) -> m ()
 scheduleWorkState schedulerS withState =
   scheduleWorkId (_getScheduler schedulerS) $ \(WorkerId i) ->
     withState (indexSmallArray (_workerStatesArray (_workerStates schedulerS)) i)
@@ -170,7 +170,7 @@
 -- | Same as `scheduleWorkState`, but dont' keep the result of computation.
 --
 -- @since 1.4.0
-scheduleWorkState_ :: MonadPrimBase RealWorld m => SchedulerWS ws () -> (ws -> m ()) -> m ()
+scheduleWorkState_ :: (PrimBase m, RealWorld ~ PrimState m) => SchedulerWS ws () -> (ws -> m ()) -> m ()
 scheduleWorkState_ schedulerS withState =
   scheduleWorkId_ (_getScheduler schedulerS) $ \(WorkerId i) ->
     withState (indexSmallArray (_workerStatesArray (_workerStates schedulerS)) i)
@@ -191,7 +191,7 @@
 -- scheduler.
 --
 -- @since 1.2.0
-scheduleWorkId :: MonadPrimBase s m => Scheduler s a -> (WorkerId -> m a) -> m ()
+scheduleWorkId :: (PrimBase m, s ~ PrimState m) => Scheduler s a -> (WorkerId -> m a) -> m ()
 scheduleWorkId s f = stToPrim (_scheduleWorkId s (primToPrim . f))
 
 -- | As soon as possible try to terminate any computation that is being performed by all
@@ -203,7 +203,7 @@
 -- although it will make sure their results are discarded.
 --
 -- @since 1.1.0
-terminate :: MonadPrim s m => Scheduler s a -> a -> m a
+terminate :: (PrimMonad m, s ~ PrimState m) => Scheduler s a -> a -> m a
 terminate scheduler a = stToPrim (_terminate scheduler (Early a))
 
 -- | Same as `terminate`, but returning a single element list containing the supplied
@@ -216,14 +216,14 @@
 -- function.
 --
 -- @since 1.1.0
-terminateWith :: MonadPrim s m => Scheduler s a -> a -> m a
+terminateWith :: (PrimMonad m, s ~ PrimState m) => Scheduler s a -> a -> m a
 terminateWith scheduler a = stToPrim $ _terminate scheduler (EarlyWith a)
 
 -- | Schedule an action to be picked up and computed by a worker from a pool of
 -- jobs. Similar to `scheduleWorkId`, except the job doesn't get the worker id.
 --
 -- @since 1.0.0
-scheduleWork :: MonadPrimBase s m => Scheduler s a -> m a -> m ()
+scheduleWork :: (PrimBase m, s ~ PrimState m) => Scheduler s a -> m a -> m ()
 scheduleWork scheduler f = stToPrim $ _scheduleWorkId scheduler (const (primToPrim f))
 
 
@@ -232,13 +232,13 @@
 -- | Same as `scheduleWork`, but only for a `Scheduler` that doesn't keep the results.
 --
 -- @since 1.1.0
-scheduleWork_ :: MonadPrimBase s m => Scheduler s () -> m () -> m ()
+scheduleWork_ :: (PrimBase m, s ~ PrimState m) => Scheduler s () -> m () -> m ()
 scheduleWork_ s = stToPrim . scheduleWork s . primToPrim
 
 -- | Same as `scheduleWorkId`, but only for a `Scheduler` that doesn't keep the results.
 --
 -- @since 1.2.0
-scheduleWorkId_ :: MonadPrimBase s m => Scheduler s () -> (WorkerId -> m ()) -> m ()
+scheduleWorkId_ :: (PrimBase m, s ~ PrimState m) => Scheduler s () -> (WorkerId -> m ()) -> m ()
 scheduleWorkId_ scheduler f = stToPrim $ _scheduleWorkId scheduler (primToPrim . f)
 
 -- | Schedule the same action to run @n@ times concurrently. This differs from
@@ -247,7 +247,7 @@
 -- To be called within a `withScheduler` block.
 --
 -- @since 2.0.0
-replicateWork :: MonadPrimBase s m => Scheduler s a -> Int -> m a -> m ()
+replicateWork :: (PrimBase m, s ~ PrimState m) => Scheduler s a -> Int -> m a -> m ()
 replicateWork scheduler n f = go n
   where
     go !k
@@ -258,7 +258,7 @@
 -- | Same as `replicateWork`, but it does not retain the results of scheduled jobs
 --
 -- @since 2.0.0
-replicateWork_ :: MonadPrimBase s m => Scheduler s () -> Int -> m a -> m ()
+replicateWork_ :: (PrimBase m, s ~ PrimState m) => Scheduler s () -> Int -> m a -> m ()
 replicateWork_ scheduler n f = go n
   where
     go !k
@@ -270,7 +270,7 @@
 -- /Important/ - In case of `Seq` computation strategy this function has no affect.
 --
 -- @since 1.1.0
-terminate_ :: MonadPrim s m => Scheduler s () -> m ()
+terminate_ :: (PrimMonad m, s ~ PrimState m) => Scheduler s () -> m ()
 terminate_ s = stToPrim $ _terminate s (Early ())
 
 
@@ -278,7 +278,7 @@
 -- computation strategy, except it is restricted to `PrimMonad`, instead of `MonadUnliftIO`.
 --
 -- @since 1.4.2
-withTrivialScheduler :: MonadPrim s m => (Scheduler s a -> m b) -> m [a]
+withTrivialScheduler :: (PrimMonad m, s ~ PrimState m) => (Scheduler s a -> m b) -> m [a]
 withTrivialScheduler action = F.toList <$> withTrivialSchedulerR action
 
 
@@ -305,7 +305,8 @@
 traverseConcurrently_ :: (MonadUnliftIO m, Foldable t) => Comp -> (a -> m b) -> t a -> m ()
 traverseConcurrently_ comp f xs =
   withRunInIO $ \run ->
-    withScheduler_ comp $ \s -> scheduleWork s $ F.traverse_ (scheduleWork s . void . run . f) xs
+    withScheduler_ comp $ \s -> F.traverse_ (scheduleWork_ s . void . run . f) xs
+{-# INLINE traverseConcurrently_ #-}
 
 -- | Replicate an action @n@ times and schedule them acccording to the supplied computation
 -- strategy.
@@ -315,6 +316,7 @@
 replicateConcurrently comp n f =
   withRunInIO $ \run ->
     withScheduler comp $ \s -> replicateM_ n $ scheduleWork s (run f)
+{-# INLINE replicateConcurrently #-}
 
 -- | Just like `replicateConcurrently`, but discards the results of computation.
 --
@@ -322,8 +324,8 @@
 replicateConcurrently_ :: MonadUnliftIO m => Comp -> Int -> m a -> m ()
 replicateConcurrently_ comp n f =
   withRunInIO $ \run -> do
-    withScheduler_ comp $ \s -> scheduleWork s $ replicateM_ n (scheduleWork s $ void $ run f)
-
+    withScheduler_ comp $ \s -> replicateM_ n (scheduleWork_ s $ void $ run f)
+{-# INLINE replicateConcurrently_ #-}
 
 
 
@@ -410,7 +412,7 @@
 -- | Check if the supplied batch has already finished.
 --
 -- @since 1.5.0
-hasBatchFinished :: MonadPrim s m => Batch s a -> m Bool
+hasBatchFinished :: (PrimMonad m, s ~ PrimState m) => Batch s a -> m Bool
 hasBatchFinished = stToPrim . batchHasFinished
 {-# INLINE hasBatchFinished #-}
 
@@ -423,21 +425,21 @@
 -- concurrent cancelation and it will return `True`.
 --
 -- @since 1.5.0
-cancelBatch :: MonadPrim s m => Batch s a -> a -> m Bool
+cancelBatch :: (PrimMonad m, s ~ PrimState m) => Batch s a -> a -> m Bool
 cancelBatch b = stToPrim . batchCancel b
 {-# INLINE cancelBatch #-}
 
 -- | Same as `cancelBatch`, but only works with schedulers that don't care about results
 --
 -- @since 1.5.0
-cancelBatch_ :: MonadPrim s m => Batch s () -> m Bool
+cancelBatch_ :: (PrimMonad m, s ~ PrimState m) => Batch s () -> m Bool
 cancelBatch_ b = stToPrim $ batchCancel b ()
 {-# INLINE cancelBatch_ #-}
 
 -- | Same as `cancelBatch_`, but the result of computation will be set to `FinishedEarlyWith`
 --
 -- @since 1.5.0
-cancelBatchWith :: MonadPrim s m => Batch s a -> a -> m Bool
+cancelBatchWith :: (PrimMonad m, s ~ PrimState m) => Batch s a -> a -> m Bool
 cancelBatchWith b = stToPrim . batchCancelWith b
 {-# INLINE cancelBatchWith #-}
 
@@ -446,7 +448,7 @@
 --
 -- @since 1.5.0
 getCurrentBatch ::
-     MonadPrim s m => Scheduler s a -> m (Batch s a)
+     (PrimMonad m, s ~ PrimState m) => Scheduler s a -> m (Batch s a)
 getCurrentBatch scheduler = stToPrim $ do
   batchId <- _currentBatchId scheduler
   pure $ Batch
@@ -471,7 +473,7 @@
 -- scheduler prior to starting the batch it will end up on the batch result list.
 --
 -- @since 1.5.0
-runBatch :: MonadPrimBase s m => Scheduler s a -> (Batch s a -> m c) -> m [a]
+runBatch :: (PrimBase m, s ~ PrimState m) => Scheduler s a -> (Batch s a -> m c) -> m [a]
 runBatch scheduler f = stToPrim $ do
   _ <- primToPrim . f =<< getCurrentBatch scheduler
   reverse . resultsToList <$> _waitForCurrentBatch scheduler
@@ -481,7 +483,7 @@
 --
 -- @since 1.5.0
 runBatch_ ::
-     MonadPrimBase s m => Scheduler s () -> (Batch s () -> m c) -> m ()
+     (PrimBase m, s ~ PrimState m) => Scheduler s () -> (Batch s () -> m c) -> m ()
 runBatch_ scheduler f = stToPrim $ do
   _ <- primToPrim . f =<< getCurrentBatch scheduler
   void (_waitForCurrentBatch scheduler)
@@ -492,7 +494,7 @@
 --
 -- @since 1.5.0
 runBatchR ::
-     MonadPrimBase s m => Scheduler s a -> (Batch s a -> m c) -> m (Results a)
+     (PrimBase m, s ~ PrimState m) => Scheduler s a -> (Batch s a -> m c) -> m (Results a)
 runBatchR scheduler f = stToPrim $ do
   _ <- primToPrim . f =<< getCurrentBatch scheduler
   reverseResults <$> _waitForCurrentBatch scheduler
@@ -520,7 +522,5 @@
 False
 >>> didAWorkerDie $ withScheduler Par $ \ s -> scheduleWork s $ myThreadId >>= killThread >> pure False
 True
->>> withScheduler Par $ \ s -> scheduleWork s $ myThreadId >>= killThread >> pure False
-*** Exception: thread killed
 
 -}
diff --git a/src/Control/Scheduler/Computation.hs b/src/Control/Scheduler/Computation.hs
--- a/src/Control/Scheduler/Computation.hs
+++ b/src/Control/Scheduler/Computation.hs
@@ -72,7 +72,7 @@
 instance Monoid Comp where
   mempty = Seq
   {-# INLINE mempty #-}
-  mappend = joinComp
+  mappend = (<>)
   {-# INLINE mappend #-}
 
 instance Semigroup Comp where
diff --git a/src/Control/Scheduler/Internal.hs b/src/Control/Scheduler/Internal.hs
--- a/src/Control/Scheduler/Internal.hs
+++ b/src/Control/Scheduler/Internal.hs
@@ -1,10 +1,11 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE MonoLocalBinds #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# OPTIONS_HADDOCK hide, not-home #-}
 -- |
 -- Module      : Control.Scheduler.Internal
@@ -115,23 +116,23 @@
 -- rather computed immediately.
 --
 -- @since 1.4.2
-withTrivialSchedulerR :: forall a b m s. MonadPrim s m => (Scheduler s a -> m b) -> m (Results a)
+withTrivialSchedulerR :: forall a b m s. (PrimMonad m, s ~ PrimState m) => (Scheduler s a -> m b) -> m (Results a)
 withTrivialSchedulerR action = do
   resVar <- newMutVar []
   batchVar <- newMutVar $ BatchId 0
   finResVar <- newMutVar Nothing
   batchEarlyVar <- newMutVar Nothing
-  let bumpCurrentBatchId :: MonadPrim s m' => m' ()
+  let bumpCurrentBatchId :: (PrimMonad m', s ~ PrimState m') => m' ()
       bumpCurrentBatchId = atomicModifyMutVar' batchVar (\(BatchId x) -> (BatchId (x + 1), ()))
-      bumpBatchId :: MonadPrim s m' => BatchId -> m' Bool
+      bumpBatchId :: (PrimMonad m', s ~ PrimState m') => BatchId -> m' Bool
       bumpBatchId (BatchId c) =
         atomicModifyMutVar' batchVar $ \b@(BatchId x) ->
           if x == c
             then (BatchId (x + 1), True)
             else (b, False)
-      takeBatchEarly :: MonadPrim s m' => m' (Maybe (Early a))
+      takeBatchEarly :: (PrimMonad m', s ~ PrimState m') => m' (Maybe (Early a))
       takeBatchEarly = atomicModifyMutVar' batchEarlyVar $ \mEarly -> (Nothing, mEarly)
-      takeResults :: MonadPrim s m' => m' [a]
+      takeResults :: (PrimMonad m', s ~ PrimState m') => m' [a]
       takeResults = atomicModifyMutVar' resVar $ \res -> ([], res)
   _ <-
     action $
diff --git a/src/Control/Scheduler/Types.hs b/src/Control/Scheduler/Types.hs
--- a/src/Control/Scheduler/Types.hs
+++ b/src/Control/Scheduler/Types.hs
@@ -34,6 +34,7 @@
 import Control.Exception
 import Control.Scheduler.Computation
 import Control.Scheduler.Queue
+import Data.Functor.Classes
 import Data.IORef
 import Data.Primitive.SmallArray
 import Data.Primitive.PVar
@@ -77,6 +78,22 @@
       Finished xs -> Finished <$> traverse f xs
       FinishedEarly xs x -> FinishedEarly <$> traverse f xs <*> f x
       FinishedEarlyWith x -> FinishedEarlyWith <$> f x
+
+instance Eq1 Results where
+  liftEq f (Finished xs1) (Finished xs2) = liftEq f xs1 xs2
+  liftEq f (FinishedEarly xs1 x1) (FinishedEarly xs2 x2) = liftEq f xs1 xs2 && f x1 x2
+  liftEq f (FinishedEarlyWith x1) (FinishedEarlyWith x2) = f x1 x2
+  liftEq _ _ _ = False
+
+instance Show1 Results where
+  liftShowsPrec f g n = \case
+    Finished xs -> wrap (("Finished " ++) . g xs)
+    FinishedEarly xs x -> wrap (("FinishedEarly " ++) . g xs . (" " ++) . f 11 x)
+    FinishedEarlyWith x -> wrap (("FinishedEarlyWith " ++) . f 11 x)
+    where
+      wrap s
+        | n <= 1 = s
+        | otherwise = ('(' :) . s . (++ ")")
 
 data Jobs m a = Jobs
   { jobsNumWorkers       :: {-# UNPACK #-} !Int
diff --git a/tests/Control/SchedulerSpec.hs b/tests/Control/SchedulerSpec.hs
--- a/tests/Control/SchedulerSpec.hs
+++ b/tests/Control/SchedulerSpec.hs
@@ -20,16 +20,13 @@
 import qualified Data.Foldable as F (toList, traverse_)
 import Data.IORef
 import Data.List (groupBy, sort, sortOn)
+import Data.Proxy
 import Test.Hspec
 import Test.Hspec.QuickCheck
 import Test.QuickCheck
+import Test.QuickCheck.Classes
 import Test.QuickCheck.Function
 import Test.QuickCheck.Monadic
-import Test.Validity.Eq
-import Test.Validity.Functor
-import Test.Validity.Monoid
-import Test.Validity.Ord
-import Test.Validity.Show
 import UnliftIO.Async
 import UnliftIO.Exception hiding (assert)
 #if !MIN_VERSION_base(4,11,0)
@@ -514,7 +511,6 @@
 --     res' <- withSchedulerR comp scheduleJobs
 --     pure (res === [n] .&&. res' === FinishedEarlyWith n)
 
-
 spec :: Spec
 spec = do
   describe "Comp" $ do
@@ -525,27 +521,40 @@
         property $ \(x :: Comp) y z -> x <> (y <> z) === (x <> y) <> z
       it "mconcat = foldr '(<>)' mempty" $
         property $ \(xs :: [Comp]) -> mconcat xs === foldr (<>) mempty xs
-      eqSpecOnArbitrary @Comp
-      monoidSpecOnArbitrary @Comp
+    it "Laws" $
+      lawsCheckOne (Proxy @Comp)
+        [ eqLaws
+        , showLaws
+        , semigroupLaws
+        , monoidLaws
+        ]
     describe "Show" $ do
       it "show == showsPrec 0" $ property $ \(x :: Comp) -> x `deepseq` show x === showsPrec 0 x ""
       it "(show) == showsPrec 1" $
         property $ \(x :: Comp) (Positive n) ->
           x /= Seq && x /= Par ==> ("(" <> show x <> ")" === showsPrec n x "")
   describe "Results" $ do
-    eqSpecOnArbitrary @(Results Int)
-    functorSpecOnArbitrary @Results
-    showReadSpecOnArbitrary @(Results Int)
+    it "Laws" $ do
+      lawsCheckOne (Proxy @(Results Int))
+        [ eqLaws
+        , showLaws
+        , showReadLaws
+        ]
+      lawsCheck (functorLaws (Proxy @Results))
     it "Traversable" $ property $ \(rs :: Results Int) (f :: Fun Int (Maybe Int)) ->
       traverse (apply f) (F.toList rs) === fmap F.toList (traverse (apply f) rs)
   describe "WorkerId" $ do
-    eqSpecOnArbitrary @WorkerId
-    ordSpecOnArbitrary @WorkerId
     it "MaxMin" $ property $ \x y ->
       conjoin [ max (WorkerId x) (WorkerId y) === WorkerId (max x y)
               , min (WorkerId x) (WorkerId y) === WorkerId (min x y)
               ]
-    showReadSpecOnArbitrary @WorkerId
+    it "Laws" $ do
+      lawsCheckOne (Proxy @WorkerId)
+        [ eqLaws
+        , ordLaws
+        , showLaws
+        , showReadLaws
+        ]
     describe "Enum" $ do
       it "toEnumFromEnum" $ property $ \ wid@(WorkerId i) ->
         toEnum (getWorkerId wid) === wid .&&. fromEnum wid === i
@@ -621,13 +630,17 @@
   arbitrary = WorkerId <$> arbitrary
 
 instance Arbitrary a => Arbitrary (Results a) where
-  arbitrary =
+  arbitrary = liftArbitrary arbitrary
+
+instance Arbitrary1 Results where
+  liftArbitrary gen =
     oneof
-      [ Finished <$> arbitrary
-      , FinishedEarly <$> arbitrary <*> arbitrary
-      , FinishedEarlyWith <$> arbitrary
+      [ Finished <$> listOf gen
+      , FinishedEarly <$> listOf gen <*> gen
+      , FinishedEarlyWith <$> gen
       ]
 
+#if !MIN_VERSION_QuickCheck(2,15,0)
 -- | Assert a synchronous exception
 assertExceptionIO :: (NFData a, Exception exc) =>
                      (exc -> Bool) -- ^ Return True if that is the exception that was expected
@@ -641,6 +654,7 @@
         (do res <- action
             res `deepseq` return False) $ \exc -> displayException exc `deepseq` return (isExc exc)
     assert hasFailed
+#endif
 
 assertAsyncExceptionIO :: (Exception e, NFData a) => (e -> Bool) -> IO a -> Property
 assertAsyncExceptionIO isAsyncExc action =
diff --git a/tests/doctests.hs b/tests/doctests.hs
--- a/tests/doctests.hs
+++ b/tests/doctests.hs
@@ -1,17 +1,4 @@
-{-# LANGUAGE CPP #-}
 module Main where
 
-#if __GLASGOW_HASKELL__ >= 802 && __GLASGOW_HASKELL__ < 810
-
-import Test.DocTest (doctest)
-
 main :: IO ()
-main = doctest ["src"]
-
-#else
-
--- TODO: fix doctest support
-main :: IO ()
-main = putStrLn "\nDoctests are not supported for ghc version 8.2 and prior as well as 8.10\n"
-
-#endif
+main = pure ()
