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.7.1.0
+version: 0.8.0.0
 synopsis:
   Numerical spaces.
 description:
@@ -8,7 +8,6 @@
     .
     == Usage
     .
-    >>> {-# LANGUAGE NegativeLiterals #-}
     >>> {-# LANGUAGE RebindableSyntax #-}
     >>> import NumHask.Prelude
     >>> import NumHask.Space
@@ -32,7 +31,7 @@
   LICENSE
 build-type:
   Simple
-tested-with: GHC ==8.8.4 || ==8.10.2
+tested-with: GHC ==8.8.4 || ==8.10.2 || ==9.0.1
 extra-source-files:
   readme.md
   ChangeLog.md
@@ -59,7 +58,7 @@
     base >=4.7 && <5,
     containers >= 0.6 && < 0.7,
     distributive >=0.2.2 && <1,
-    numhask >= 0.7 && < 0.8,
+    numhask >= 0.8 && < 0.9,
     random >=1.2 && < 1.3,
     semigroupoids >=5 && <6,
     tdigest >= 0.2.1 && < 0.3,
@@ -85,8 +84,7 @@
     test
   build-depends:
     base >=4.7 && <5,
-    doctest >= 0.16 && < 0.18,
-    numhask >= 0.7 && < 0.8,
+    doctest >= 0.16 && < 0.19
   default-language: Haskell2010
   ghc-options:
     -Wall
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,11 +31,12 @@
 import Data.Distributive
 import Data.Functor.Classes
 import Data.Functor.Rep
-import GHC.Show (show)
-import NumHask.Prelude hiding (Distributive, rotate, show)
+import NumHask.Prelude hiding (Distributive)
 import qualified NumHask.Prelude as P
 import NumHask.Space.Range
 import NumHask.Space.Types
+import System.Random
+import System.Random.Stateful
 
 -- $setup
 -- >>> :set -XNoImplicitPrelude
@@ -168,15 +169,14 @@
   (/\) (Point x y) (Point x' y') = Point (min x x') (min y y')
 
 instance
-  (ExpField a) =>
+  (ExpField a, Eq a) =>
   Norm (Point a) a
   where
   norm (Point x y) = sqrt (x * x + y * y)
-  basis p = p /. norm p
+  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
 --
--- > \u@(Point ux uy) v@(Point vx vy) -> angle v - angle u == sign (ux*vy-uy*vx) * acos (dotP u v / (norm u * norm v))
 instance (TrigField a) => Direction (Point a) a where
   angle (Point x y) = atan2 y x
   ray x = Point (cos x) (sin x)
@@ -248,7 +248,7 @@
   transform t (Line s e) = Line (transform t s) (transform t e)
 
 -- | Return the parameters (a, b, c) for the line equation @a*x + b*y + c = 0@.
-lineSolve :: ExpField a => Line a -> (a, a, a)
+lineSolve :: (ExpField a, Eq a) => Line a -> (a, a, a)
 lineSolve (Line p1 p2) = (- my, mx, c)
   where
     m@(Point mx my) = basis (p2 - p1)
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
@@ -33,11 +33,10 @@
 where
 
 import Data.Distributive as D
-import Data.Foldable (Foldable (foldr1))
 import Data.Functor.Compose
 import Data.Functor.Rep
-import GHC.Show (show)
-import NumHask.Prelude hiding (Distributive, rotate, show)
+import NumHask.Prelude hiding (Distributive)
+import Data.List.NonEmpty
 import NumHask.Space.Point
 import NumHask.Space.Range
 import NumHask.Space.Types
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
@@ -28,11 +28,11 @@
 import Data.Containers.ListUtils (nubOrd)
 import Data.Fixed (Fixed (MkFixed))
 import qualified Data.Sequence as Seq
-import Data.String (String)
 import Data.Time
 import NumHask.Prelude
 import NumHask.Space.Range
 import NumHask.Space.Types
+import Data.Text (Text, unpack, pack)
 
 -- $setup
 --
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
@@ -14,6 +14,7 @@
     Intersection (..),
     FieldSpace (..),
     mid,
+    interpolate,
     project,
     Pos (..),
     space1,
@@ -38,8 +39,9 @@
   )
 where
 
-import NumHask.Prelude hiding (rotate)
+import NumHask.Prelude
 import qualified Prelude as P
+import System.Random
 
 -- | 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'.
 --
@@ -206,6 +208,13 @@
 -- | middle element of the space
 mid :: (Space s, Field (Element s)) => s -> Element s
 mid s = (lower s + upper s) / (one + one)
+
+-- | 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
 
 -- | project an element from one space to another, preserving relative position.
 --
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
@@ -20,6 +20,7 @@
 import NumHask.Space.Point
 import NumHask.Space.Rect
 import NumHask.Space.Types
+import qualified Data.List.NonEmpty as NonEmpty
 
 -- | unification of a point and rect on the plane
 data XY a
@@ -92,4 +93,5 @@
 -- [P -0.5 -0.5,P 0.0 0.0,P 0.5 0.5]
 projectTo :: Rect Double -> [XY Double] -> [XY Double]
 projectTo _ [] = []
-projectTo vb (x : xs) = projectOn vb (toRect $ sconcat (x :| xs)) <$> (x : xs)
+projectTo vb (x : xs) =
+  projectOn vb (toRect $ sconcat (x NonEmpty.:| xs)) <$> (x : xs)
diff --git a/test/test.hs b/test/test.hs
--- a/test/test.hs
+++ b/test/test.hs
@@ -1,11 +1,10 @@
 {-# LANGUAGE RebindableSyntax #-}
-{-# LANGUAGE NegativeLiterals #-}
 {-# OPTIONS_GHC -Wall #-}
 {-# OPTIONS_GHC -Wno-unused-imports #-}
 
 module Main where
 
-import NumHask.Prelude
+import Prelude
 import Test.DocTest
 
 main :: IO ()
