diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2014 Omari Norman.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+    * Neither the name of Omari Norman nor the names of contributors
+    to this software may be used to endorse or promote products
+    derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/barecheck.cabal b/barecheck.cabal
new file mode 100644
--- /dev/null
+++ b/barecheck.cabal
@@ -0,0 +1,85 @@
+-- This Cabal file generated using the Cartel library.
+-- Cartel is available at:
+-- http://www.github.com/massysett/cartel
+--
+-- Script name used to generate: genCabal.hs
+-- Generated on: 2014-08-04 09:08:04.876727 EDT
+-- Cartel library version: 0.10.0.2
+name: barecheck
+version: 0.2.0.0
+cabal-version: >= 1.14
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+copyright: Copyright 2014 Omari Norman
+author: Omari Norman, omari@smileystation.com
+maintainer: Omari Norman, omari@smileystation.com
+stability: Experimental
+homepage: http://github.com/massysett/barecheck
+bug-reports: http://github.com/massysett/barecheck/issues
+synopsis: QuickCheck implementations for common types
+description:
+  Provides QuickCheck implementations for common types distributed
+  with GHC and in the Haskell Platform.  The implementations
+  are NOT provided through the QuickCheck Arbitrary and
+  CoArbitrary typeclasses; instead, they are provided through
+  ordinary, non-overloaded functions.  This avoids problems
+  with orphan instances.
+  .
+  Implementations are provided through child modules of the
+  module that provides the original type.  For example, for
+  "Data.Map", look under "Data.Map.Generators",
+  "Data.Map.Shrinkers", and "Data.Map.Coarbitrary".
+  For instance, a function that generates a Map is at
+  'Data.Map.Generators.map', while a function providing
+  a coarbitrary implementation is at 'Data.Map.Coarbitrary.map'.
+  Obviously this can lead to name conflicts, both between
+  modules provided in this package and with other standard
+  modules, so keep this in mind when you do your imports.
+category: Testing
+tested-with: GHC == 7.4.1, GHC == 7.6.3, GHC == 7.8.3
+extra-source-files:
+    minimum-versions.txt
+  , current-versions.txt
+  , genCabal.hs
+  , sunlight-test.hs
+
+source-repository head
+  type: git
+  location: http://github.com/massysett/barecheck.git
+
+Library
+  exposed-modules:
+      Barecheck.Util
+    , Data.Map.Coarbitrary
+    , Data.Map.Generators
+    , Data.Map.Shrinkers
+    , Data.Monoid.Coarbitrary
+    , Data.Monoid.Generators
+    , Data.Monoid.Shrinkers
+    , Data.Sequence.Coarbitrary
+    , Data.Sequence.Generators
+    , Data.Sequence.Shrinkers
+    , Data.Text.Coarbitrary
+    , Data.Text.Generators
+    , Data.Text.Shrinkers
+    , Data.Time.Coarbitrary
+    , Data.Time.Generators
+    , Data.Time.Shrinkers
+    , Data.Tree.Coarbitrary
+    , Data.Tree.Generators
+    , Data.Tree.Shrinkers
+    , Prelude.Coarbitrary
+    , Prelude.Generators
+    , Prelude.Shrinkers
+  build-depends:
+      QuickCheck ((> 2.7 || == 2.7) && < 2.8)
+    , base ((> 4.5.0.0 || == 4.5.0.0) && < 4.8.0.0)
+    , text ((> 0.11.0.0 || == 0.11.0.0) && < 1.2)
+    , containers ((> 0.4.2.1 || == 0.4.2.1) && < 0.6)
+    , time ((> 1.4 || == 1.4) && < 1.5)
+  hs-source-dirs:
+      lib
+  ghc-options:
+      -Wall
+  default-language: Haskell2010
diff --git a/current-versions.txt b/current-versions.txt
new file mode 100644
--- /dev/null
+++ b/current-versions.txt
diff --git a/genCabal.hs b/genCabal.hs
new file mode 100644
--- /dev/null
+++ b/genCabal.hs
@@ -0,0 +1,115 @@
+-- Generates the Cabal file using Cartel.
+-- Written for Cartel version 0.10.0.2
+-- Cartel is available at
+-- http://github.com/massysett/cartel
+
+module Main where
+
+import qualified Cartel as A
+
+versionInts :: [Int]
+versionInts = [0,2,0,0]
+
+version :: A.Version
+version = A.Version versionInts
+
+properties :: A.Properties
+properties = A.empty
+  { A.prName = "barecheck"
+  , A.prVersion = version
+  , A.prCabalVersion = (1,14)
+  , A.prBuildType = A.Simple
+  , A.prLicense = A.BSD3
+  , A.prLicenseFile = "LICENSE"
+  , A.prCopyright = "Copyright 2014 Omari Norman"
+  , A.prAuthor = "Omari Norman, omari@smileystation.com"
+  , A.prMaintainer = "Omari Norman, omari@smileystation.com"
+  , A.prStability = "Experimental"
+  , A.prHomepage = "http://github.com/massysett/barecheck"
+  , A.prBugReports = "http://github.com/massysett/barecheck/issues"
+  , A.prSynopsis = "QuickCheck implementations for common types"
+  , A.prDescription =
+    [ "Provides QuickCheck implementations for common types distributed"
+    , "with GHC and in the Haskell Platform.  The implementations"
+    , "are NOT provided through the QuickCheck Arbitrary and"
+    , "CoArbitrary typeclasses; instead, they are provided through"
+    , "ordinary, non-overloaded functions.  This avoids problems"
+    , "with orphan instances."
+    , ""
+    , "Implementations are provided through child modules of the"
+    , "module that provides the original type.  For example, for"
+    , "\"Data.Map\", look under \"Data.Map.Generators\","
+    , "\"Data.Map.Shrinkers\", and \"Data.Map.Coarbitrary\"."
+    , "For instance, a function that generates a Map is at"
+    , "\'Data.Map.Generators.map', while a function providing"
+    , "a coarbitrary implementation is at \'Data.Map.Coarbitrary.map\'."
+    , "Obviously this can lead to name conflicts, both between"
+    , "modules provided in this package and with other standard"
+    , "modules, so keep this in mind when you do your imports."
+    ]
+  , A.prCategory = "Testing"
+  , A.prTestedWith =
+    let ghc ints = (A.GHC, A.eq ints)
+    in map ghc [[7,4,1], [7,6,3], [7,8,3]]
+  , A.prExtraSourceFiles =
+    [ "minimum-versions.txt"
+    , "current-versions.txt"
+    , "genCabal.hs"
+    , "sunlight-test.hs"
+    ]
+  }
+
+repo :: A.Repository
+repo = A.empty
+  { A.repoVcs = A.Git
+  , A.repoKind = A.Head
+  , A.repoLocation = "http://github.com/massysett/barecheck.git"
+  }
+
+quickcheck :: A.Package
+quickcheck = A.nextBreaking "QuickCheck" [2,7]
+
+base :: A.Package
+base = A.closedOpen "base" [4,5,0,0] [4,8,0,0]
+
+text :: A.Package
+text = A.closedOpen "text" [0,11,0,0] [1,2]
+
+containers :: A.Package
+containers = A.closedOpen "containers" [0,4,2,1] [0,6]
+
+time :: A.Package
+time = A.closedOpen "time" [1,4] [1,5]
+
+library
+  :: [String]
+  -- ^ Library modules
+  -> A.Library
+library ms = A.Library
+  [ A.LibExposedModules ms
+  , A.buildDepends
+    [ quickcheck
+    , base
+    , text
+    , containers
+    , time
+    ]
+  , A.hsSourceDirs [ "lib" ]
+  , A.ghcOptions [ "-Wall" ]
+  , A.defaultLanguage A.Haskell2010
+  ]
+
+cabal
+  :: [String]
+  -- ^ Library modules
+  -> A.Cabal
+cabal ms = A.empty
+  { A.cProperties = properties
+  , A.cRepositories = [repo]
+  , A.cLibrary = Just $ library ms
+  }
+
+main :: IO ()
+main = do
+  ms <- A.modules "lib"
+  A.render "genCabal.hs" $ cabal ms
diff --git a/lib/Barecheck/Util.hs b/lib/Barecheck/Util.hs
new file mode 100644
--- /dev/null
+++ b/lib/Barecheck/Util.hs
@@ -0,0 +1,8 @@
+module Barecheck.Util where
+
+import Test.QuickCheck
+
+-- | 'variant' monomorphised to 'Int'; eliminates type defaulting
+-- compiler warnings.
+varInt :: Int -> Gen b -> Gen b
+varInt = variant
diff --git a/lib/Data/Map/Coarbitrary.hs b/lib/Data/Map/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Map/Coarbitrary.hs
@@ -0,0 +1,17 @@
+module Data.Map.Coarbitrary where
+
+import Prelude hiding (map)
+import qualified Data.Map as M
+import Test.QuickCheck
+
+map
+  :: Ord k
+  => ((k, a) -> Gen r -> Gen r)
+  -> M.Map k a
+  -> Gen r
+  -> Gen r
+map f m = go $ M.toList m
+  where
+    go ls = case ls of
+      [] -> variant (0 :: Int)
+      x:xs -> variant (1 :: Int) . f x . go xs
diff --git a/lib/Data/Map/Generators.hs b/lib/Data/Map/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Map/Generators.hs
@@ -0,0 +1,8 @@
+module Data.Map.Generators where
+
+import Prelude hiding (map)
+import Test.QuickCheck
+import qualified Data.Map as M
+
+map :: Ord k => Gen [(k, a)] -> Gen (M.Map k a)
+map = fmap M.fromList
diff --git a/lib/Data/Map/Shrinkers.hs b/lib/Data/Map/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Map/Shrinkers.hs
@@ -0,0 +1,8 @@
+module Data.Map.Shrinkers where
+
+import Prelude hiding (map)
+import Test.QuickCheck
+import qualified Data.Map as M
+
+map :: Ord k => ((k, a) -> [(k, a)]) -> M.Map k a -> [M.Map k a]
+map s = fmap M.fromList . shrinkList s . M.toList
diff --git a/lib/Data/Monoid/Coarbitrary.hs b/lib/Data/Monoid/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Monoid/Coarbitrary.hs
@@ -0,0 +1,14 @@
+module Data.Monoid.Coarbitrary where
+
+import Test.QuickCheck
+import qualified Data.Monoid as O
+
+last :: (a -> Gen b -> Gen b) -> O.Last a -> Gen b -> Gen b
+last f (O.Last m) = case m of
+  Nothing -> variant (0 :: Int)
+  Just a -> variant (1 :: Int) . f a
+
+first :: (a -> Gen b -> Gen b) -> O.First a -> Gen b -> Gen b
+first f (O.First m) = case m of
+  Nothing -> variant (0 :: Int)
+  Just a -> variant (1 :: Int) . f a
diff --git a/lib/Data/Monoid/Generators.hs b/lib/Data/Monoid/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Monoid/Generators.hs
@@ -0,0 +1,12 @@
+module Data.Monoid.Generators where
+
+import qualified Data.Monoid as O
+import Test.QuickCheck
+
+last :: Gen a -> Gen (O.Last a)
+last g = fmap O.Last $ frequency
+  [ (3, fmap Just g), (1, return Nothing) ]
+
+first :: Gen a -> Gen (O.First a)
+first g = fmap O.First $ frequency
+  [ (3, fmap Just g), (1, return Nothing) ]
diff --git a/lib/Data/Monoid/Shrinkers.hs b/lib/Data/Monoid/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Monoid/Shrinkers.hs
@@ -0,0 +1,13 @@
+module Data.Monoid.Shrinkers where
+
+import qualified Data.Monoid as O
+
+last :: (a -> [a]) -> O.Last a -> [O.Last a]
+last f (O.Last l) = case l of
+  Nothing -> []
+  Just a -> map O.Last $ Nothing : [Just x | x <- f a]
+
+first :: (a -> [a]) -> O.First a -> [O.First a]
+first f (O.First l) = case l of
+  Nothing -> []
+  Just a -> map O.First $ Nothing : [Just x | x <- f a]
diff --git a/lib/Data/Sequence/Coarbitrary.hs b/lib/Data/Sequence/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Sequence/Coarbitrary.hs
@@ -0,0 +1,10 @@
+module Data.Sequence.Coarbitrary where
+
+import Data.Sequence
+import Test.QuickCheck
+import Prelude hiding (seq)
+
+seq :: (a -> Gen b -> Gen b) -> Seq a -> Gen b -> Gen b
+seq f s = case viewl s of
+  EmptyL -> variant (0 :: Int)
+  a :< rest -> variant (1 :: Int) . f a . seq f rest
diff --git a/lib/Data/Sequence/Generators.hs b/lib/Data/Sequence/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Sequence/Generators.hs
@@ -0,0 +1,8 @@
+module Data.Sequence.Generators where
+
+import Data.Sequence
+import Test.QuickCheck
+import Prelude hiding (seq)
+
+seq :: Gen a -> Gen (Seq a)
+seq = fmap fromList . listOf
diff --git a/lib/Data/Sequence/Shrinkers.hs b/lib/Data/Sequence/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Sequence/Shrinkers.hs
@@ -0,0 +1,9 @@
+module Data.Sequence.Shrinkers where
+
+import Test.QuickCheck
+import Data.Sequence
+import Prelude hiding (seq)
+import Data.Foldable
+
+seq :: (a -> [a]) -> Seq a -> [Seq a]
+seq f = map fromList . shrinkList f . toList
diff --git a/lib/Data/Text/Coarbitrary.hs b/lib/Data/Text/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Text/Coarbitrary.hs
@@ -0,0 +1,10 @@
+module Data.Text.Coarbitrary where
+
+import Test.QuickCheck
+import Data.Text (Text)
+import qualified Data.Text as X
+
+text :: Text -> Gen b -> Gen b
+text t = case X.uncons t of
+  Nothing -> variant (0 :: Int)
+  Just (x, xs) -> variant (1 :: Int) . coarbitrary x . text xs
diff --git a/lib/Data/Text/Generators.hs b/lib/Data/Text/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Text/Generators.hs
@@ -0,0 +1,9 @@
+module Data.Text.Generators where
+
+import Test.QuickCheck
+import qualified Data.Text as X
+import Data.Text (Text)
+
+text :: Gen Char -> Gen Text
+text = fmap X.pack . listOf
+
diff --git a/lib/Data/Text/Shrinkers.hs b/lib/Data/Text/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Text/Shrinkers.hs
@@ -0,0 +1,8 @@
+module Data.Text.Shrinkers where
+
+import Data.Text (Text)
+import qualified Data.Text as X
+import Test.QuickCheck
+
+text :: (Char -> [Char]) -> Text -> [Text]
+text f = map X.pack . shrinkList f . X.unpack
diff --git a/lib/Data/Time/Coarbitrary.hs b/lib/Data/Time/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Time/Coarbitrary.hs
@@ -0,0 +1,13 @@
+module Data.Time.Coarbitrary where
+
+import Data.Time
+import Test.QuickCheck
+
+day :: Day -> Gen b -> Gen b
+day (ModifiedJulianDay i) = variant i
+
+diffTime :: DiffTime -> Gen b -> Gen b
+diffTime d = coarbitrary (toRational d)
+
+uTCTime :: UTCTime -> Gen b -> Gen b
+uTCTime (UTCTime d t) = day d . diffTime t
diff --git a/lib/Data/Time/Generators.hs b/lib/Data/Time/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Time/Generators.hs
@@ -0,0 +1,14 @@
+module Data.Time.Generators where
+
+import Test.QuickCheck
+import Data.Time
+import Control.Monad
+
+day :: Gen Day
+day = fmap ModifiedJulianDay arbitrarySizedIntegral
+
+diffTime :: Gen DiffTime
+diffTime = fmap (picosecondsToDiffTime . abs) arbitrary
+
+uTCTime :: Gen UTCTime
+uTCTime = liftM2 UTCTime day diffTime
diff --git a/lib/Data/Time/Shrinkers.hs b/lib/Data/Time/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Time/Shrinkers.hs
@@ -0,0 +1,15 @@
+module Data.Time.Shrinkers where
+
+import Data.Time
+import Test.QuickCheck
+import Prelude.Shrinkers
+
+day :: Day -> [Day]
+day = fmap ModifiedJulianDay . shrinkIntegral . toModifiedJulianDay
+
+diffTime :: DiffTime -> [DiffTime]
+diffTime _ = []
+
+uTCTime :: UTCTime -> [UTCTime]
+uTCTime (UTCTime a t) =
+  [ UTCTime a' t' | (a', t') <- tuple2 day diffTime (a, t) ]
diff --git a/lib/Data/Tree/Coarbitrary.hs b/lib/Data/Tree/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Tree/Coarbitrary.hs
@@ -0,0 +1,12 @@
+module Data.Tree.Coarbitrary where
+
+import Data.Tree
+import Test.QuickCheck
+import Prelude.Coarbitrary
+
+tree
+  :: (a -> Gen b -> Gen b)
+  -> Tree a
+  -> Gen b
+  -> Gen b
+tree f (Node a as) = f a . list (tree f) as
diff --git a/lib/Data/Tree/Generators.hs b/lib/Data/Tree/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Tree/Generators.hs
@@ -0,0 +1,20 @@
+module Data.Tree.Generators where
+
+import Data.Tree
+import Test.QuickCheck
+import Control.Monad
+
+tree
+  :: (Int -> Int)
+  -- ^ This function is applied to the size parameter.  It determines
+  -- the length of the list in child forests, to prevent this function
+  -- from generating trees that are infinitely large.  Here, supply a
+  -- function that reduces the size parameter by some amount; using
+  -- @(\`div\` 2)@ is typical, though if you want to restrict the size
+  -- of trees produced even more you might try something like
+  -- @(\`div\` 5)@.
+  -> Gen a
+  -- ^ Generates a root label.
+  -> Gen (Tree a)
+tree f g = liftM2 Node g (sized $ \s -> resize (f s) (listOf (tree f g)))
+
diff --git a/lib/Data/Tree/Shrinkers.hs b/lib/Data/Tree/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Data/Tree/Shrinkers.hs
@@ -0,0 +1,12 @@
+module Data.Tree.Shrinkers where
+
+import Data.Tree
+import Prelude.Shrinkers
+import Test.QuickCheck
+
+tree
+  :: (a -> [a])
+  -> Tree a
+  -> [Tree a]
+tree f (Node a as) = as ++
+  [ Node n cs | (n, cs) <- tuple2 f (shrinkList (tree f)) (a, as) ]
diff --git a/lib/Prelude/Coarbitrary.hs b/lib/Prelude/Coarbitrary.hs
new file mode 100644
--- /dev/null
+++ b/lib/Prelude/Coarbitrary.hs
@@ -0,0 +1,68 @@
+module Prelude.Coarbitrary where
+
+import Test.QuickCheck
+import Prelude hiding (maybe, either)
+import Barecheck.Util
+
+maybe :: (a -> Gen b -> Gen b) -> Maybe a -> Gen b -> Gen b
+maybe f m = case m of
+  Nothing -> varInt 0
+  Just x -> varInt 1 . f x
+
+either
+  :: (a -> Gen c -> Gen c)
+  -> (b -> Gen c -> Gen c)
+  -> Either a b
+  -> Gen c
+  -> Gen c
+either fa fb ei = case ei of
+  Left a -> varInt 0 . fa a
+  Right b -> varInt 1 . fb b
+
+list
+  :: (a -> Gen b -> Gen b)
+  -> [a]
+  -> Gen b
+  -> Gen b
+list f xs = case xs of
+  [] -> varInt 0
+  a:as -> varInt 1 . f a . list f as
+
+tuple2
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (a, b)
+  -> Gen r
+  -> Gen r
+tuple2 fa fb (a, b) = fa a . fb b
+
+tuple3
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (c -> Gen r -> Gen r)
+  -> (a, b, c)
+  -> Gen r
+  -> Gen r
+tuple3 fa fb fc (a, b, c) = fa a . fb b . fc c
+
+tuple4
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (c -> Gen r -> Gen r)
+  -> (d -> Gen r -> Gen r)
+  -> (a, b, c, d)
+  -> Gen r
+  -> Gen r
+tuple4 fa fb fc fd (a, b, c, d) = fa a . fb b . fc c . fd d
+
+tuple5
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (c -> Gen r -> Gen r)
+  -> (d -> Gen r -> Gen r)
+  -> (e -> Gen r -> Gen r)
+  -> (a, b, c, d, e)
+  -> Gen r
+  -> Gen r
+tuple5 fa fb fc fd fe (a, b, c, d, e) = fa a . fb b . fc c . fd d . fe e
+
diff --git a/lib/Prelude/Generators.hs b/lib/Prelude/Generators.hs
new file mode 100644
--- /dev/null
+++ b/lib/Prelude/Generators.hs
@@ -0,0 +1,99 @@
+-- | Generators for "Prelude" types.
+--
+-- This module also contains function generators, like 'function1' and
+-- 'function2'.  These generate random functions.  To use these, get a
+-- coarbitrary function from one of the modules whose name ends in
+-- @Coarbitrary@ or by using the QuickCheck 'coarbitrary' function,
+-- along with using a generator for the function's result type.  For
+-- example:
+--
+-- @
+--    module MyModule where
+--
+--    import Test.QuickCheck
+--    import qualified Prelude.Generators as G
+--    import qualified Data.Text.Coarbitrary as C
+--    import qualified Data.Text.Generators as G
+--
+--    genTextToMaybeText :: Gen (Text -> Maybe Text)
+--    genTextToMaybeText = function1 C.text (G.maybe (G.text arbitrary))
+-- @
+
+
+module Prelude.Generators where
+
+import Test.QuickCheck
+import Prelude hiding (maybe, either)
+import Test.QuickCheck.Gen.Unsafe
+import Control.Monad
+
+maybe :: Gen a -> Gen (Maybe a)
+maybe g = frequency [(3, fmap Just g), (1, return Nothing)]
+
+either :: Gen a -> Gen b -> Gen (Either a b)
+either a b = oneof [ fmap Left a, fmap Right b ]
+
+function1
+  :: (a -> Gen b -> Gen b)
+  -> Gen b
+  -> Gen (a -> b)
+function1 perturb gen = promote (`perturb` gen)
+
+function2
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> Gen r
+  -> Gen (a -> b -> r)
+function2 p1 p2 = fmap f . function1 p'
+  where
+    p' (a, b) = p1 a . p2 b
+    f g = \a b -> g (a, b)
+
+function3
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (c -> Gen r -> Gen r)
+  -> Gen r
+  -> Gen (a -> b -> c -> r)
+function3 p1 p2 p3 = fmap f . function1 p'
+  where
+    p' (a, b, c) = p1 a . p2 b . p3 c
+    f g = \a b c -> g (a, b, c)
+
+function4
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (c -> Gen r -> Gen r)
+  -> (d -> Gen r -> Gen r)
+  -> Gen r
+  -> Gen (a -> b -> c -> d -> r)
+function4 p1 p2 p3 p4 = fmap f . function1 p'
+  where
+    p' (a, b, c, d) = p1 a . p2 b . p3 c . p4 d
+    f g = \a b c d -> g (a, b, c, d)
+
+function5
+  :: (a -> Gen r -> Gen r)
+  -> (b -> Gen r -> Gen r)
+  -> (c -> Gen r -> Gen r)
+  -> (d -> Gen r -> Gen r)
+  -> (e -> Gen r -> Gen r)
+  -> Gen r
+  -> Gen (a -> b -> c -> d -> e -> r)
+function5 p1 p2 p3 p4 p5 = fmap f . function1 p'
+  where
+    p' (a, b, c, d, e) = p1 a . p2 b . p3 c . p4 d . p5 e
+    f g = \a b c d e -> g (a, b, c, d, e)
+
+
+tuple2 :: Gen a -> Gen b -> Gen (a, b)
+tuple2 a b = liftM2 (,) a b
+
+tuple3 :: Gen a -> Gen b -> Gen c -> Gen (a, b, c)
+tuple3 a b c = liftM3 (,,) a b c
+
+tuple4 :: Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d)
+tuple4 a b c d = liftM4 (,,,) a b c d
+
+tuple5 :: Gen a -> Gen b -> Gen c -> Gen d -> Gen e -> Gen (a, b, c, d, e)
+tuple5 a b c d e = liftM5 (,,,,) a b c d e
diff --git a/lib/Prelude/Shrinkers.hs b/lib/Prelude/Shrinkers.hs
new file mode 100644
--- /dev/null
+++ b/lib/Prelude/Shrinkers.hs
@@ -0,0 +1,54 @@
+module Prelude.Shrinkers where
+
+import Prelude hiding (maybe, either)
+
+maybe :: (a -> [a]) -> Maybe a -> [Maybe a]
+maybe f m = case m of
+  Nothing -> []
+  Just x -> Nothing : map Just (f x)
+
+either :: (a -> [a]) -> (b -> [b]) -> Either a b -> [Either a b]
+either fa fb ei = case ei of
+  Left a -> map Left (fa a)
+  Right b -> map Right (fb b)
+
+tuple2 :: (a -> [a]) -> (b -> [b]) -> (a, b) -> [(a, b)]
+tuple2 fa fb (a, b) =
+     [ (a', b) | a' <- fa a ]
+  ++ [ (a, b') | b' <- fb b ]
+
+tuple3
+  :: (a -> [a])
+  -> (b -> [b])
+  -> (c -> [c])
+  -> (a, b, c)
+  -> [(a, b, c)]
+tuple3 fa fb fc (a, b, c) =
+  [ (a', b', c') | (a', (b', c'))
+    <- tuple2 fa (tuple2 fb fc) (a, (b, c)) ]
+
+tuple4
+  :: (a -> [a])
+  -> (b -> [b])
+  -> (c -> [c])
+  -> (d -> [d])
+  -> (a, b, c, d)
+  -> [(a, b, c, d)]
+tuple4 fa fb fc fd (a, b, c, d) =
+  [ (a', b', c', d') | (a', (b', (c', d')))
+    <- tuple2 fa (tuple2 fb (tuple2 fc fd)) (a, (b, (c, d))) ]
+
+tuple5
+  :: (a -> [a])
+  -> (b -> [b])
+  -> (c -> [c])
+  -> (d -> [d])
+  -> (e -> [e])
+  -> (a, b, c, d, e)
+  -> [(a, b, c, d, e)]
+tuple5 fa fb fc fd fe (a, b, c, d, e) =
+  [ (a', b', c', d', e') | (a', (b', (c', (d', e'))))
+    <- tuple2 fa (tuple2 fb (tuple2 fc (tuple2 fd fe)))
+                  (a, (b, (c, (d, e)))) ]
+
+
diff --git a/minimum-versions.txt b/minimum-versions.txt
new file mode 100644
--- /dev/null
+++ b/minimum-versions.txt
diff --git a/sunlight-test.hs b/sunlight-test.hs
new file mode 100644
--- /dev/null
+++ b/sunlight-test.hs
