diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+0.12
+==
+* rx,ry,rz,rw added to NumHask.Space.Rect
+
 0.11.1.0
 ===
 * Rect and Point show instances include negative brackets.
diff --git a/numhask-space.cabal b/numhask-space.cabal
--- a/numhask-space.cabal
+++ b/numhask-space.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: numhask-space
-version: 0.11.1.0
+version: 0.12.0.0
 license: BSD-3-Clause
 license-file: LICENSE
 copyright: Tony Day (c) 2016
@@ -21,7 +21,10 @@
 
 
 build-type: Simple
-tested-with: GHC ==8.10.7 || ==9.2.8 || ==9.4.5 || ==9.6.2
+tested-with:
+    , GHC == 9.10.1
+    , GHC == 9.6.5
+    , GHC == 9.8.2
 extra-doc-files: ChangeLog.md
 
 source-repository head
@@ -39,60 +42,7 @@
         -Wredundant-constraints
 
 common ghc2021-stanza
-    if impl ( ghc >= 9.2 )
-        default-language: GHC2021
-
-    if impl ( ghc < 9.2 )
-        default-language: Haskell2010
-        default-extensions:
-            BangPatterns
-            BinaryLiterals
-            ConstrainedClassMethods
-            ConstraintKinds
-            DeriveDataTypeable
-            DeriveFoldable
-            DeriveFunctor
-            DeriveGeneric
-            DeriveLift
-            DeriveTraversable
-            DoAndIfThenElse
-            EmptyCase
-            EmptyDataDecls
-            EmptyDataDeriving
-            ExistentialQuantification
-            ExplicitForAll
-            FlexibleContexts
-            FlexibleInstances
-            ForeignFunctionInterface
-            GADTSyntax
-            GeneralisedNewtypeDeriving
-            HexFloatLiterals
-            ImplicitPrelude
-            InstanceSigs
-            KindSignatures
-            MonomorphismRestriction
-            MultiParamTypeClasses
-            NamedFieldPuns
-            NamedWildCards
-            NumericUnderscores
-            PatternGuards
-            PolyKinds
-            PostfixOperators
-            RankNTypes
-            RelaxedPolyRec
-            ScopedTypeVariables
-            StandaloneDeriving
-            StarIsType
-            TraditionalRecordSyntax
-            TupleSections
-            TypeApplications
-            TypeOperators
-            TypeSynonymInstances
-
-    if impl ( ghc < 9.2 ) && impl ( ghc >= 8.10 )
-        default-extensions:
-            ImportQualifiedPost
-            StandaloneKindSignatures
+    default-language: GHC2021
 
 library
     import: ghc-options-stanza
@@ -100,7 +50,7 @@
     hs-source-dirs: src
     build-depends:
         , adjunctions   >=4.0 && <5
-        , base          >=4.7 && <5
+        , base          >=4.14 && <5
         , containers    >=0.6 && <0.8
         , distributive  >=0.4 && <0.7
         , numhask       >=0.10 && <0.13
@@ -108,7 +58,7 @@
         , semigroupoids >=5.3 && <6.1
         , tdigest       >=0.2.1 && <0.4
         , text          >=1.2 && <2.2
-        , time          >=1.9.1 && <1.13
+        , time          >=1.9.1 && <1.15
         , vector        >=0.12.3 && <0.14
     exposed-modules:
         NumHask.Space
@@ -118,3 +68,14 @@
         NumHask.Space.Rect
         NumHask.Space.Time
         NumHask.Space.Types
+
+test-suite doctests
+    import: ghc2021-stanza
+    main-is: doctests.hs
+    hs-source-dirs: test
+    build-depends:
+        , base             >=4.14 && <5
+        , doctest-parallel >=0.3 && <0.4
+        , numhask-space
+    ghc-options: -threaded
+    type: exitcode-stdio-1.0
diff --git a/src/NumHask/Space.hs b/src/NumHask/Space.hs
--- a/src/NumHask/Space.hs
+++ b/src/NumHask/Space.hs
@@ -39,6 +39,7 @@
 
 -- $setup
 --
+-- >>> :m -Prelude
 -- >>> :set -XRebindableSyntax
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
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,7 @@
 import NumHask.Space.Types
 
 -- $setup
+-- >>> :m -Prelude
 -- >>> :set -XRebindableSyntax
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
@@ -159,7 +160,9 @@
       fromMaybe 0 $
         TD.quantile x (TD.tdigest xs :: TD.TDigest 25)
   )
-    <$> ((/ fromIntegral n) . fromIntegral <$> [0 .. n])
+    . (/ fromIntegral n)
+    . fromIntegral
+    <$> [0 .. n]
 
 -- | single (approx) quantile
 --
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
@@ -31,6 +31,7 @@
 import System.Random.Stateful
 
 -- $setup
+-- >>> :m -Prelude
 -- >>> :set -XRebindableSyntax
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
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
@@ -6,6 +6,7 @@
 module NumHask.Space.Range
   ( Range (..),
     gridSensible,
+    stepSensible,
   )
 where
 
@@ -19,6 +20,7 @@
 
 -- $setup
 --
+-- >>> :m -Prelude
 -- >>> :set -XFlexibleContexts
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
@@ -157,6 +159,10 @@
   basis (Range l u) = bool (negate one) one (u >= l)
   magnitude (Range l u) = bool (u ... l) (l ... u) (u >= l)
 
+-- | Find a step that feels pleasent for a 10 digit species.
+--
+-- >>> stepSensible OuterPos 35 6
+-- 5.0
 stepSensible :: Pos -> Double -> Int -> Double
 stepSensible tp span' n =
   step + bool 0 (step / 2) (tp == MidPos)
@@ -180,8 +186,12 @@
   Int ->
   [Double]
 gridSensible tp inside r@(Range l u) n =
-  bool id (filter (`memberOf` r)) inside $
-    (+ bool 0 (step / 2) (tp == MidPos)) <$> posns
+  bool
+    ( bool id (filter (`memberOf` r)) inside $
+        (+ bool 0 (step / 2) (tp == MidPos)) <$> posns
+    )
+    [l - 0.5, l + 0.5]
+    (span' == zero)
   where
     posns = (first' +) . (step *) . fromIntegral <$> [i0 .. i1]
     span' = u - l
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
@@ -8,6 +8,11 @@
   ( Rect (..),
     pattern Rect,
     pattern Ranges,
+    rx,
+    rz,
+    ry,
+    rw,
+    flipAxes,
     corners,
     corners4,
     projectRect,
@@ -35,6 +40,7 @@
 
 -- $setup
 --
+-- >>> :m -Prelude
 -- >>> :set -XRebindableSyntax
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
@@ -170,12 +176,47 @@
 
   gridSpace (Ranges rX rY) (Point stepX stepY) =
     [ Rect x (x + sx) y (y + sy)
-      | x <- grid LowerPos rX stepX,
-        y <- grid LowerPos rY stepY
+    | x <- grid LowerPos rX stepX,
+      y <- grid LowerPos rY stepY
     ]
     where
       sx = width rX / fromIntegral stepX
       sy = width rY / fromIntegral stepY
+
+-- | The first X coordinate of a Rect
+--
+-- >>> rx one
+-- -0.5
+rx :: Rect a -> a
+rx (Rect x _ _ _) = x
+
+-- | The second X coordinate of a Rect
+--
+-- >>> rz one
+-- 0.5
+rz :: Rect a -> a
+rz (Rect _ z _ _) = z
+
+-- | The first Y coordinate of a Rect
+--
+-- >>> ry one
+-- -0.5
+ry :: Rect a -> a
+ry (Rect _ _ y _) = y
+
+-- | The second Y coordinate of a Rect
+--
+-- >>> rw one
+-- 0.5
+rw :: Rect a -> a
+rw (Rect _ _ _ w) = w
+
+-- | flip axes
+--
+-- >>> flipAxes (Rect 1 2 3 4)
+-- Rect 3 4 1 2
+flipAxes :: Rect a -> Rect a
+flipAxes (Rect x z y w) = Rect y w x z
 
 -- | create a list of points representing the lower left and upper right corners of a rectangle.
 --
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
@@ -29,6 +29,7 @@
 
 -- $setup
 --
+-- >>> :m -Prelude
 -- >>> :set -XRebindableSyntax
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
@@ -322,26 +323,6 @@
             . (\x -> addGrain grain x first')
             <$> [0 ..]
       _notMid -> posns $ (\x -> addGrain grain x first') <$> [0 ..]
-
--- come up with a sensible step for a grid over a Field
-stepSensible ::
-  Pos ->
-  Double ->
-  Int ->
-  Double
-stepSensible tp span' n =
-  step
-    + if tp == MidPos
-      then step / 2
-      else 0
-  where
-    step' = 10 ^^ floor (logBase 10 (span' / fromIntegral n))
-    err = fromIntegral n / span' * step'
-    step
-      | err <= 0.15 = 10 * step'
-      | err <= 0.35 = 5 * step'
-      | err <= 0.75 = 2 * step'
-      | otherwise = step'
 
 -- come up with a sensible step for a grid over a Field, where sensible means the 18th century
 -- practice of using multiples of 3 to round
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
@@ -44,6 +44,7 @@
 import Prelude qualified as P
 
 -- $setup
+-- >>> :m -Prelude
 -- >>> :set -XRebindableSyntax
 -- >>> import NumHask.Prelude
 -- >>> import NumHask.Space
diff --git a/test/doctests.hs b/test/doctests.hs
new file mode 100644
--- /dev/null
+++ b/test/doctests.hs
@@ -0,0 +1,8 @@
+module Main where
+
+import System.Environment (getArgs)
+import Test.DocTest (mainFromCabal)
+import Prelude (IO, (=<<))
+
+main :: IO ()
+main = mainFromCabal "numhask-space" =<< getArgs
