content: -- `PolyKinds` ensures the derived HasRep instances are fully polymorphic. In future, we could try
  -- to make this explicit in `deriveHasRep`.
  {-# LANGUAGE PolyKinds #-}
  {-# LANGUAGE TemplateHaskell #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# OPTIONS_GHC -Wno-orphans #-}
  
  -- | The only module that should be needed by code that is in the dependency graph of calls to
  --  `Categorifier.Categorify.expression`. If the module actually /calls/
  --  `Categorifier.Categorify.expression`, then it will also need to
  --   @import qualified "Categorifier.Categorify" as Categorify@.
  module Categorifier.Client
    ( HasRep (..),
      Rep,
      deriveHasRep,
  
      -- * testing
      abstReturn,
      reprReturn,
    )
  where
  
  import Categorifier.Client.Internal (HasRep (..), Rep, deriveHasRep)
  import Data.Complex (Complex)
  import Data.Functor.Compose (Compose)
  import Data.Functor.Identity (Identity)
  import qualified Data.Functor.Product as Functor
  import qualified Data.Functor.Sum as Functor
  import Data.List.NonEmpty (NonEmpty)
  import Data.Proxy (Proxy (..))
  import Data.Ratio (Ratio)
  import qualified Data.Semigroup as Semigroup
  import qualified GHC.Generics as Generic
  
  -- | This property should be true for every `HasRep` instance. `r` should be a classifying object,
  --   and the first argument a comparison (e.g., `Bool` and `==` or `Hedgehog.Property` and
  --  `Hedgehog.===`) to make it easy to test.
  abstReturn :: forall a r. (HasRep a) => Proxy a -> (Rep a -> Rep a -> r) -> Rep a -> r
  abstReturn Proxy eq = eq <$> id <*> repr . abst @a
  
  -- | This property should be true for every `HasRep` instance. `r` should be a classifying object,
  --   and the first argument a comparison (e.g., `Bool` and `==` or `Hedgehog.Property` and
  --  `Hedgehog.===`) to make it easy to test.
  reprReturn :: (HasRep a) => (a -> a -> r) -> a -> r
  reprReturn eq = eq <$> id <*> abst . repr
  
  deriveHasRep ''[]
  deriveHasRep ''(,,)
  deriveHasRep ''(,,,)
  deriveHasRep ''(,,,,)
  deriveHasRep ''(,,,,,)
  deriveHasRep ''(,,,,,,)
  deriveHasRep ''(,,,,,,,)
  deriveHasRep ''(,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''(,,,,,,,,,,,,,,,,,,,,,,,,,,)
  deriveHasRep ''Complex
  deriveHasRep ''Compose
  deriveHasRep ''Functor.Product
  deriveHasRep ''Functor.Sum
  deriveHasRep ''(Generic.:+:)
  deriveHasRep ''(Generic.:*:)
  deriveHasRep ''(Generic.:.:)
  deriveHasRep ''Generic.K1
  deriveHasRep ''Generic.M1
  deriveHasRep ''Generic.Par1
  deriveHasRep ''Generic.U1
  deriveHasRep ''Identity
  deriveHasRep ''Maybe
  deriveHasRep ''NonEmpty
  deriveHasRep ''Ordering
  deriveHasRep ''Proxy
  deriveHasRep ''Ratio
  deriveHasRep ''Semigroup.All
  deriveHasRep ''Semigroup.Any
  deriveHasRep ''Semigroup.Dual
  deriveHasRep ''Semigroup.Endo
  deriveHasRep ''Semigroup.Max
  deriveHasRep ''Semigroup.Min
  deriveHasRep ''Semigroup.Product
  deriveHasRep ''Semigroup.Sum
  