diff --git a/genvalidity.cabal b/genvalidity.cabal
--- a/genvalidity.cabal
+++ b/genvalidity.cabal
@@ -1,5 +1,5 @@
 name:                genvalidity
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Testing utilities for the validity library
 description:         Please see README.md
 homepage:            https://github.com/NorfairKing/validity#readme
@@ -16,10 +16,34 @@
 library
   hs-source-dirs:      src
   exposed-modules:     Data.GenValidity
+                     , Data.GenRelativeValidity
   build-depends:       base               < 5
-                     , validity           >= 0.1 && < 0.2
+                     , validity           >= 0.2 && < 0.3
                      , QuickCheck         >= 2.8 && < 2.9
   default-language:    Haskell2010
+
+test-suite genvalidity-test
+  type:
+    exitcode-stdio-1.0
+  default-language:
+    Haskell2010
+  hs-source-dirs:
+    test
+  main-is:
+    Spec.hs
+  other-modules:
+    Data.GenValiditySpec
+  ghc-options:
+    -threaded -rtsopts -with-rtsopts=-N
+    -Wall
+    -fno-warn-name-shadowing
+  build-depends:
+      base
+
+    , hspec
+    , QuickCheck     >= 2.8 && < 2.9
+
+    , genvalidity
 
 source-repository head
   type:     git
diff --git a/src/Data/GenRelativeValidity.hs b/src/Data/GenRelativeValidity.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/GenRelativeValidity.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Data.GenRelativeValidity
+    ( module Data.RelativeValidity
+    , module Data.GenRelativeValidity
+    ) where
+
+import           Data.RelativeValidity
+import           Data.GenValidity
+
+import           Test.QuickCheck
+
+class (GenValidity a, RelativeValidity a b) => GenRelativeValidity a b where
+    genUncheckedFor :: b -> Gen a
+    genUncheckedFor _ = genUnchecked
+
+    genValidFor :: b -> Gen a
+    genValidFor b = genValid `suchThat` (`isValidFor` b)
+
+    genInvalidFor :: b -> Gen a
+    genInvalidFor b = genUncheckedFor b `suchThat` (not . (`isValidFor` b))
diff --git a/src/Data/GenValidity.hs b/src/Data/GenValidity.hs
--- a/src/Data/GenValidity.hs
+++ b/src/Data/GenValidity.hs
@@ -5,8 +5,9 @@
 
  Let's use the example from @Data.Validity@ again: A datatype that represents
  primes.
- To implement tests for this datatype, we would have to be able primes and
- non-primes. We could do this with @(Prime <$> arbitrary) `suchThat` isValid@
+ To implement tests for this datatype, we would have to be able to generate
+ both primes and non-primes. We could do this with
+ @(Prime <$> arbitrary) `suchThat` isValid@
  but this is tedious and inefficient.
 
  The @GenValidity@ type class allows you to specify how to (efficiently)
@@ -104,33 +105,43 @@
     genValid     = genListOf genValid
 
     -- | At least one invalid value in the list, the rest could be either.
-    genInvalid   = sized $ \n ->
-        case n of
-            0 -> (:[]) <$> genInvalid
-            1 -> (:[]) <$> genInvalid
-            _ -> do
-                (x, y) <- genSplit $ n - 1
-                before <- resize x $ genListOf genUnchecked
-                middle <- genInvalid
-                after  <- resize y $ genListOf genUnchecked
-                return $ before ++ [middle] ++ after
-      where
-        genSplit :: Int -> Gen (Int, Int)
-        genSplit n = elements $ [ (i, n - i) | i <- [0..n] ]
+    genInvalid   = sized $ \n -> do
+        (x, y, z) <- genSplit3 n
+        before <- resize x $ genListOf genUnchecked
+        middle <- resize y genInvalid
+        after  <- resize z $ genListOf genUnchecked
+        return $ before ++ [middle] ++ after
 
+upTo :: Int -> Gen Int
+upTo n
+    | n <= 0 = pure 0
+    | otherwise = elements [0 .. n]
+
+genSplit :: Int -> Gen (Int, Int)
+genSplit n
+    | n < 0     = pure (0, 0)
+    | otherwise = elements $ [ (i, n - i) | i <- [0..n] ]
+
+genSplit3 :: Int -> Gen (Int, Int, Int)
+genSplit3 n
+    | n < 0     = pure (0, 0, 0)
+    | otherwise = do
+    (a, z) <- genSplit n
+    (b, c) <- genSplit z
+    return (a, b, c)
+
+arbPartition :: Int -> Gen [Int]
+arbPartition k
+    | k <= 0 = pure []
+    | otherwise = do
+    first <- elements [1..k]
+    rest <- arbPartition $ k - first
+    return $ first : rest
+
 -- | A version of @listOf@ that takes size into account more accurately.
 genListOf :: Gen a -> Gen [a]
-genListOf func = sized $ \n ->
-    case n of
-        0 -> pure []
-        m -> do
-            pars <- arbPartition m
-            forM pars $ \i -> resize i func
-  where
-    arbPartition :: Int -> Gen [Int]
-    arbPartition 0 = pure []
-    arbPartition 1 = pure [1]
-    arbPartition k = do
-        first <- elements [1..k]
-        rest <- arbPartition $ k - first
-        return $ first : rest
+genListOf func = sized $ \n -> do
+    size <- upTo n
+    pars <- arbPartition size
+    forM pars $ \i -> resize i func
+
diff --git a/test/Data/GenValiditySpec.hs b/test/Data/GenValiditySpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/GenValiditySpec.hs
@@ -0,0 +1,43 @@
+module Data.GenValiditySpec (spec) where
+
+import           Test.Hspec
+import           Test.QuickCheck
+
+import           Data.GenValidity
+
+spec :: Spec
+spec = do
+    describe "upTo" $ do
+        it "returns only positive integers" $ do
+            forAll arbitrary $ \n ->
+                forAll (upTo n) (`shouldSatisfy` (>= 0))
+
+    describe "genSplit" $ do
+        it "returns positive integers" $ do
+            forAll arbitrary $ \i ->
+                forAll (genSplit i) $ \(a, b) -> do
+                    a `shouldSatisfy` (>= 0)
+                    b `shouldSatisfy` (>= 0)
+
+        it "returns two integers such that the sum is the original integer" $ do
+            forAll (arbitrary `suchThat` (>= 0)) $ \i ->
+                forAll (genSplit i) $ \(a, b) ->
+                    a + b `shouldBe` i
+
+    describe "arbPartition" $ do
+        it "returns an empty list upon strictly negative input" $ do
+            forAll (arbitrary `suchThat` (< 0)) $ \n ->
+                forAll (arbPartition n) (`shouldBe` [])
+
+        it "returns a list of strictly positive integers" $ do
+            forAll arbitrary $ \n ->
+                forAll (arbPartition n) $ \p ->
+                    p `shouldSatisfy` all (> 0)
+
+        it "returns a list of integers that sum to the original positive integer" $ do
+            forAll (arbitrary `suchThat` (>= 0)) $ \n ->
+                forAll (arbPartition n) $ \p ->
+                    sum p `shouldBe` n
+
+
+
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
