diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+0.3.17
+
+* Support GHC-8.4.1
+* Split package into per-package modules
+* Add instances for `ShortByteString`
+* Add Function `ByteString` and `ShortByteString` instances (bytestring >= 0.10.4)
+* Enable PolyKinds for `Tagged` instances (GHC >= 7.6)
+
 0.3.16.1
 
 * Support QuickCheck-2.11
diff --git a/quickcheck-instances.cabal b/quickcheck-instances.cabal
--- a/quickcheck-instances.cabal
+++ b/quickcheck-instances.cabal
@@ -1,5 +1,5 @@
 Name:                quickcheck-instances
-Version:             0.3.16.1
+Version:             0.3.17
 Synopsis:            Common quickcheck instances
 Description:         QuickCheck instances.
                      .
@@ -33,7 +33,6 @@
   GHC==7.10.3,
   GHC==8.0.2,
   GHC==8.2.2,
-  -- GHC-8.4 is in alpha atm
   GHC==8.4.1
 
 Source-repository head
@@ -42,9 +41,25 @@
 
 Library
   Exposed-modules:     Test.QuickCheck.Instances
+                       Test.QuickCheck.Instances.Array
+                       Test.QuickCheck.Instances.ByteString
+                       Test.QuickCheck.Instances.CaseInsensitive
+                       Test.QuickCheck.Instances.Containers
+                       Test.QuickCheck.Instances.Hashable
+                       Test.QuickCheck.Instances.Natural
+                       Test.QuickCheck.Instances.OldTime
+                       Test.QuickCheck.Instances.Scientific
+                       Test.QuickCheck.Instances.Semigroup
+                       Test.QuickCheck.Instances.Tagged
+                       Test.QuickCheck.Instances.Text
+                       Test.QuickCheck.Instances.Time
+                       Test.QuickCheck.Instances.Transformer
+                       Test.QuickCheck.Instances.UUID
+                       Test.QuickCheck.Instances.UnorderedContainers
+                       Test.QuickCheck.Instances.Vector
   Hs-Source-Dirs:      src
   Build-depends:
-    base       >=4.5  && <4.11,
+    base       >=4.5  && <4.12,
     QuickCheck >=2.10 && <2.12,
 
     array                >=0.4.0.0 && <0.6,
@@ -59,7 +74,7 @@
     text                 >=1.0.0.0 && <1.3,
     time                 >=1.4     && <1.9,
     transformers         >=0.3.0.0 && <0.6,
-    transformers-compat  >=0.5     && <0.6,
+    transformers-compat  >=0.5     && <0.7,
     unordered-containers >=0.2.2.0 && <0.3,
     uuid-types           >=1.0.3   && <1.1,
     vector               >=0.9     && <0.13
diff --git a/src/Test/QuickCheck/Instances.hs b/src/Test/QuickCheck/Instances.hs
--- a/src/Test/QuickCheck/Instances.hs
+++ b/src/Test/QuickCheck/Instances.hs
@@ -29,655 +29,20 @@
 -}
 module Test.QuickCheck.Instances () where
 
-import Prelude ()
-import Prelude.Compat
-
-import Control.Applicative (liftA2)
-import Data.Functor.Sum (Sum (..))
-import Data.Hashable (Hashable, Hashed, hashed)
-import Data.Int (Int32)
-import Data.Ix (Ix (..))
-import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
-import Data.Maybe (mapMaybe)
-import Data.Proxy (Proxy (..))
-import Data.Traversable (for)
-import Data.Word (Word32)
-import Numeric.Natural (Natural)
-
-import Test.QuickCheck
-import Test.QuickCheck.Function (functionIntegral)
-
-import qualified Data.Array.IArray as Array
-import qualified Data.Array.Unboxed as Array
-import qualified Data.ByteString as BS
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.CaseInsensitive as CI
-import qualified Data.HashMap.Lazy as HML
-import qualified Data.HashSet as HS
-import qualified Data.Scientific as Scientific
-import qualified Data.Semigroup as Semi
-import qualified Data.Tagged as Tagged (Tagged (..))
-import qualified Data.Text as TS
-import qualified Data.Text.Lazy as TL
-import qualified Data.Time as Time
-import qualified Data.Time.Clock.TAI as Time
-import qualified Data.Tree as Tree
-import qualified Data.UUID.Types as UUID
-import qualified Data.Vector as Vector
-import qualified Data.Vector.Generic as GVector
-import qualified Data.Vector.Storable as SVector
-import qualified Data.Vector.Unboxed as UVector
-import qualified System.Time as OldTime
-
--------------------------------------------------------------------------------
--- array
--------------------------------------------------------------------------------
-
-instance (Num i, Ix i, Arbitrary i) => Arbitrary1 (Array.Array i) where
-    liftArbitrary = liftA2 makeArray arbitrary . liftArbitrary
-    liftShrink = shrinkArray
-
-instance (Num i, Ix i, Arbitrary i, Arbitrary a) => Arbitrary (Array.Array i a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance (Ix i, CoArbitrary i, CoArbitrary a) => CoArbitrary (Array.Array i a) where
-    coarbitrary arr = coarbitrary (Array.bounds arr, Array.elems arr)
-
-
-instance (Num i, Ix i, Array.IArray Array.UArray a, Arbitrary i, Arbitrary a) => Arbitrary (Array.UArray i a) where
-    arbitrary = liftA2 makeArray arbitrary arbitrary
-    shrink = shrinkArray shrink
-
-instance (Ix i, Array.IArray Array.UArray a, CoArbitrary i, CoArbitrary a) => CoArbitrary (Array.UArray i a) where
-    coarbitrary arr = coarbitrary (Array.bounds arr, Array.elems arr)
-
-
-shrinkArray
-    :: (Num i, Ix i, Array.IArray arr a, Arbitrary i)
-    => (a -> [a]) -> arr i a -> [arr i a]
-shrinkArray shr arr =
-  [ makeArray lo xs | xs <- liftShrink shr (Array.elems arr) ] ++
-  [ makeArray lo' (Array.elems arr) | lo' <- shrink lo ]
-  where
-    (lo, _) = Array.bounds arr
-
-makeArray :: (Num i, Ix i, Array.IArray arr a) => i -> [a] -> arr i a
-makeArray lo xs = Array.listArray (lo, lo + fromIntegral (length xs - 1)) xs
-
--------------------------------------------------------------------------------
--- vector
--------------------------------------------------------------------------------
-
-instance Arbitrary1 Vector.Vector where
-    liftArbitrary = fmap Vector.fromList . liftArbitrary
-    liftShrink shr = fmap Vector.fromList . liftShrink shr . Vector.toList
-
-instance Arbitrary a => Arbitrary (Vector.Vector a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Vector.Vector a) where
-    coarbitrary = coarbitraryVector
-
-
-instance (SVector.Storable a, Arbitrary a) => Arbitrary (SVector.Vector a) where
-    arbitrary = arbitraryVector
-    shrink = shrinkVector
-
-instance (SVector.Storable a, CoArbitrary a) => CoArbitrary (SVector.Vector a) where
-    coarbitrary = coarbitraryVector
-
-instance (UVector.Unbox a, Arbitrary a) => Arbitrary (UVector.Vector a) where
-    arbitrary = arbitraryVector
-    shrink = shrinkVector
-
-instance (UVector.Unbox a, CoArbitrary a) => CoArbitrary (UVector.Vector a) where
-    coarbitrary = coarbitraryVector
-
-arbitraryVector :: (GVector.Vector v a, Arbitrary a) => Gen (v a)
-arbitraryVector = GVector.fromList `fmap` arbitrary
-
-shrinkVector :: (GVector.Vector v a, Arbitrary a) => v a -> [v a]
-shrinkVector = fmap GVector.fromList . shrink . GVector.toList
-
-coarbitraryVector :: (GVector.Vector v a, CoArbitrary a) => v a -> Gen b -> Gen b
-coarbitraryVector = coarbitrary . GVector.toList
-
--------------------------------------------------------------------------------
--- scientific
--------------------------------------------------------------------------------
-
-instance Arbitrary Scientific.Scientific where
-    arbitrary = do
-        c <- arbitrary
-        e <- arbitrary
-        return $ Scientific.scientific c e
-    shrink s = map (uncurry Scientific.scientific) $
-        shrink (Scientific.coefficient s, Scientific.base10Exponent s)
-
-instance CoArbitrary Scientific.Scientific where
-    coarbitrary s = coarbitrary (Scientific.coefficient s, Scientific.base10Exponent s)
-
--------------------------------------------------------------------------------
--- bytestring
--------------------------------------------------------------------------------
-
-instance Arbitrary BS.ByteString where
-    arbitrary = BS.pack <$> arbitrary
-    shrink xs = BS.pack <$> shrink (BS.unpack xs)
-
-instance Arbitrary BL.ByteString where
-    arbitrary = BL.pack <$> arbitrary
-    shrink xs = BL.pack <$> shrink (BL.unpack xs)
-
-instance CoArbitrary BS.ByteString where
-    coarbitrary = coarbitrary . BS.unpack
-
-instance CoArbitrary BL.ByteString where
-    coarbitrary = coarbitrary . BL.unpack
-
--------------------------------------------------------------------------------
--- text
--------------------------------------------------------------------------------
-
-instance Arbitrary TS.Text where
-    arbitrary = TS.pack <$> arbitrary
-    shrink xs = TS.pack <$> shrink (TS.unpack xs)
-
-instance Arbitrary TL.Text where
-    arbitrary = TL.pack <$> arbitrary
-    shrink xs = TL.pack <$> shrink (TL.unpack xs)
-
-instance CoArbitrary TS.Text where
-    coarbitrary = coarbitrary . TS.unpack
-
-instance CoArbitrary TL.Text where
-    coarbitrary = coarbitrary . TL.unpack
-
-instance Function TS.Text where
-    function = functionMap TS.unpack TS.pack
-
-instance Function TL.Text where
-    function = functionMap TL.unpack TL.pack
-
--------------------------------------------------------------------------------
--- unordered-containers
--------------------------------------------------------------------------------
-
-instance (Hashable a, Eq a, Arbitrary a) => Arbitrary (HS.HashSet a) where
-    arbitrary = HS.fromList <$> arbitrary
-    shrink hashset = HS.fromList <$> shrink (HS.toList hashset)
-
-instance CoArbitrary a => CoArbitrary (HS.HashSet a) where
-    coarbitrary = coarbitrary . HS.toList
-
-instance (Hashable k, Eq k, Arbitrary k) => Arbitrary1 (HML.HashMap k) where
-    liftArbitrary arb =
-        HML.fromList <$> liftArbitrary (liftArbitrary2 arbitrary arb)
-    liftShrink shr m =
-        HML.fromList <$> liftShrink (liftShrink2 shrink shr) (HML.toList m)
-
-instance (Hashable k, Eq k, Arbitrary k, Arbitrary v) => Arbitrary (HML.HashMap k v) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance (CoArbitrary k, CoArbitrary v) => CoArbitrary (HML.HashMap k v) where
-    coarbitrary = coarbitrary . HML.toList
-
--------------------------------------------------------------------------------
--- hashable
--------------------------------------------------------------------------------
-
-#if MIN_VERSION_hashable(1,2,5)
-instance (Hashable a, Arbitrary a) => Arbitrary (Hashed a) where
-    arbitrary = hashed <$> arbitrary
-
-instance CoArbitrary (Hashed a) where
-    coarbitrary x = coarbitrary (hashed x)
-#endif
-
--------------------------------------------------------------------------------
--- containers
--------------------------------------------------------------------------------
-
-instance Arbitrary1 Tree.Tree where
-    liftArbitrary arb = go
-      where
-        go = sized $ \n -> do -- Sized is the size of the trees.
-            value <- arb
-            pars <- arbPartition (n - 1) -- can go negative!
-            forest <- for pars $ \i -> resize i go
-            return $ Tree.Node value forest
-
-        arbPartition :: Int -> Gen [Int]
-        arbPartition k = case compare k 1 of
-            LT -> pure []
-            EQ -> pure [1]
-            GT -> do
-                first <- elements [1..k]
-                rest <- arbPartition $ k - first
-                return $ first : rest
-
-    liftShrink shr = go 
-      where
-        go (Tree.Node val forest) = forest ++
-            [ Tree.Node e fs
-            | (e, fs) <- liftShrink2 shr (liftShrink go) (val, forest)
-            ]
-
-instance Arbitrary a => Arbitrary (Tree.Tree a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Tree.Tree a) where
-    coarbitrary (Tree.Node val forest) =
-        coarbitrary val . coarbitrary forest
-
--------------------------------------------------------------------------------
--- old-time
--------------------------------------------------------------------------------
-
-instance Arbitrary OldTime.Month where
-    arbitrary = arbitraryBoundedEnum
-
-instance CoArbitrary OldTime.Month where
-    coarbitrary = coarbitraryEnum
-
-instance Arbitrary OldTime.Day where
-    arbitrary = arbitraryBoundedEnum
-
-instance CoArbitrary OldTime.Day where
-    coarbitrary = coarbitraryEnum
-
-instance Arbitrary OldTime.ClockTime where
-    arbitrary =
-        OldTime.TOD <$> choose (0, fromIntegral (maxBound :: Int32))
-                    <*> choose (0, 1000000000000 - 1)
-    shrink (OldTime.TOD s p) =
-        [ OldTime.TOD s' p  | s' <- shrink s ] ++
-        [ OldTime.TOD s  p' | p' <- shrink p ]
-
-instance CoArbitrary OldTime.ClockTime where
-    coarbitrary (OldTime.TOD s p) =
-        coarbitrary s . coarbitrary p
-
-instance Arbitrary OldTime.TimeDiff where
-    -- a bit of a cheat ...
-    arbitrary =
-        OldTime.normalizeTimeDiff <$>
-           (OldTime.diffClockTimes <$> arbitrary <*> arbitrary)
-    shrink td@(OldTime.TimeDiff year month day hour minute sec picosec) =
-        [ td { OldTime.tdYear    = y' } | y' <- shrink year    ] ++
-        [ td { OldTime.tdMonth   = m' } | m' <- shrink month   ] ++
-        [ td { OldTime.tdDay     = d' } | d' <- shrink day     ] ++
-        [ td { OldTime.tdHour    = h' } | h' <- shrink hour    ] ++
-        [ td { OldTime.tdMin     = m' } | m' <- shrink minute  ] ++
-        [ td { OldTime.tdSec     = s' } | s' <- shrink sec     ] ++
-        [ td { OldTime.tdPicosec = p' } | p' <- shrink picosec ]
-
-instance CoArbitrary OldTime.TimeDiff where
-    coarbitrary (OldTime.TimeDiff year month day hour minute sec picosec) =
-        coarbitrary year    .
-        coarbitrary month   .
-        coarbitrary day     .
-        coarbitrary hour    .
-        coarbitrary minute  .
-        coarbitrary sec     .
-        coarbitrary picosec
-
--- UTC only
-instance Arbitrary OldTime.CalendarTime where
-    arbitrary = OldTime.toUTCTime <$> arbitrary
-
-instance CoArbitrary OldTime.CalendarTime where
-    coarbitrary (OldTime.CalendarTime
-                        year month day hour minute sec picosec
-                        wDay yDay tzName tz isDST) =
-        coarbitrary year    .
-        coarbitrary month   .
-        coarbitrary day     .
-        coarbitrary hour    .
-        coarbitrary minute  .
-        coarbitrary sec     .
-        coarbitrary picosec .
-        coarbitrary wDay    .
-        coarbitrary yDay    .
-        coarbitrary tzName  .
-        coarbitrary tz      .
-        coarbitrary isDST
-
--------------------------------------------------------------------------------
--- time
--------------------------------------------------------------------------------
-
-instance Arbitrary Time.Day where
-    arbitrary = Time.ModifiedJulianDay <$> (2000 +) <$> arbitrary
-    shrink    = (Time.ModifiedJulianDay <$>) . shrink . Time.toModifiedJulianDay
-
-instance CoArbitrary Time.Day where
-    coarbitrary = coarbitrary . Time.toModifiedJulianDay
-
-instance Function Time.Day where
-    function = functionMap Time.toModifiedJulianDay Time.ModifiedJulianDay
-
-instance Arbitrary Time.UniversalTime where
-    arbitrary = Time.ModJulianDate <$> (2000 +) <$> arbitrary
-    shrink    = (Time.ModJulianDate <$>) . shrink . Time.getModJulianDate
-
-instance CoArbitrary Time.UniversalTime where
-    coarbitrary = coarbitrary . Time.getModJulianDate
-
-instance Arbitrary Time.DiffTime where
-    arbitrary = arbitrarySizedFractional
-#if MIN_VERSION_time(1,3,0)
-    shrink    = shrinkRealFrac
-#else
-    shrink    = (fromRational <$>) . shrink . toRational
-#endif
-
-instance CoArbitrary Time.DiffTime where
-    coarbitrary = coarbitraryReal
-
-instance Function Time.DiffTime where
-    function = functionMap toRational fromRational
-
-instance Arbitrary Time.UTCTime where
-    arbitrary =
-        Time.UTCTime
-        <$> arbitrary
-        <*> (fromRational . toRational <$> choose (0::Double, 86400))
-    shrink ut@(Time.UTCTime day dayTime) =
-        [ ut { Time.utctDay     = d' } | d' <- shrink day     ] ++
-        [ ut { Time.utctDayTime = t' } | t' <- shrink dayTime ]
-
-instance CoArbitrary Time.UTCTime where
-    coarbitrary (Time.UTCTime day dayTime) =
-        coarbitrary day . coarbitrary dayTime
-
-instance Function Time.UTCTime where
-    function = functionMap (\(Time.UTCTime day dt) -> (day,dt))
-                           (uncurry Time.UTCTime)
-
-instance Arbitrary Time.NominalDiffTime where
-    arbitrary = arbitrarySizedFractional
-    shrink    = shrinkRealFrac
-
-instance CoArbitrary Time.NominalDiffTime where
-    coarbitrary = coarbitraryReal
-
-instance Arbitrary Time.TimeZone where
-    arbitrary =
-        Time.TimeZone
-         <$> choose (-12*60,14*60) -- utc offset (m)
-         <*> arbitrary -- is summer time
-         <*> (sequence . replicate 4 $ choose ('A','Z'))
-    shrink tz@(Time.TimeZone minutes summerOnly name) =
-        [ tz { Time.timeZoneMinutes    = m' } | m' <- shrink minutes    ] ++
-        [ tz { Time.timeZoneSummerOnly = s' } | s' <- shrink summerOnly ] ++
-        [ tz { Time.timeZoneName       = n' } | n' <- shrink name       ]
-
-instance CoArbitrary Time.TimeZone where
-    coarbitrary (Time.TimeZone minutes summerOnly name) =
-        coarbitrary minutes . coarbitrary summerOnly . coarbitrary name
-
-instance Arbitrary Time.TimeOfDay where
-    arbitrary =
-        Time.TimeOfDay
-         <$> choose (0, 23) -- hour
-         <*> choose (0, 59) -- minute
-         <*> (fromRational . toRational <$> choose (0::Double, 60)) -- picoseconds, via double
-    shrink tod@(Time.TimeOfDay hour minute sec) =
-        [ tod { Time.todHour = h' } | h' <- shrink hour   ] ++
-        [ tod { Time.todMin  = m' } | m' <- shrink minute ] ++
-        [ tod { Time.todSec  = s' } | s' <- shrink sec    ]
-
-instance CoArbitrary Time.TimeOfDay where
-    coarbitrary (Time.TimeOfDay hour minute sec) =
-        coarbitrary hour . coarbitrary minute . coarbitrary sec
-
-instance Arbitrary Time.LocalTime where
-    arbitrary =
-        Time.LocalTime
-         <$> arbitrary
-         <*> arbitrary
-    shrink lt@(Time.LocalTime day tod) =
-        [ lt { Time.localDay       = d' } | d' <- shrink day ] ++
-        [ lt { Time.localTimeOfDay = t' } | t' <- shrink tod ]
-
-instance CoArbitrary Time.LocalTime where
-    coarbitrary (Time.LocalTime day tod) =
-        coarbitrary day . coarbitrary tod
-
-instance Arbitrary Time.ZonedTime where
-    arbitrary =
-        Time.ZonedTime
-         <$> arbitrary
-         <*> arbitrary
-    shrink zt@(Time.ZonedTime lt zone) =
-        [ zt { Time.zonedTimeToLocalTime = l' } | l' <- shrink lt   ] ++
-        [ zt { Time.zonedTimeZone        = z' } | z' <- shrink zone ]
-
-instance CoArbitrary Time.ZonedTime where
-    coarbitrary (Time.ZonedTime lt zone) =
-        coarbitrary lt . coarbitrary zone
-
-instance Arbitrary Time.AbsoluteTime where
-    arbitrary =
-        Time.addAbsoluteTime
-         <$> arbitrary
-         <*> return Time.taiEpoch
-    shrink at =
-        (`Time.addAbsoluteTime` at) <$> shrink (Time.diffAbsoluteTime at Time.taiEpoch)
-
-instance CoArbitrary Time.AbsoluteTime where
-    coarbitrary = coarbitrary . flip Time.diffAbsoluteTime Time.taiEpoch
-
--------------------------------------------------------------------------------
--- case-insensitive
--------------------------------------------------------------------------------
-
-instance (CI.FoldCase a, Arbitrary a) => Arbitrary (CI.CI a) where
-    arbitrary = CI.mk <$> arbitrary
-    shrink = fmap CI.mk . shrink . CI.original
-
-instance CoArbitrary a => CoArbitrary (CI.CI a) where
-    coarbitrary = coarbitrary . CI.original
-
-instance (CI.FoldCase a, Function a) => Function (CI.CI a) where
-    function = functionMap CI.mk CI.original
-
--------------------------------------------------------------------------------
--- tagged
--------------------------------------------------------------------------------
-
-instance Arbitrary2 Tagged.Tagged where
-    liftArbitrary2 _ arb = Tagged.Tagged <$> arb
-    liftShrink2 _ shr = fmap Tagged.Tagged . shr . Tagged.unTagged
-
-instance Arbitrary1 (Tagged.Tagged a) where
-    liftArbitrary arb = Tagged.Tagged <$> arb
-    liftShrink shr = fmap Tagged.Tagged . shr . Tagged.unTagged
-
-instance Arbitrary b => Arbitrary (Tagged.Tagged a b) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary b => CoArbitrary (Tagged.Tagged a b) where
-    coarbitrary = coarbitrary . Tagged.unTagged
-
-instance Function b => Function (Tagged.Tagged a b) where
-    function = functionMap Tagged.unTagged Tagged.Tagged
-
-
-instance Arbitrary1 Proxy where
-  liftArbitrary _ = pure Proxy
-  liftShrink _ _ = []
-
-instance Arbitrary (Proxy a) where
-  arbitrary = pure Proxy
-  shrink _  = []
-
-instance CoArbitrary (Proxy a) where
-  coarbitrary _ = id
-
-instance Function (Proxy a) where
-  function = functionMap (const ()) (const Proxy)
-
--------------------------------------------------------------------------------
--- uuid
--------------------------------------------------------------------------------
-
-uuidFromWords :: (Word32, Word32, Word32, Word32) -> UUID.UUID
-uuidFromWords (a,b,c,d) = UUID.fromWords a b c d
-
--- | Uniform distribution.
-instance Arbitrary UUID.UUID where
-    arbitrary = uuidFromWords <$> arbitrary
-    shrink = map uuidFromWords . shrink . UUID.toWords
-
-instance CoArbitrary UUID.UUID where
-    coarbitrary = coarbitrary . UUID.toWords
-
-instance Function UUID.UUID where
-    function = functionMap UUID.toWords uuidFromWords
-
--------------------------------------------------------------------------------
--- nats
--------------------------------------------------------------------------------
-
-instance Arbitrary Natural where
-  arbitrary = arbitrarySizedNatural
-  shrink    = shrinkIntegral
-
-instance CoArbitrary Natural where
-  coarbitrary = coarbitraryIntegral
-
-instance Function Natural where
-  function = functionIntegral
-
--------------------------------------------------------------------------------
--- semigroups
--------------------------------------------------------------------------------
-
-instance Arbitrary1 NonEmpty where
-  liftArbitrary arb = liftA2 (:|) arb (liftArbitrary arb)
-  liftShrink shr (x :| xs) = mapMaybe nonEmpty . liftShrink shr $ x : xs
-
-instance Arbitrary a => Arbitrary (NonEmpty a) where
-  arbitrary = arbitrary1
-  shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (NonEmpty a) where
-  coarbitrary (x :| xs) = coarbitrary (x, xs)
-
-instance Function a => Function (NonEmpty a) where
-  function = functionMap g h
-   where
-     g (x :| xs) = (x,   xs)
-     h (x,   xs) =  x :| xs
-
-
-instance Arbitrary1 Semi.Min where
-    liftArbitrary arb = Semi.Min <$> arb
-    liftShrink shr = map Semi.Min . shr . Semi.getMin
-
-instance Arbitrary a => Arbitrary (Semi.Min a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Semi.Min a) where
-    coarbitrary = coarbitrary . Semi.getMin
-
-instance Function a => Function (Semi.Min a) where
-    function = functionMap Semi.getMin Semi.Min
-
-
-instance Arbitrary1 Semi.Max where
-    liftArbitrary arb = Semi.Max <$> arb
-    liftShrink shr = map Semi.Max . shr . Semi.getMax
-
-instance Arbitrary a => Arbitrary (Semi.Max a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Semi.Max a) where
-    coarbitrary = coarbitrary . Semi.getMax
-
-instance Function a => Function (Semi.Max a) where
-    function = functionMap Semi.getMax Semi.Max
-
-
-instance Arbitrary1 Semi.First where
-    liftArbitrary arb = Semi.First <$> arb
-    liftShrink shr = map Semi.First . shr . Semi.getFirst
-
-instance Arbitrary a => Arbitrary (Semi.First a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Semi.First a) where
-    coarbitrary = coarbitrary . Semi.getFirst
-
-instance Function a => Function (Semi.First a) where
-    function = functionMap Semi.getFirst Semi.First
-
-
-instance Arbitrary1 Semi.Last where
-    liftArbitrary arb = Semi.Last <$> arb
-    liftShrink shr = map Semi.Last . shr . Semi.getLast
-
-instance Arbitrary a => Arbitrary (Semi.Last a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Semi.Last a) where
-    coarbitrary = coarbitrary . Semi.getLast
-
-instance Function a => Function (Semi.Last a) where
-    function = functionMap Semi.getLast Semi.Last
-
-
-instance Arbitrary1 Semi.WrappedMonoid where
-    liftArbitrary arb = Semi.WrapMonoid <$> arb
-    liftShrink shr = map Semi.WrapMonoid . shr . Semi.unwrapMonoid
-
-instance Arbitrary a => Arbitrary (Semi.WrappedMonoid a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Semi.WrappedMonoid a) where
-    coarbitrary = coarbitrary . Semi.unwrapMonoid
-
-instance Function a => Function (Semi.WrappedMonoid a) where
-    function = functionMap Semi.unwrapMonoid Semi.WrapMonoid
-
-
-instance Arbitrary1 Semi.Option where
-    liftArbitrary arb = Semi.Option <$> liftArbitrary arb
-    liftShrink shr = map Semi.Option . liftShrink shr . Semi.getOption
-
-instance Arbitrary a => Arbitrary (Semi.Option a) where
-    arbitrary = arbitrary1
-    shrink = shrink1
-
-instance CoArbitrary a => CoArbitrary (Semi.Option a) where
-    coarbitrary = coarbitrary . Semi.getOption
-
-instance Function a => Function (Semi.Option a) where
-    function = functionMap Semi.getOption Semi.Option
-
--------------------------------------------------------------------------------
--- transformers
--------------------------------------------------------------------------------
-
--- TODO: CoArbitrary and Function, needs Coarbitrary1 and Function1
-
-instance (Arbitrary1 f, Arbitrary1 g) => Arbitrary1 (Sum f g) where
-  liftArbitrary arb = oneof [fmap InL (liftArbitrary arb), fmap InR (liftArbitrary arb)]
-  liftShrink shr (InL f) = map InL (liftShrink shr f)
-  liftShrink shr (InR g) = map InR (liftShrink shr g)
-
-instance (Arbitrary1 f, Arbitrary1 g, Arbitrary a) => Arbitrary (Sum f g a) where
-  arbitrary = arbitrary1
-  shrink = shrink1
+import Test.QuickCheck.Instances.Array ()
+import Test.QuickCheck.Instances.ByteString ()
+import Test.QuickCheck.Instances.CaseInsensitive ()
+import Test.QuickCheck.Instances.Containers ()
+import Test.QuickCheck.Instances.Hashable ()
+import Test.QuickCheck.Instances.Natural ()
+import Test.QuickCheck.Instances.OldTime ()
+import Test.QuickCheck.Instances.Natural ()
+import Test.QuickCheck.Instances.Scientific ()
+import Test.QuickCheck.Instances.Semigroup ()
+import Test.QuickCheck.Instances.Tagged ()
+import Test.QuickCheck.Instances.Text ()
+import Test.QuickCheck.Instances.Time ()
+import Test.QuickCheck.Instances.Transformer ()
+import Test.QuickCheck.Instances.UUID ()
+import Test.QuickCheck.Instances.UnorderedContainers ()
+import Test.QuickCheck.Instances.Vector ()
diff --git a/src/Test/QuickCheck/Instances/Array.hs b/src/Test/QuickCheck/Instances/Array.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Array.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Array () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Control.Applicative (liftA2)
+import Data.Ix (Ix (..))
+
+import Test.QuickCheck
+
+import qualified Data.Array.IArray as Array
+import qualified Data.Array.Unboxed as Array
+
+-------------------------------------------------------------------------------
+-- array
+-------------------------------------------------------------------------------
+
+instance (Num i, Ix i, Arbitrary i) => Arbitrary1 (Array.Array i) where
+    liftArbitrary = liftA2 makeArray arbitrary . liftArbitrary
+    liftShrink = shrinkArray
+
+instance (Num i, Ix i, Arbitrary i, Arbitrary a) => Arbitrary (Array.Array i a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance (Ix i, CoArbitrary i, CoArbitrary a) => CoArbitrary (Array.Array i a) where
+    coarbitrary arr = coarbitrary (Array.bounds arr, Array.elems arr)
+
+
+instance (Num i, Ix i, Array.IArray Array.UArray a, Arbitrary i, Arbitrary a) => Arbitrary (Array.UArray i a) where
+    arbitrary = liftA2 makeArray arbitrary arbitrary
+    shrink = shrinkArray shrink
+
+instance (Ix i, Array.IArray Array.UArray a, CoArbitrary i, CoArbitrary a) => CoArbitrary (Array.UArray i a) where
+    coarbitrary arr = coarbitrary (Array.bounds arr, Array.elems arr)
+
+
+shrinkArray
+    :: (Num i, Ix i, Array.IArray arr a, Arbitrary i)
+    => (a -> [a]) -> arr i a -> [arr i a]
+shrinkArray shr arr =
+  [ makeArray lo xs | xs <- liftShrink shr (Array.elems arr) ] ++
+  [ makeArray lo' (Array.elems arr) | lo' <- shrink lo ]
+  where
+    (lo, _) = Array.bounds arr
+
+makeArray :: (Num i, Ix i, Array.IArray arr a) => i -> [a] -> arr i a
+makeArray lo xs = Array.listArray (lo, lo + fromIntegral (length xs - 1)) xs
diff --git a/src/Test/QuickCheck/Instances/ByteString.hs b/src/Test/QuickCheck/Instances/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/ByteString.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.ByteString () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Test.QuickCheck
+
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BL
+#if MIN_VERSION_bytestring(0,10,4)
+import qualified Data.ByteString.Short as SBS
+#endif
+
+-------------------------------------------------------------------------------
+-- bytestring
+-------------------------------------------------------------------------------
+
+instance Arbitrary BS.ByteString where
+    arbitrary = BS.pack <$> arbitrary
+    shrink xs = BS.pack <$> shrink (BS.unpack xs)
+
+instance CoArbitrary BS.ByteString where
+    coarbitrary = coarbitrary . BS.unpack
+
+instance Function BS.ByteString where
+    function = functionMap BS.unpack BS.pack
+
+
+instance Arbitrary BL.ByteString where
+    arbitrary = BL.pack <$> arbitrary
+    shrink xs = BL.pack <$> shrink (BL.unpack xs)
+
+instance CoArbitrary BL.ByteString where
+    coarbitrary = coarbitrary . BL.unpack
+
+instance Function BL.ByteString where
+    function = functionMap BL.unpack BL.pack
+
+
+#if MIN_VERSION_bytestring(0,10,4)
+instance Arbitrary SBS.ShortByteString where
+    arbitrary = SBS.pack <$> arbitrary
+    shrink xs = SBS.pack <$> shrink (SBS.unpack xs)
+
+instance CoArbitrary SBS.ShortByteString where
+    coarbitrary = coarbitrary . SBS.unpack
+
+instance Function SBS.ShortByteString where
+    function = functionMap SBS.unpack SBS.pack
+#endif
diff --git a/src/Test/QuickCheck/Instances/CaseInsensitive.hs b/src/Test/QuickCheck/Instances/CaseInsensitive.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/CaseInsensitive.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.CaseInsensitive () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Test.QuickCheck
+
+import qualified Data.CaseInsensitive as CI
+
+-------------------------------------------------------------------------------
+-- case-insensitive
+-------------------------------------------------------------------------------
+
+instance (CI.FoldCase a, Arbitrary a) => Arbitrary (CI.CI a) where
+    arbitrary = CI.mk <$> arbitrary
+    shrink = fmap CI.mk . shrink . CI.original
+
+instance CoArbitrary a => CoArbitrary (CI.CI a) where
+    coarbitrary = coarbitrary . CI.original
+
+instance (CI.FoldCase a, Function a) => Function (CI.CI a) where
+    function = functionMap CI.mk CI.original
diff --git a/src/Test/QuickCheck/Instances/Containers.hs b/src/Test/QuickCheck/Instances/Containers.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Containers.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Containers () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Traversable (for)
+
+import Test.QuickCheck
+
+import qualified Data.Tree as Tree
+
+-------------------------------------------------------------------------------
+-- containers
+-------------------------------------------------------------------------------
+
+instance Arbitrary1 Tree.Tree where
+    liftArbitrary arb = go
+      where
+        go = sized $ \n -> do -- Sized is the size of the trees.
+            value <- arb
+            pars <- arbPartition (n - 1) -- can go negative!
+            forest <- for pars $ \i -> resize i go
+            return $ Tree.Node value forest
+
+        arbPartition :: Int -> Gen [Int]
+        arbPartition k = case compare k 1 of
+            LT -> pure []
+            EQ -> pure [1]
+            GT -> do
+                first <- elements [1..k]
+                rest <- arbPartition $ k - first
+                return $ first : rest
+
+    liftShrink shr = go 
+      where
+        go (Tree.Node val forest) = forest ++
+            [ Tree.Node e fs
+            | (e, fs) <- liftShrink2 shr (liftShrink go) (val, forest)
+            ]
+
+instance Arbitrary a => Arbitrary (Tree.Tree a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Tree.Tree a) where
+    coarbitrary (Tree.Node val forest) =
+        coarbitrary val . coarbitrary forest
diff --git a/src/Test/QuickCheck/Instances/Hashable.hs b/src/Test/QuickCheck/Instances/Hashable.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Hashable.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Hashable () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Hashable (Hashable, Hashed, hashed)
+
+import Test.QuickCheck
+
+-------------------------------------------------------------------------------
+-- hashable
+-------------------------------------------------------------------------------
+
+#if MIN_VERSION_hashable(1,2,5)
+instance (Hashable a, Arbitrary a) => Arbitrary (Hashed a) where
+    arbitrary = hashed <$> arbitrary
+
+instance CoArbitrary (Hashed a) where
+    coarbitrary x = coarbitrary (hashed x)
+#endif
diff --git a/src/Test/QuickCheck/Instances/Natural.hs b/src/Test/QuickCheck/Instances/Natural.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Natural.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Natural () where
+
+import Prelude ()
+
+import Numeric.Natural (Natural)
+
+import Test.QuickCheck
+import Test.QuickCheck.Function (functionIntegral)
+
+-------------------------------------------------------------------------------
+-- nats
+-------------------------------------------------------------------------------
+
+instance Arbitrary Natural where
+  arbitrary = arbitrarySizedNatural
+  shrink    = shrinkIntegral
+
+instance CoArbitrary Natural where
+  coarbitrary = coarbitraryIntegral
+
+instance Function Natural where
+  function = functionIntegral
diff --git a/src/Test/QuickCheck/Instances/OldTime.hs b/src/Test/QuickCheck/Instances/OldTime.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/OldTime.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.OldTime () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Int (Int32)
+
+import Test.QuickCheck
+
+import qualified System.Time as OldTime
+
+-------------------------------------------------------------------------------
+-- old-time
+-------------------------------------------------------------------------------
+
+instance Arbitrary OldTime.Month where
+    arbitrary = arbitraryBoundedEnum
+
+instance CoArbitrary OldTime.Month where
+    coarbitrary = coarbitraryEnum
+
+instance Arbitrary OldTime.Day where
+    arbitrary = arbitraryBoundedEnum
+
+instance CoArbitrary OldTime.Day where
+    coarbitrary = coarbitraryEnum
+
+instance Arbitrary OldTime.ClockTime where
+    arbitrary =
+        OldTime.TOD <$> choose (0, fromIntegral (maxBound :: Int32))
+                    <*> choose (0, 1000000000000 - 1)
+    shrink (OldTime.TOD s p) =
+        [ OldTime.TOD s' p  | s' <- shrink s ] ++
+        [ OldTime.TOD s  p' | p' <- shrink p ]
+
+instance CoArbitrary OldTime.ClockTime where
+    coarbitrary (OldTime.TOD s p) =
+        coarbitrary s . coarbitrary p
+
+instance Arbitrary OldTime.TimeDiff where
+    -- a bit of a cheat ...
+    arbitrary =
+        OldTime.normalizeTimeDiff <$>
+           (OldTime.diffClockTimes <$> arbitrary <*> arbitrary)
+    shrink td@(OldTime.TimeDiff year month day hour minute sec picosec) =
+        [ td { OldTime.tdYear    = y' } | y' <- shrink year    ] ++
+        [ td { OldTime.tdMonth   = m' } | m' <- shrink month   ] ++
+        [ td { OldTime.tdDay     = d' } | d' <- shrink day     ] ++
+        [ td { OldTime.tdHour    = h' } | h' <- shrink hour    ] ++
+        [ td { OldTime.tdMin     = m' } | m' <- shrink minute  ] ++
+        [ td { OldTime.tdSec     = s' } | s' <- shrink sec     ] ++
+        [ td { OldTime.tdPicosec = p' } | p' <- shrink picosec ]
+
+instance CoArbitrary OldTime.TimeDiff where
+    coarbitrary (OldTime.TimeDiff year month day hour minute sec picosec) =
+        coarbitrary year    .
+        coarbitrary month   .
+        coarbitrary day     .
+        coarbitrary hour    .
+        coarbitrary minute  .
+        coarbitrary sec     .
+        coarbitrary picosec
+
+-- UTC only
+instance Arbitrary OldTime.CalendarTime where
+    arbitrary = OldTime.toUTCTime <$> arbitrary
+
+instance CoArbitrary OldTime.CalendarTime where
+    coarbitrary (OldTime.CalendarTime
+                        year month day hour minute sec picosec
+                        wDay yDay tzName tz isDST) =
+        coarbitrary year    .
+        coarbitrary month   .
+        coarbitrary day     .
+        coarbitrary hour    .
+        coarbitrary minute  .
+        coarbitrary sec     .
+        coarbitrary picosec .
+        coarbitrary wDay    .
+        coarbitrary yDay    .
+        coarbitrary tzName  .
+        coarbitrary tz      .
+        coarbitrary isDST
diff --git a/src/Test/QuickCheck/Instances/Scientific.hs b/src/Test/QuickCheck/Instances/Scientific.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Scientific.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Scientific () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Test.QuickCheck
+
+import qualified Data.Scientific as Scientific
+
+-------------------------------------------------------------------------------
+-- scientific
+-------------------------------------------------------------------------------
+
+instance Arbitrary Scientific.Scientific where
+    arbitrary = do
+        c <- arbitrary
+        e <- arbitrary
+        return $ Scientific.scientific c e
+    shrink s = map (uncurry Scientific.scientific) $
+        shrink (Scientific.coefficient s, Scientific.base10Exponent s)
+
+instance CoArbitrary Scientific.Scientific where
+    coarbitrary s = coarbitrary (Scientific.coefficient s, Scientific.base10Exponent s)
diff --git a/src/Test/QuickCheck/Instances/Semigroup.hs b/src/Test/QuickCheck/Instances/Semigroup.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Semigroup.hs
@@ -0,0 +1,126 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Semigroup () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Control.Applicative (liftA2)
+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)
+import Data.Maybe (mapMaybe)
+
+import Test.QuickCheck
+
+import qualified Data.Semigroup as Semi
+
+-------------------------------------------------------------------------------
+-- semigroups
+-------------------------------------------------------------------------------
+
+instance Arbitrary1 NonEmpty where
+  liftArbitrary arb = liftA2 (:|) arb (liftArbitrary arb)
+  liftShrink shr (x :| xs) = mapMaybe nonEmpty . liftShrink shr $ x : xs
+
+instance Arbitrary a => Arbitrary (NonEmpty a) where
+  arbitrary = arbitrary1
+  shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (NonEmpty a) where
+  coarbitrary (x :| xs) = coarbitrary (x, xs)
+
+instance Function a => Function (NonEmpty a) where
+  function = functionMap g h
+   where
+     g (x :| xs) = (x,   xs)
+     h (x,   xs) =  x :| xs
+
+
+instance Arbitrary1 Semi.Min where
+    liftArbitrary arb = Semi.Min <$> arb
+    liftShrink shr = map Semi.Min . shr . Semi.getMin
+
+instance Arbitrary a => Arbitrary (Semi.Min a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Semi.Min a) where
+    coarbitrary = coarbitrary . Semi.getMin
+
+instance Function a => Function (Semi.Min a) where
+    function = functionMap Semi.getMin Semi.Min
+
+
+instance Arbitrary1 Semi.Max where
+    liftArbitrary arb = Semi.Max <$> arb
+    liftShrink shr = map Semi.Max . shr . Semi.getMax
+
+instance Arbitrary a => Arbitrary (Semi.Max a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Semi.Max a) where
+    coarbitrary = coarbitrary . Semi.getMax
+
+instance Function a => Function (Semi.Max a) where
+    function = functionMap Semi.getMax Semi.Max
+
+
+instance Arbitrary1 Semi.First where
+    liftArbitrary arb = Semi.First <$> arb
+    liftShrink shr = map Semi.First . shr . Semi.getFirst
+
+instance Arbitrary a => Arbitrary (Semi.First a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Semi.First a) where
+    coarbitrary = coarbitrary . Semi.getFirst
+
+instance Function a => Function (Semi.First a) where
+    function = functionMap Semi.getFirst Semi.First
+
+
+instance Arbitrary1 Semi.Last where
+    liftArbitrary arb = Semi.Last <$> arb
+    liftShrink shr = map Semi.Last . shr . Semi.getLast
+
+instance Arbitrary a => Arbitrary (Semi.Last a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Semi.Last a) where
+    coarbitrary = coarbitrary . Semi.getLast
+
+instance Function a => Function (Semi.Last a) where
+    function = functionMap Semi.getLast Semi.Last
+
+
+instance Arbitrary1 Semi.WrappedMonoid where
+    liftArbitrary arb = Semi.WrapMonoid <$> arb
+    liftShrink shr = map Semi.WrapMonoid . shr . Semi.unwrapMonoid
+
+instance Arbitrary a => Arbitrary (Semi.WrappedMonoid a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Semi.WrappedMonoid a) where
+    coarbitrary = coarbitrary . Semi.unwrapMonoid
+
+instance Function a => Function (Semi.WrappedMonoid a) where
+    function = functionMap Semi.unwrapMonoid Semi.WrapMonoid
+
+
+instance Arbitrary1 Semi.Option where
+    liftArbitrary arb = Semi.Option <$> liftArbitrary arb
+    liftShrink shr = map Semi.Option . liftShrink shr . Semi.getOption
+
+instance Arbitrary a => Arbitrary (Semi.Option a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Semi.Option a) where
+    coarbitrary = coarbitrary . Semi.getOption
+
+instance Function a => Function (Semi.Option a) where
+    function = functionMap Semi.getOption Semi.Option
diff --git a/src/Test/QuickCheck/Instances/Tagged.hs b/src/Test/QuickCheck/Instances/Tagged.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Tagged.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+#if __GLASGOW_HASKELL__ >= 706
+{-# LANGUAGE PolyKinds #-}
+#endif
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Tagged () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Proxy (Proxy (Proxy))
+
+import Test.QuickCheck
+
+import qualified Data.Tagged as Tagged (Tagged (..))
+
+-------------------------------------------------------------------------------
+-- tagged
+-------------------------------------------------------------------------------
+
+instance Arbitrary2 Tagged.Tagged where
+    liftArbitrary2 _ arb = Tagged.Tagged <$> arb
+    liftShrink2 _ shr = fmap Tagged.Tagged . shr . Tagged.unTagged
+
+instance Arbitrary1 (Tagged.Tagged a) where
+    liftArbitrary arb = Tagged.Tagged <$> arb
+    liftShrink shr = fmap Tagged.Tagged . shr . Tagged.unTagged
+
+instance Arbitrary b => Arbitrary (Tagged.Tagged a b) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary b => CoArbitrary (Tagged.Tagged a b) where
+    coarbitrary = coarbitrary . Tagged.unTagged
+
+instance Function b => Function (Tagged.Tagged a b) where
+    function = functionMap Tagged.unTagged Tagged.Tagged
+
+
+instance Arbitrary1 Proxy where
+  liftArbitrary _ = pure Proxy
+  liftShrink _ _ = []
+
+instance Arbitrary (Proxy a) where
+  arbitrary = pure Proxy
+  shrink _  = []
+
+instance CoArbitrary (Proxy a) where
+  coarbitrary _ = id
+
+instance Function (Proxy a) where
+  function = functionMap (const ()) (const Proxy)
diff --git a/src/Test/QuickCheck/Instances/Text.hs b/src/Test/QuickCheck/Instances/Text.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Text.hs
@@ -0,0 +1,36 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Text () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Test.QuickCheck
+
+import qualified Data.Text as TS
+import qualified Data.Text.Lazy as TL
+
+-------------------------------------------------------------------------------
+-- text
+-------------------------------------------------------------------------------
+
+instance Arbitrary TS.Text where
+    arbitrary = TS.pack <$> arbitrary
+    shrink xs = TS.pack <$> shrink (TS.unpack xs)
+
+instance Arbitrary TL.Text where
+    arbitrary = TL.pack <$> arbitrary
+    shrink xs = TL.pack <$> shrink (TL.unpack xs)
+
+instance CoArbitrary TS.Text where
+    coarbitrary = coarbitrary . TS.unpack
+
+instance CoArbitrary TL.Text where
+    coarbitrary = coarbitrary . TL.unpack
+
+instance Function TS.Text where
+    function = functionMap TS.unpack TS.pack
+
+instance Function TL.Text where
+    function = functionMap TL.unpack TL.pack
diff --git a/src/Test/QuickCheck/Instances/Time.hs b/src/Test/QuickCheck/Instances/Time.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Time.hs
@@ -0,0 +1,138 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Time () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Test.QuickCheck
+
+import qualified Data.Time as Time
+import qualified Data.Time.Clock.TAI as Time
+
+-------------------------------------------------------------------------------
+-- time
+-------------------------------------------------------------------------------
+
+instance Arbitrary Time.Day where
+    arbitrary = Time.ModifiedJulianDay <$> (2000 +) <$> arbitrary
+    shrink    = (Time.ModifiedJulianDay <$>) . shrink . Time.toModifiedJulianDay
+
+instance CoArbitrary Time.Day where
+    coarbitrary = coarbitrary . Time.toModifiedJulianDay
+
+instance Function Time.Day where
+    function = functionMap Time.toModifiedJulianDay Time.ModifiedJulianDay
+
+instance Arbitrary Time.UniversalTime where
+    arbitrary = Time.ModJulianDate <$> (2000 +) <$> arbitrary
+    shrink    = (Time.ModJulianDate <$>) . shrink . Time.getModJulianDate
+
+instance CoArbitrary Time.UniversalTime where
+    coarbitrary = coarbitrary . Time.getModJulianDate
+
+instance Arbitrary Time.DiffTime where
+    arbitrary = arbitrarySizedFractional
+#if MIN_VERSION_time(1,3,0)
+    shrink    = shrinkRealFrac
+#else
+    shrink    = (fromRational <$>) . shrink . toRational
+#endif
+
+instance CoArbitrary Time.DiffTime where
+    coarbitrary = coarbitraryReal
+
+instance Function Time.DiffTime where
+    function = functionMap toRational fromRational
+
+instance Arbitrary Time.UTCTime where
+    arbitrary =
+        Time.UTCTime
+        <$> arbitrary
+        <*> (fromRational . toRational <$> choose (0::Double, 86400))
+    shrink ut@(Time.UTCTime day dayTime) =
+        [ ut { Time.utctDay     = d' } | d' <- shrink day     ] ++
+        [ ut { Time.utctDayTime = t' } | t' <- shrink dayTime ]
+
+instance CoArbitrary Time.UTCTime where
+    coarbitrary (Time.UTCTime day dayTime) =
+        coarbitrary day . coarbitrary dayTime
+
+instance Function Time.UTCTime where
+    function = functionMap (\(Time.UTCTime day dt) -> (day,dt))
+                           (uncurry Time.UTCTime)
+
+instance Arbitrary Time.NominalDiffTime where
+    arbitrary = arbitrarySizedFractional
+    shrink    = shrinkRealFrac
+
+instance CoArbitrary Time.NominalDiffTime where
+    coarbitrary = coarbitraryReal
+
+instance Arbitrary Time.TimeZone where
+    arbitrary =
+        Time.TimeZone
+         <$> choose (-12*60,14*60) -- utc offset (m)
+         <*> arbitrary -- is summer time
+         <*> (sequence . replicate 4 $ choose ('A','Z'))
+    shrink tz@(Time.TimeZone minutes summerOnly name) =
+        [ tz { Time.timeZoneMinutes    = m' } | m' <- shrink minutes    ] ++
+        [ tz { Time.timeZoneSummerOnly = s' } | s' <- shrink summerOnly ] ++
+        [ tz { Time.timeZoneName       = n' } | n' <- shrink name       ]
+
+instance CoArbitrary Time.TimeZone where
+    coarbitrary (Time.TimeZone minutes summerOnly name) =
+        coarbitrary minutes . coarbitrary summerOnly . coarbitrary name
+
+instance Arbitrary Time.TimeOfDay where
+    arbitrary =
+        Time.TimeOfDay
+         <$> choose (0, 23) -- hour
+         <*> choose (0, 59) -- minute
+         <*> (fromRational . toRational <$> choose (0::Double, 60)) -- picoseconds, via double
+    shrink tod@(Time.TimeOfDay hour minute sec) =
+        [ tod { Time.todHour = h' } | h' <- shrink hour   ] ++
+        [ tod { Time.todMin  = m' } | m' <- shrink minute ] ++
+        [ tod { Time.todSec  = s' } | s' <- shrink sec    ]
+
+instance CoArbitrary Time.TimeOfDay where
+    coarbitrary (Time.TimeOfDay hour minute sec) =
+        coarbitrary hour . coarbitrary minute . coarbitrary sec
+
+instance Arbitrary Time.LocalTime where
+    arbitrary =
+        Time.LocalTime
+         <$> arbitrary
+         <*> arbitrary
+    shrink lt@(Time.LocalTime day tod) =
+        [ lt { Time.localDay       = d' } | d' <- shrink day ] ++
+        [ lt { Time.localTimeOfDay = t' } | t' <- shrink tod ]
+
+instance CoArbitrary Time.LocalTime where
+    coarbitrary (Time.LocalTime day tod) =
+        coarbitrary day . coarbitrary tod
+
+instance Arbitrary Time.ZonedTime where
+    arbitrary =
+        Time.ZonedTime
+         <$> arbitrary
+         <*> arbitrary
+    shrink zt@(Time.ZonedTime lt zone) =
+        [ zt { Time.zonedTimeToLocalTime = l' } | l' <- shrink lt   ] ++
+        [ zt { Time.zonedTimeZone        = z' } | z' <- shrink zone ]
+
+instance CoArbitrary Time.ZonedTime where
+    coarbitrary (Time.ZonedTime lt zone) =
+        coarbitrary lt . coarbitrary zone
+
+instance Arbitrary Time.AbsoluteTime where
+    arbitrary =
+        Time.addAbsoluteTime
+         <$> arbitrary
+         <*> return Time.taiEpoch
+    shrink at =
+        (`Time.addAbsoluteTime` at) <$> shrink (Time.diffAbsoluteTime at Time.taiEpoch)
+
+instance CoArbitrary Time.AbsoluteTime where
+    coarbitrary = coarbitrary . flip Time.diffAbsoluteTime Time.taiEpoch
diff --git a/src/Test/QuickCheck/Instances/Transformer.hs b/src/Test/QuickCheck/Instances/Transformer.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Transformer.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Transformer () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Functor.Sum (Sum (..))
+
+import Test.QuickCheck
+
+-------------------------------------------------------------------------------
+-- transformers
+-------------------------------------------------------------------------------
+
+-- TODO: CoArbitrary and Function, needs Coarbitrary1 and Function1
+
+instance (Arbitrary1 f, Arbitrary1 g) => Arbitrary1 (Sum f g) where
+  liftArbitrary arb = oneof [fmap InL (liftArbitrary arb), fmap InR (liftArbitrary arb)]
+  liftShrink shr (InL f) = map InL (liftShrink shr f)
+  liftShrink shr (InR g) = map InR (liftShrink shr g)
+
+instance (Arbitrary1 f, Arbitrary1 g, Arbitrary a) => Arbitrary (Sum f g a) where
+  arbitrary = arbitrary1
+  shrink = shrink1
diff --git a/src/Test/QuickCheck/Instances/UUID.hs b/src/Test/QuickCheck/Instances/UUID.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/UUID.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.UUID () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Word (Word32)
+
+import Test.QuickCheck
+
+import qualified Data.UUID.Types as UUID
+
+-------------------------------------------------------------------------------
+-- uuid
+-------------------------------------------------------------------------------
+
+uuidFromWords :: (Word32, Word32, Word32, Word32) -> UUID.UUID
+uuidFromWords (a,b,c,d) = UUID.fromWords a b c d
+
+-- | Uniform distribution.
+instance Arbitrary UUID.UUID where
+    arbitrary = uuidFromWords <$> arbitrary
+    shrink = map uuidFromWords . shrink . UUID.toWords
+
+instance CoArbitrary UUID.UUID where
+    coarbitrary = coarbitrary . UUID.toWords
+
+instance Function UUID.UUID where
+    function = functionMap UUID.toWords uuidFromWords
diff --git a/src/Test/QuickCheck/Instances/UnorderedContainers.hs b/src/Test/QuickCheck/Instances/UnorderedContainers.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/UnorderedContainers.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.UnorderedContainers () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Data.Hashable (Hashable)
+
+import Test.QuickCheck
+
+import qualified Data.HashMap.Lazy as HML
+import qualified Data.HashSet as HS
+
+-------------------------------------------------------------------------------
+-- unordered-containers
+-------------------------------------------------------------------------------
+
+instance (Hashable a, Eq a, Arbitrary a) => Arbitrary (HS.HashSet a) where
+    arbitrary = HS.fromList <$> arbitrary
+    shrink hashset = HS.fromList <$> shrink (HS.toList hashset)
+
+instance CoArbitrary a => CoArbitrary (HS.HashSet a) where
+    coarbitrary = coarbitrary . HS.toList
+
+instance (Hashable k, Eq k, Arbitrary k) => Arbitrary1 (HML.HashMap k) where
+    liftArbitrary arb =
+        HML.fromList <$> liftArbitrary (liftArbitrary2 arbitrary arb)
+    liftShrink shr m =
+        HML.fromList <$> liftShrink (liftShrink2 shrink shr) (HML.toList m)
+
+instance (Hashable k, Eq k, Arbitrary k, Arbitrary v) => Arbitrary (HML.HashMap k v) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance (CoArbitrary k, CoArbitrary v) => CoArbitrary (HML.HashMap k v) where
+    coarbitrary = coarbitrary . HML.toList
diff --git a/src/Test/QuickCheck/Instances/Vector.hs b/src/Test/QuickCheck/Instances/Vector.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/QuickCheck/Instances/Vector.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Test.QuickCheck.Instances.Vector () where
+
+import Prelude ()
+import Prelude.Compat
+
+import Test.QuickCheck
+
+import qualified Data.Vector as Vector
+import qualified Data.Vector.Generic as GVector
+import qualified Data.Vector.Storable as SVector
+import qualified Data.Vector.Unboxed as UVector
+
+-------------------------------------------------------------------------------
+-- vector
+-------------------------------------------------------------------------------
+
+instance Arbitrary1 Vector.Vector where
+    liftArbitrary = fmap Vector.fromList . liftArbitrary
+    liftShrink shr = fmap Vector.fromList . liftShrink shr . Vector.toList
+
+instance Arbitrary a => Arbitrary (Vector.Vector a) where
+    arbitrary = arbitrary1
+    shrink = shrink1
+
+instance CoArbitrary a => CoArbitrary (Vector.Vector a) where
+    coarbitrary = coarbitraryVector
+
+
+instance (SVector.Storable a, Arbitrary a) => Arbitrary (SVector.Vector a) where
+    arbitrary = arbitraryVector
+    shrink = shrinkVector
+
+instance (SVector.Storable a, CoArbitrary a) => CoArbitrary (SVector.Vector a) where
+    coarbitrary = coarbitraryVector
+
+instance (UVector.Unbox a, Arbitrary a) => Arbitrary (UVector.Vector a) where
+    arbitrary = arbitraryVector
+    shrink = shrinkVector
+
+instance (UVector.Unbox a, CoArbitrary a) => CoArbitrary (UVector.Vector a) where
+    coarbitrary = coarbitraryVector
+
+arbitraryVector :: (GVector.Vector v a, Arbitrary a) => Gen (v a)
+arbitraryVector = GVector.fromList `fmap` arbitrary
+
+shrinkVector :: (GVector.Vector v a, Arbitrary a) => v a -> [v a]
+shrinkVector = fmap GVector.fromList . shrink . GVector.toList
+
+coarbitraryVector :: (GVector.Vector v a, CoArbitrary a) => v a -> Gen b -> Gen b
+coarbitraryVector = coarbitrary . GVector.toList
