content: -- An example of generic Arbitrary instances with explicit generators
  -- for some types of fields for which there is no 'Arbitrary' instance
  -- or the existing one is unsatisfactory.
  --
  -- For example, Postgres can't handle strings containing NUL characters
  -- see https://github.com/lpsmith/postgresql-simple/issues/223
  -- so applications may want to generate data without them.
  
  {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE FlexibleInstances #-}
  
  import Data.Char (isAlphaNum)
  import Data.Text as T (Text, pack, unpack)
  import GHC.Generics (Generic)
  import Test.QuickCheck
  
  import Generic.Random
  
  instance Arbitrary Text where
    arbitrary = pack <$> arbitrary
    shrink = fmap pack . shrink . unpack
  
  data R = R                    -- Two constraints:
    { name :: Text              -- names and
    , address :: Text           -- addresses don't contain '\NUL'
    , id_ :: Text               -- IDs are alphanumeric
    } deriving (Show, Generic)
  
  instance Arbitrary R where
    arbitrary = genericArbitrarySingleG gens
      where
        gens =
          (FieldGen (pack . filter isAlphaNum <$> scale (* 5) arbitrary)
            :: FieldGen "id_" Text) :+
          (pack . filter (/= '\NUL') <$> arbitrary)
  
    shrink = genericShrink
  
  newtype Bugged a = Bugged a deriving Show
  
  instance Arbitrary (Bugged R) where
    arbitrary = Bugged <$> genericArbitrarySingle
    shrink (Bugged r) = Bugged <$> shrink r
  
  main :: IO ()
  main = do
    sample (arbitrary :: Gen R)
    let prop_nameNullFree r = all (/= '\NUL') (unpack (name r))
        prop_idAlpha r = all isAlphaNum (unpack (id_ r))
        qc prop = quickCheckWith stdArgs{maxSuccess = 1000} prop
    qc prop_nameNullFree
    qc prop_idAlpha
    qc $ expectFailure $ \(Bugged r) -> prop_nameNullFree r
    qc $ expectFailure $ \(Bugged r) -> prop_idAlpha r
  