content: {-# LANGUAGE TypeApplications, DeriveGeneric #-}
  
  import Codec.Winery
  import Data.List (intercalate)
  import Data.Proxy
  import GHC.Generics
  import Prettyprinter
  import Test.QuickCheck
  import qualified Test.QuickCheck.Gen as Gen
  
  data BigUnion = BU0 | BU1 | BU2 | BU3 | BU4 deriving (Show, Eq, Generic, Enum)
  instance Serialise BigUnion where
      bundleSerialise = bundleVia WineryVariant
  
  instance Arbitrary BigUnion where
    arbitrary = toEnum <$> Gen.choose (0, 4)
  
  data BigRecord = BigRecord
      { foo :: BigUnion
      , bar :: BigUnion
      , baz :: BigUnion
      , qux :: BigUnion
      } deriving (Show, Eq, Generic)
  
  instance Arbitrary BigRecord where
    arbitrary = BigRecord <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
  
  data BiggerRecord = BiggerRecord
      { union :: BigUnion
      , alpha :: BigRecord
      , bravo :: BigRecord
      } deriving (Show, Eq, Generic)
  
  instance Arbitrary BiggerRecord where
    arbitrary = BiggerRecord <$> arbitrary <*> arbitrary <*> arbitrary
  
  instance Serialise BigRecord where
      bundleSerialise = alterSchemaGen (withSchema @BigUnion)
          $ bundleVia WineryRecord
  
  instance Serialise BiggerRecord where
      bundleSerialise = alterSchemaGen (withSchema @BigUnion . withSchema @BigRecord)
          $ bundleVia WineryRecord
  
  main :: IO ()
  main = do
      let expected = intercalate "\n"
              [ "let BU0 | BU1 | BU2 | BU3 | BU4"
              , "  let { foo :: $0, bar :: $0, baz :: $0, qux :: $0 }"
              , "    { union :: $1, alpha :: $0, bravo :: $0 }"
              ]
      let actual = show $ pretty $ schema (Proxy @BiggerRecord)
      if expected == actual
          then quickCheck $ testSerialise @BiggerRecord
          else fail $ "Schema mismatch: \n" <> actual