diff --git a/changelog b/changelog
new file mode 100644
--- /dev/null
+++ b/changelog
@@ -0,0 +1,3 @@
+1.1.1
+
+* Make Data.Universe.Helpers.cartesianProduct more generative
diff --git a/src/Data/Universe/Helpers.hs b/src/Data/Universe/Helpers.hs
--- a/src/Data/Universe/Helpers.hs
+++ b/src/Data/Universe/Helpers.hs
@@ -85,11 +85,6 @@
 cartesianProduct :: (a -> b -> c) -> [a] -> [b] -> [c]
 -- special case: don't want to construct an infinite list of empty lists to pass to diagonal
 cartesianProduct _ []   _  = []
-cartesianProduct _ _   []  = []
--- singleton lists:
-cartesianProduct f [x] ys  = fmap (f x) ys
-cartesianProduct f xs  [y] = fmap (`f` y) xs
--- general case:
 cartesianProduct f xs  ys  = diagonal [[f x y | x <- xs] | y <- ys]
 
 -- | @'cartesianProduct' (,)@
@@ -107,7 +102,7 @@
 -- finite index in list i for each i, @[v1, ..., vn]@ has finite index in the
 -- output list.
 choices :: [[a]] -> [[a]]
-choices = foldr ((map (uncurry (:)) .) . (+*+)) [[]]
+choices = foldr (cartesianProduct (:)) [[]]
 
 retagWith :: (a -> b) -> Tagged a x -> Tagged b x
 retagWith _ (Tagged n) = Tagged n
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -1,13 +1,16 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 module Main (main) where
 
+import Control.Exception (evaluate)
 import Data.List (elemIndex)
 import Data.Int (Int8)
 import Test.QuickCheck
 import Data.Universe.Class (Universe(..), Finite(..))
+import Data.Universe.Helpers (interleave, choices)
 import Data.Set (Set)
 import Data.Ratio (Ratio, (%))
 import Numeric.Natural (Natural)
+import System.Timeout (timeout)
 
 import qualified Data.Set as Set
 
@@ -71,6 +74,17 @@
     u = elemIndex (Left True :: Either Bool Bool) universe
     f = elemIndex (Left True :: Either Bool Bool) universeF
 
+choicesLazinessProperty :: IO ()
+choicesLazinessProperty = do
+    v <- timeout oneSecond (evaluate (s !! 1))
+    case v of
+        Just _ -> putStrLn "OK"
+        Nothing -> putStrLn "ERROR: Timeout while evaluating a sneaky, self-referential collection of helpers"
+    where
+    -- generate strings from the grammar S -> x | S S
+    s = interleave [["x"], map concat $ choices [s, s]]
+    oneSecond = 1000000
+
 -------------------------------------------------------------------------------
 -- Main
 -------------------------------------------------------------------------------
@@ -97,6 +111,8 @@
     quickCheck $ finiteLaws (P :: P (Set Bool))
     quickCheck $ finiteLaws (P :: P (Set (Maybe Bool)))
     quickCheck $ finiteLaws (P :: P (Set (Set (Maybe Bool))))
+
+    choicesLazinessProperty
 
 -------------------------------------------------------------------------------
 -- Natural'
diff --git a/universe-base.cabal b/universe-base.cabal
--- a/universe-base.cabal
+++ b/universe-base.cabal
@@ -1,5 +1,5 @@
 name:          universe-base
-version:       1.1
+version:       1.1.1
 synopsis:      A class for finite and recursively enumerable types.
 description:
   A class for finite and recursively enumerable types and some helper functions for enumerating them.
@@ -22,6 +22,7 @@
 category:      Data
 build-type:    Simple
 cabal-version: >=1.10
+extra-source-files: changelog
 tested-with:
   GHC ==8.8.1 || ==8.6.4 || ==8.4.4 || ==8.2.2 || ==8.0.2 || ==7.10.3 || ==7.8.4 || ==7.6.3 || ==7.4.2 || ==7.0.4
 
@@ -73,7 +74,7 @@
       , void  >=0.7.2 && <0.8
 
   if !impl(ghc >=8.0)
-    build-depends: semigroups >=0.18.2 && <0.19
+    build-depends: semigroups >=0.18.2 && <0.20
 
   if impl(ghc >=7.4)
     cpp-options:      -DDEFAULT_SIGNATURES
