content: {-# LANGUAGE CPP #-}
  
  module Grisette.Internal.Core.Data.Class.Concrete (Concrete) where
  
  #if MIN_VERSION_base(4,16,0)
  import Data.Bits (And, Iff, Ior, Xor)
  import Data.Tuple (Solo)
  #endif
  
  import Control.Monad.Identity (Identity)
  import Data.Complex (Complex)
  import Data.Functor.Compose (Compose)
  import qualified Data.Functor.Product as Functor
  import qualified Data.Functor.Sum as Functor
  import Data.Int (Int16, Int32, Int64, Int8)
  import Data.List.NonEmpty (NonEmpty)
  import Data.Monoid (All, Any, Dual, First, Last, Product, Sum)
  import Data.Ord (Down)
  import Data.Ratio (Ratio)
  import Data.Semigroup (Max, Min)
  import qualified Data.Text as T
  import qualified Data.Text.Lazy as TL
  import Data.Void (Void)
  import Data.Word (Word16, Word32, Word64, Word8)
  import GHC.Natural (Natural)
  
  -- | A tag for concrete types.
  --
  -- Can be used in code to constrain types to concrete ones.
  -- For example, when trying to support hash maps in Grisette, we may want to
  -- restrict the key type to be concrete. The 'Concrete' type class is handy.
  class Concrete a
  
  instance Concrete Void
  
  instance Concrete All
  
  instance Concrete Any
  
  instance Concrete Int
  
  instance Concrete Int8
  
  instance Concrete Int16
  
  instance Concrete Int32
  
  instance Concrete Int64
  
  instance Concrete Integer
  
  instance Concrete Natural
  
  instance Concrete Word
  
  instance Concrete Word8
  
  instance Concrete Word16
  
  instance Concrete Word32
  
  instance Concrete Word64
  
  instance Concrete Float
  
  instance Concrete Double
  
  instance Concrete Char
  
  instance Concrete Bool
  
  instance (Concrete a) => Concrete (Maybe a)
  
  instance (Concrete a, Concrete b) => Concrete (Either a b)
  
  instance (Concrete a) => Concrete [a]
  
  instance (Concrete a, Concrete b) => Concrete (a, b)
  
  instance (Concrete a, Concrete b, Concrete c) => Concrete (a, b, c)
  
  instance
    (Concrete a, Concrete b, Concrete c, Concrete d) =>
    Concrete (a, b, c, d)
  
  instance
    (Concrete a, Concrete b, Concrete c, Concrete d, Concrete e) =>
    Concrete (a, b, c, d, e)
  
  instance
    ( Concrete a,
      Concrete b,
      Concrete c,
      Concrete d,
      Concrete e,
      Concrete f
    ) =>
    Concrete (a, b, c, d, e, f)
  
  instance
    ( Concrete a,
      Concrete b,
      Concrete c,
      Concrete d,
      Concrete e,
      Concrete f,
      Concrete g
    ) =>
    Concrete (a, b, c, d, e, f, g)
  
  instance
    ( Concrete a,
      Concrete b,
      Concrete c,
      Concrete d,
      Concrete e,
      Concrete f,
      Concrete g,
      Concrete h
    ) =>
    Concrete (a, b, c, d, e, f, g, h)
  
  instance
    ( Concrete a,
      Concrete b,
      Concrete c,
      Concrete d,
      Concrete e,
      Concrete f,
      Concrete g,
      Concrete h,
      Concrete i
    ) =>
    Concrete (a, b, c, d, e, f, g, h, i)
  
  instance
    ( Concrete a,
      Concrete b,
      Concrete c,
      Concrete d,
      Concrete e,
      Concrete f,
      Concrete g,
      Concrete h,
      Concrete i,
      Concrete j
    ) =>
    Concrete (a, b, c, d, e, f, g, h, i, j)
  
  instance
    ( Concrete a,
      Concrete b,
      Concrete c,
      Concrete d,
      Concrete e,
      Concrete f,
      Concrete g,
      Concrete h,
      Concrete i,
      Concrete j,
      Concrete k
    ) =>
    Concrete (a, b, c, d, e, f, g, h, i, j, k)
  
  instance (Concrete a) => Concrete (Complex a)
  
  instance (Concrete a) => Concrete (Ratio a)
  
  instance (Concrete a) => Concrete (First a)
  
  instance (Concrete a) => Concrete (Last a)
  
  instance (Concrete a) => Concrete (Min a)
  
  instance (Concrete a) => Concrete (Max a)
  
  instance (Concrete a) => Concrete (NonEmpty a)
  
  #if MIN_VERSION_base(4,16,0)
  instance (Concrete a) => Concrete (And a)
  
  instance (Concrete a) => Concrete (Iff a)
  
  instance (Concrete a) => Concrete (Ior a)
  
  instance (Concrete a) => Concrete (Xor a)
  #endif
  
  instance (Concrete a) => Concrete (Identity a)
  
  instance (Concrete a) => Concrete (Down a)
  
  instance (Concrete a) => Concrete (Dual a)
  
  instance (Concrete a) => Concrete (Sum a)
  
  instance (Concrete a) => Concrete (Product a)
  
  #if MIN_VERSION_base(4,16,0)
  instance (Concrete a) => Concrete (Solo a)
  #endif
  
  instance (Concrete (f a), Concrete (g a)) => Concrete (Functor.Product f g a)
  
  instance (Concrete (f a), Concrete (g a)) => Concrete (Functor.Sum f g a)
  
  instance (Concrete (f (g a))) => Concrete (Compose f g a)
  
  instance Concrete T.Text
  
  instance Concrete TL.Text
  