diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,8 @@
+0.8.1
+===
+* GHC 9.0.1 support
+* API fixes for random-1.2; `randomS`, `randomSM` & `randomSs` 
+
 0.7.0
 =====
 
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,3 @@
 import Distribution.Simple
+
 main = defaultMain
diff --git a/numhask-space.cabal b/numhask-space.cabal
--- a/numhask-space.cabal
+++ b/numhask-space.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.4
 name: numhask-space
-version: 0.8.0.0
+version: 0.8.1.0
 synopsis:
   Numerical spaces.
 description:
@@ -31,9 +31,12 @@
   LICENSE
 build-type:
   Simple
-tested-with: GHC ==8.8.4 || ==8.10.2 || ==9.0.1
+tested-with:
+  GHC ==8.8.4
+   || ==8.10.4
+   || ==9.0.1
+   || ==9.2.0.20210821
 extra-source-files:
-  readme.md
   ChangeLog.md
 source-repository head
   type:
@@ -58,9 +61,9 @@
     base >=4.7 && <5,
     containers >= 0.6 && < 0.7,
     distributive >=0.2.2 && <1,
-    numhask >= 0.8 && < 0.9,
-    random >=1.2 && < 1.3,
-    semigroupoids >=5 && <6,
+    numhask >= 0.8.1 && < 0.9,
+    random >= 1.2 && < 1.3,
+    semigroupoids >=5 && <5.4,
     tdigest >= 0.2.1 && < 0.3,
     text >= 1.2.3.1 && <2,
     time >= 1.9.1 && <1.12,
@@ -76,22 +79,3 @@
     NumHask.Space.XY
   other-modules:
   default-language: Haskell2010
-
-test-suite test
-  type: exitcode-stdio-1.0
-  main-is: test.hs
-  hs-source-dirs:
-    test
-  build-depends:
-    base >=4.7 && <5,
-    doctest >= 0.16 && < 0.19
-  default-language: Haskell2010
-  ghc-options:
-    -Wall
-    -Wcompat
-    -Wincomplete-record-updates
-    -Wincomplete-uni-patterns
-    -Wredundant-constraints
-    -fwrite-ide-info
-    -hiedir=.hie
-  default-extensions:
diff --git a/readme.md b/readme.md
deleted file mode 100644
--- a/readme.md
+++ /dev/null
@@ -1,23 +0,0 @@
-numhask-space
-===
-
-[![Build Status](https://travis-ci.org/tonyday567/numhask-space.svg)](https://travis-ci.org/tonyday567/numhask-space) [![Hackage](https://img.shields.io/hackage/v/numhask-space.svg)](https://hackage.haskell.org/package/numhask-space)
-
-`numhask-space` provides support for spaces where [space](https://en.wikipedia.org/wiki/Space_(mathematics)) is defined as a set of numbers with a `lower `and `upper` bound.
-
-Usage
-===
-
-``` haskell
-{-# LANGUAGE NegativeLiterals #-}
-{-# LANGUAGE RebindableSyntax #-}
-import NumHask.Prelude
-import NumHask.Space
-```
-
-Develop
-===
-
-```
-stack build --test --haddock --file-watch
-```
diff --git a/src/NumHask/Space.hs b/src/NumHask/Space.hs
--- a/src/NumHask/Space.hs
+++ b/src/NumHask/Space.hs
@@ -45,7 +45,6 @@
 -- $setup
 --
 -- >>> :set -XRebindableSyntax
--- >>> :set -XNegativeLiterals
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
 -- >>> Point 1 1
diff --git a/src/NumHask/Space/Histogram.hs b/src/NumHask/Space/Histogram.hs
--- a/src/NumHask/Space/Histogram.hs
+++ b/src/NumHask/Space/Histogram.hs
@@ -29,6 +29,10 @@
 import NumHask.Space.Rect
 import NumHask.Space.Types
 
+-- $setup
+-- >>> import NumHask.Prelude
+-- >>> import NumHask.Space
+
 -- | This Histogram is a list of contiguous boundaries (a boundary being the lower edge of one bucket and the upper edge of another), and a value (usually a count) for each bucket, represented here as a map
 --
 -- Overs and Unders are contained in key = 0 and key = length cuts
diff --git a/src/NumHask/Space/Point.hs b/src/NumHask/Space/Point.hs
--- a/src/NumHask/Space/Point.hs
+++ b/src/NumHask/Space/Point.hs
@@ -39,7 +39,8 @@
 import System.Random.Stateful
 
 -- $setup
--- >>> :set -XNoImplicitPrelude
+-- >>> import NumHask.Prelude
+-- >>> import NumHask.Space
 
 -- | A 2-dimensional Point of a's
 --
@@ -173,10 +174,9 @@
   Norm (Point a) a
   where
   norm (Point x y) = sqrt (x * x + y * y)
-  basis p = let m = norm p in bool (p /. m) zero (m==zero)
+  basis p = let m = norm p in bool (p /. m) zero (m == zero)
 
 -- | angle formed by a vector from the origin to a Point and the x-axis (Point 1 0). Note that an angle between two points p1 & p2 is thus angle p2 - angle p1
---
 instance (TrigField a) => Direction (Point a) a where
   angle (Point x y) = atan2 y x
   ray x = Point (cos x) (sin x)
@@ -235,7 +235,7 @@
 
 -- | reflect on x-axis
 flipY :: (Subtractive a) => Point a -> Point a
-flipY (Point x y) = Point x (- y)
+flipY (Point x y) = Point x (-y)
 
 -- | A line is a composed of 2 'Point's
 data Line a = Line
@@ -249,7 +249,7 @@
 
 -- | Return the parameters (a, b, c) for the line equation @a*x + b*y + c = 0@.
 lineSolve :: (ExpField a, Eq a) => Line a -> (a, a, a)
-lineSolve (Line p1 p2) = (- my, mx, c)
+lineSolve (Line p1 p2) = (-my, mx, c)
   where
     m@(Point mx my) = basis (p2 - p1)
     c = crossP p1 m
diff --git a/src/NumHask/Space/Range.hs b/src/NumHask/Space/Range.hs
--- a/src/NumHask/Space/Range.hs
+++ b/src/NumHask/Space/Range.hs
@@ -28,6 +28,8 @@
 --
 -- >>> :set -XFlexibleContexts
 -- >>> :set -XGADTs
+-- >>> import NumHask.Prelude
+-- >>> import NumHask.Space
 
 -- | A continuous range over type a
 --
@@ -160,7 +162,7 @@
   one = Range (negate one / (one + one)) (one / (one + one))
 
 instance (Ord a, Field a) => Divisive (Range a) where
-  recip a = bool (Range (- m - one / (two * r)) (- m + one / (two * r))) zero (r == zero)
+  recip a = bool (Range (-m - one / (two * r)) (-m + one / (two * r))) zero (r == zero)
     where
       m = mid a
       r = width a
diff --git a/src/NumHask/Space/Rect.hs b/src/NumHask/Space/Rect.hs
--- a/src/NumHask/Space/Rect.hs
+++ b/src/NumHask/Space/Rect.hs
@@ -35,8 +35,8 @@
 import Data.Distributive as D
 import Data.Functor.Compose
 import Data.Functor.Rep
-import NumHask.Prelude hiding (Distributive)
 import Data.List.NonEmpty
+import NumHask.Prelude hiding (Distributive)
 import NumHask.Space.Point
 import NumHask.Space.Range
 import NumHask.Space.Types
@@ -44,6 +44,8 @@
 -- $setup
 --
 -- >>> :set -XFlexibleContexts
+-- >>> import NumHask.Prelude
+-- >>> import NumHask.Space
 
 -- | a rectangular space often representing a finite 2-dimensional or XY plane.
 --
diff --git a/src/NumHask/Space/Time.hs b/src/NumHask/Space/Time.hs
--- a/src/NumHask/Space/Time.hs
+++ b/src/NumHask/Space/Time.hs
@@ -1,7 +1,6 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NegativeLiterals #-}
 {-# LANGUAGE RebindableSyntax #-}
 {-# LANGUAGE StrictData #-}
 {-# OPTIONS_GHC -Wall #-}
@@ -14,6 +13,7 @@
     TimeGrain (..),
     floorGrain,
     ceilingGrain,
+    addGrain,
     sensibleTimeGrid,
     PosDiscontinuous (..),
     placedTimeLabelDiscontinuous,
@@ -28,26 +28,25 @@
 import Data.Containers.ListUtils (nubOrd)
 import Data.Fixed (Fixed (MkFixed))
 import qualified Data.Sequence as Seq
+import Data.Text (Text, pack, unpack)
 import Data.Time
 import NumHask.Prelude
 import NumHask.Space.Range
 import NumHask.Space.Types
-import Data.Text (Text, unpack, pack)
 
 -- $setup
 --
--- >>> :set -XRebindableSyntax
--- >>> :set -XNegativeLiterals
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
--- >>> Point 1 1
--- Point 1 1
+-- >>> import NumHask.Space.Time
+-- >>> import Data.Text (Text, pack)
+-- >>> import Data.Time
+--
+-- > :set -XOverloadedStrings
 
 -- | parse text as per iso8601
 --
--- >>> :set -XOverloadedStrings
--- >>> let t0 = parseUTCTime ("2017-12-05" :: Text)
--- >>> t0
+-- >>> parseUTCTime (pack "2017-12-05")
 -- Just 2017-12-05 00:00:00 UTC
 parseUTCTime :: Text -> Maybe UTCTime
 parseUTCTime =
@@ -236,7 +235,7 @@
 --
 -- The assumption with getSensibleTimeGrid is that there is a list of discountinuous UTCTimes rather than a continuous range.  Output is a list of index points for the original [UTCTime] and label tuples, and a list of unused list elements.
 --
--- >>> placedTimeLabelDiscontinuous PosIncludeBoundaries (Just "%d %b") 2 [UTCTime (fromGregorian 2017 12 6) (toDiffTime 0), UTCTime (fromGregorian 2017 12 29) (toDiffTime 0), UTCTime (fromGregorian 2018 1 31) (toDiffTime 0), UTCTime (fromGregorian 2018 3 3) (toDiffTime 0)]
+-- >>> placedTimeLabelDiscontinuous PosIncludeBoundaries (Just (pack "%d %b")) 2 [UTCTime (fromGregorian 2017 12 6) (toDiffTime 0), UTCTime (fromGregorian 2017 12 29) (toDiffTime 0), UTCTime (fromGregorian 2018 1 31) (toDiffTime 0), UTCTime (fromGregorian 2018 3 3) (toDiffTime 0)]
 -- ([(0,"06 Dec"),(1,"31 Dec"),(2,"28 Feb"),(3,"03 Mar")],[])
 placedTimeLabelDiscontinuous :: PosDiscontinuous -> Maybe Text -> Int -> [UTCTime] -> ([(Int, Text)], [UTCTime])
 placedTimeLabelDiscontinuous posd format n ts = (zip (fst <$> inds') labels, rem')
@@ -284,7 +283,7 @@
 
 -- | A sensible time grid between two dates, projected onto (0,1) with no attempt to get finnicky.
 --
--- >>> placedTimeLabelContinuous PosIncludeBoundaries (Just "%d %b") 2 (Range (UTCTime (fromGregorian 2017 12 6) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 29) (toDiffTime 0)))
+-- >>> placedTimeLabelContinuous PosIncludeBoundaries (Just (pack "%d %b")) 2 (Range (UTCTime (fromGregorian 2017 12 6) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 29) (toDiffTime 0)))
 -- [(0.0,"06 Dec"),(0.4347826086956521,"16 Dec"),(0.8695652173913042,"26 Dec"),(0.9999999999999999,"29 Dec")]
 placedTimeLabelContinuous :: PosDiscontinuous -> Maybe Text -> Int -> Range UTCTime -> [(Double, Text)]
 placedTimeLabelContinuous posd format n r@(Range l u) = zip tpsd labels
@@ -309,10 +308,10 @@
 -- >>> sensibleTimeGrid InnerPos 2 (Range (UTCTime (fromGregorian 2017 1 1) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 30) (toDiffTime 0)))
 -- (Months 6,[2017-06-30 00:00:00 UTC])
 --
--- >>>  sensibleTimeGrid UpperPos 2 (Range (UTCTime (fromGregorian 2017 1 1) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 30) (toDiffTime 0)))
+-- >>> sensibleTimeGrid UpperPos 2 (Range (UTCTime (fromGregorian 2017 1 1) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 30) (toDiffTime 0)))
 -- (Months 6,[2017-06-30 00:00:00 UTC,2017-12-31 00:00:00 UTC])
 --
--- >>>sensibleTimeGrid LowerPos 2 (Range (UTCTime (fromGregorian 2017 1 1) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 30) (toDiffTime 0)))
+-- >>> sensibleTimeGrid LowerPos 2 (Range (UTCTime (fromGregorian 2017 1 1) (toDiffTime 0)) (UTCTime (fromGregorian 2017 12 30) (toDiffTime 0)))
 -- (Months 6,[2016-12-31 00:00:00 UTC,2017-06-30 00:00:00 UTC])
 sensibleTimeGrid :: Pos -> Int -> Range UTCTime -> (TimeGrain, [UTCTime])
 sensibleTimeGrid p n (Range l u) = (grain, ts)
diff --git a/src/NumHask/Space/Types.hs b/src/NumHask/Space/Types.hs
--- a/src/NumHask/Space/Types.hs
+++ b/src/NumHask/Space/Types.hs
@@ -19,6 +19,7 @@
     Pos (..),
     space1,
     randomS,
+    randomSM,
     randomSs,
     memberOf,
     contains,
@@ -39,10 +40,17 @@
   )
 where
 
+import Control.Monad
 import NumHask.Prelude
+import System.Random.Stateful
 import qualified Prelude as P
-import System.Random
 
+-- $setup
+-- >>> import NumHask.Prelude
+-- >>> import NumHask.Space
+-- >>> import System.Random.Stateful
+-- >>> let g = mkStdGen 42
+
 -- | A 'Space' is a continuous set of numbers. Continuous here means that the set has an upper and lower bound, and an element that is between these two bounds is a member of the 'Space'.
 --
 -- > a `union` b == b `union` a
@@ -164,19 +172,30 @@
   (<>) (Intersection a) (Intersection b) = Intersection (a `union` b)
 
 -- | supply a random element within a 'Space'
-randomS :: (Space s, RandomGen g, Random (Element s)) => s -> g -> (Element s, g)
-randomS s = randomR (lower s, upper s)
+--
+-- >>> randomS (one :: Range Double) g
+-- (0.43085240252163404,StdGen {unStdGen = SMGen 4530528345362647137 13679457532755275413})
+randomS :: (Space s, RandomGen g, UniformRange (Element s)) => s -> g -> (Element s, g)
+randomS s = uniformR (lower s, upper s)
 
--- | supply an (infinite) list of random elements within a 'Space'
+-- | StatefulGen version of randomS
 --
+-- >>> import Control.Monad
+-- >>> runStateGen_ g (randomSM (one :: Range Double))
+-- 0.43085240252163404
+randomSM :: (UniformRange (Element s), StatefulGen g m, Space s) => s -> g -> m (Element s)
+randomSM s = uniformRM (lower s, upper s)
+
+-- | list of n random elements within a 'Space'
+--
 -- >>> let g = mkStdGen 42
--- >>> take 3 $ randomSs (one :: Range Double) g
+-- >>> fst (randomSs 3 (one :: Range Double) g)
 -- [0.43085240252163404,-6.472345419562497e-2,0.3854692674681801]
 --
--- >>> take 3 $ randomSs (Rect 0 10 0 10 :: Rect Word8) g
--- [Point 8 0,Point 6 4,Point 5 3]
-randomSs :: (Space s, RandomGen g, Random (Element s)) => s -> g -> [Element s]
-randomSs s = randomRs (lower s, upper s)
+-- >>> fst (randomSs 3 (Rect 0 10 0 10 :: Rect Int) g)
+-- [Point 0 7,Point 0 2,Point 1 7]
+randomSs :: (Space s, RandomGen g, UniformRange (Element s)) => Int -> s -> g -> ([Element s], g)
+randomSs n s g = runStateGen g (replicateM n . randomSM s)
 
 -- | a space that can be divided neatly
 --
@@ -212,7 +231,6 @@
 -- | interpolate a space
 --
 -- > interpolate s x == project s (zero ... one) x
---
 interpolate :: (Space s, Ring (Element s)) => s -> Element s -> Element s
 interpolate s x = lower s + x * width s
 
@@ -313,10 +331,10 @@
             ( Transform
                 (a / det)
                 (d / det)
-                (- (a * c + d * f) / det)
+                (-(a * c + d * f) / det)
                 (b / det)
                 (e / det)
-                (- (b * c + e * f) / det)
+                (-(b * c + e * f) / det)
             )
         )
         Nothing
@@ -346,4 +364,4 @@
 
 -- | Rotate an 'Affinity' (counter-clockwise)
 rotate :: (TrigField a) => a -> Transform a
-rotate a = Transform (cos a) (- sin a) zero (sin a) (cos a) zero
+rotate a = Transform (cos a) (-sin a) zero (sin a) (cos a) zero
diff --git a/src/NumHask/Space/XY.hs b/src/NumHask/Space/XY.hs
--- a/src/NumHask/Space/XY.hs
+++ b/src/NumHask/Space/XY.hs
@@ -15,12 +15,16 @@
   )
 where
 
+import qualified Data.List.NonEmpty as NonEmpty
 import GHC.Show (show)
 import NumHask.Prelude hiding (show)
 import NumHask.Space.Point
 import NumHask.Space.Rect
 import NumHask.Space.Types
-import qualified Data.List.NonEmpty as NonEmpty
+
+-- $setup
+-- >>> import NumHask.Prelude
+-- >>> import NumHask.Space
 
 -- | unification of a point and rect on the plane
 data XY a
diff --git a/test/test.hs b/test/test.hs
deleted file mode 100644
--- a/test/test.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-{-# LANGUAGE RebindableSyntax #-}
-{-# OPTIONS_GHC -Wall #-}
-{-# OPTIONS_GHC -Wno-unused-imports #-}
-
-module Main where
-
-import Prelude
-import Test.DocTest
-
-main :: IO ()
-main =
-  doctest
-    [ "src/NumHask/Space.hs",
-      "src/NumHask/Space/Histogram.hs",
-      "src/NumHask/Space/Point.hs",
-      "src/NumHask/Space/Range.hs",
-      "src/NumHask/Space/Rect.hs",
-      "src/NumHask/Space/Time.hs",
-      "src/NumHask/Space/XY.hs"
-    ]
