    {-# LANGUAGE PolyKinds #-}
    {-# LANGUAGE UndecidableInstances #-}
    {-# LANGUAGE UndecidableSuperClasses #-}
    -- | Type-level metadata
    --
    -- This module provides datatypes (to be used promoted) that can represent the
    -- metadata of Haskell datatypes on the type level.
    --
    -- We do not reuse the term-level metadata types, because these are GADTs that
    -- incorporate additional invariants. We could (at least in GHC 8) impose the
    -- same invariants on the type level as well, but some tests have revealed that
    -- the resulting type are rather inconvenient to work with.
    --
    -- So we use simple datatypes to represent the type-level metadata, even if
    -- this means that some invariants are not explicitly captured.
    --
    -- We establish a relation between the term- and type-level versions of the
    -- metadata by automatically computing the term-level version from the type-level
    -- version.
    --
    -- As we now have two versions of metadata (term-level and type-level)
    -- with very similar, yet slightly different datatype definitions, the names
    -- between the modules clash, and this module is recommended to be imported
    -- qualified when needed.
    --
    -- The interface exported by this module is still somewhat experimental.
    --
    -- @since 0.3.0.0
    --
    module Generics.SOP.Type.Metadata
      ( module Generics.SOP.Type.Metadata
        -- * re-exports
      , Associativity(..)
      ) where

    #if __GLASGOW_HASKELL__ <802
    import Data.Kind (Type)
    #endif
    import Data.Proxy (Proxy (..))
    import GHC.Generics
      ( Associativity(..)
      , DecidedStrictness(..)
      , SourceStrictness(..)
      , SourceUnpackedness(..)
      )
    import GHC.Types
    import GHC.TypeLits

    import qualified Generics.SOP.Metadata as M
    import Generics.SOP.NP
    import Generics.SOP.Sing

    -- Regarding the CPP in the datatype definitions below:
    --
    -- We cannot promote type synonyms in GHC 7, so we
    -- use equivalent yet less descriptive definitions
    -- for the older GHCs.

    -- | Metadata for a datatype (to be used promoted).
    --
    -- A type of kind @'DatatypeInfo'@ contains meta-information about a datatype
    -- that is not contained in its code. This information consists
    -- primarily of the names of the datatype, its constructors, and possibly its
    -- record selectors.
    --
    -- The constructor indicates whether the datatype has been declared using @newtype@
    -- or not.
    --
    -- @since 0.3.0.0
    --
    data DatatypeInfo =
        ADT ModuleName DatatypeName [ConstructorInfo] [[StrictnessInfo]]
        -- ^ Standard algebraic datatype
      | Newtype ModuleName DatatypeName ConstructorInfo
        -- ^ Newtype

    -- | Metadata for a single constructors (to be used promoted).
    --
    -- @since 0.3.0.0
    --
    data ConstructorInfo =
        Constructor ConstructorName
        -- ^ Normal constructor
      | Infix ConstructorName Associativity Fixity
        -- ^ Infix constructor
      | Record ConstructorName [FieldInfo]
        -- ^ Record constructor

    -- | Strictness information for a single field (to be used promoted).
    --
    -- @since 0.4.0.0
    --
    data StrictnessInfo =
        StrictnessInfo SourceUnpackedness SourceStrictness DecidedStrictness

    -- | Metadata for a single record field (to be used promoted).
    --
    -- @since 0.3.0.0
    --
    data FieldInfo =
        FieldInfo FieldName

    -- | The name of a datatype.
    type DatatypeName    = Symbol

    -- | The name of a module.
    type ModuleName      = Symbol

    -- | The name of a data constructor.
    type ConstructorName = Symbol

    -- | The name of a field / record selector.
    type FieldName       = Symbol

    -- | The fixity of an infix constructor.
    type Fixity          = Nat

    -- Demotion
    --
    -- The following classes are concerned with computing the
    -- term-level metadata from the type-level metadata.

    -- | Class for computing term-level datatype information from
    -- type-level datatype information.
    --
    -- @since 0.3.0.0
    --
    class DemoteDatatypeInfo (x :: DatatypeInfo) (xss :: [[Type]]) where
      -- | Given a proxy of some type-level datatype information,
      -- return the corresponding term-level information.
      --
      -- @since 0.3.0.0
      --
      demoteDatatypeInfo :: proxy x -> M.DatatypeInfo xss

    instance
         ( KnownSymbol m
         , KnownSymbol d
         , DemoteConstructorInfos cs xss
         , DemoteStrictnessInfoss sss xss
         )
      => DemoteDatatypeInfo ('ADT m d cs sss) xss where
      demoteDatatypeInfo :: forall (proxy :: DatatypeInfo -> *).
    proxy ('ADT m d cs sss) -> DatatypeInfo xss
    demoteDatatypeInfo proxy ('ADT m d cs sss)
    _ =
        ModuleName
    -> ModuleName
    -> NP ConstructorInfo xss
    -> POP StrictnessInfo xss
    -> DatatypeInfo xss
    forall (a :: [[*]]).
    ModuleName
    -> ModuleName
    -> NP ConstructorInfo a
    -> POP StrictnessInfo a
    -> DatatypeInfo a
    M.ADT
          (Proxy m -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy m
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy m))
          (Proxy d -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy d
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy d))
          (Proxy cs -> NP ConstructorInfo xss
    forall (cs :: [ConstructorInfo]) (xss :: [[*]])
           (proxy :: [ConstructorInfo] -> *).
    DemoteConstructorInfos cs xss =>
    proxy cs -> NP ConstructorInfo xss
    forall (proxy :: [ConstructorInfo] -> *).
    proxy cs -> NP ConstructorInfo xss
    demoteConstructorInfos (Proxy cs
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy cs))
          (NP (NP StrictnessInfo) xss -> POP StrictnessInfo xss
    forall k (f :: k -> *) (xss :: [[k]]). NP (NP f) xss -> POP f xss
    POP (Proxy sss -> NP (NP StrictnessInfo) xss
    forall (sss :: [[StrictnessInfo]]) (xss :: [[*]])
           (proxy :: [[StrictnessInfo]] -> *).
    DemoteStrictnessInfoss sss xss =>
    proxy sss -> NP (NP StrictnessInfo) xss
    forall (proxy :: [[StrictnessInfo]] -> *).
    proxy sss -> NP (NP StrictnessInfo) xss
    demoteStrictnessInfoss (Proxy sss
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy sss)))

    instance
         (KnownSymbol m, KnownSymbol d, DemoteConstructorInfo c '[ x ])
      => DemoteDatatypeInfo ('Newtype m d c) '[ '[ x ] ] where
      demoteDatatypeInfo :: forall (proxy :: DatatypeInfo -> *).
    proxy ('Newtype m d c) -> DatatypeInfo '[ '[x]]
    demoteDatatypeInfo proxy ('Newtype m d c)
    _ =
        ModuleName
    -> ModuleName -> ConstructorInfo '[x] -> DatatypeInfo '[ '[x]]
    forall x.
    ModuleName
    -> ModuleName -> ConstructorInfo '[x] -> DatatypeInfo '[ '[x]]
    M.Newtype
          (Proxy m -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy m
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy m))
          (Proxy d -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy d
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy d))
          (Proxy c -> ConstructorInfo '[x]
    forall (x :: ConstructorInfo) (xs :: [*])
           (proxy :: ConstructorInfo -> *).
    DemoteConstructorInfo x xs =>
    proxy x -> ConstructorInfo xs
    forall (proxy :: ConstructorInfo -> *).
    proxy c -> ConstructorInfo '[x]
    demoteConstructorInfo (Proxy c
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy c))

    -- | Class for computing term-level constructor information from
    -- type-level constructor information.
    --
    -- @since 0.3.0.0
    --
    class DemoteConstructorInfos (cs :: [ConstructorInfo]) (xss :: [[Type]]) where
      -- | Given a proxy of some type-level constructor information,
      -- return the corresponding term-level information as a product.
      --
      -- @since 0.3.0.0
      --
      demoteConstructorInfos :: proxy cs -> NP M.ConstructorInfo xss

    instance DemoteConstructorInfos '[] '[] where
      demoteConstructorInfos :: forall (proxy :: [ConstructorInfo] -> *).
    proxy '[] -> NP ConstructorInfo '[]
    demoteConstructorInfos proxy '[]
    _ = NP ConstructorInfo '[]
    forall {k} (a :: k -> *). NP a '[]
    Nil

    instance
         (DemoteConstructorInfo c xs, DemoteConstructorInfos cs xss)
      => DemoteConstructorInfos (c ': cs) (xs ': xss) where
      demoteConstructorInfos :: forall (proxy :: [ConstructorInfo] -> *).
    proxy (c : cs) -> NP ConstructorInfo (xs : xss)
    demoteConstructorInfos proxy (c : cs)
    _ =
        Proxy c -> ConstructorInfo xs
    forall (x :: ConstructorInfo) (xs :: [*])
           (proxy :: ConstructorInfo -> *).
    DemoteConstructorInfo x xs =>
    proxy x -> ConstructorInfo xs
    forall (proxy :: ConstructorInfo -> *).
    proxy c -> ConstructorInfo xs
    demoteConstructorInfo (Proxy c
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy c) ConstructorInfo xs
    -> NP ConstructorInfo xss -> NP ConstructorInfo (xs : xss)
    forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
    a x -> NP a xs -> NP a (x : xs)
    :* Proxy cs -> NP ConstructorInfo xss
    forall (cs :: [ConstructorInfo]) (xss :: [[*]])
           (proxy :: [ConstructorInfo] -> *).
    DemoteConstructorInfos cs xss =>
    proxy cs -> NP ConstructorInfo xss
    forall (proxy :: [ConstructorInfo] -> *).
    proxy cs -> NP ConstructorInfo xss
    demoteConstructorInfos (Proxy cs
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy cs)

    -- | Class for computing term-level constructor information from
    -- type-level constructor information.
    --
    -- @since 0.3.0.0
    --
    class DemoteConstructorInfo (x :: ConstructorInfo) (xs :: [Type]) where
      -- | Given a proxy of some type-level constructor information,
      -- return the corresponding term-level information.
      --
      -- @since 0.3.0.0
      --
      demoteConstructorInfo :: proxy x -> M.ConstructorInfo xs

    instance (KnownSymbol s, SListI xs) => DemoteConstructorInfo ('Constructor s) xs where
      demoteConstructorInfo :: forall (proxy :: ConstructorInfo -> *).
    proxy ('Constructor s) -> ConstructorInfo xs
    demoteConstructorInfo proxy ('Constructor s)
    _ = ModuleName -> ConstructorInfo xs
    forall (a :: [*]). SListI a => ModuleName -> ConstructorInfo a
    M.Constructor (Proxy s -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy s
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy s))

    instance
         (KnownSymbol s, DemoteAssociativity a, KnownNat f)
      => DemoteConstructorInfo ('Infix s a f) [y, z] where
      demoteConstructorInfo :: forall (proxy :: ConstructorInfo -> *).
    proxy ('Infix s a f) -> ConstructorInfo '[y, z]
    demoteConstructorInfo proxy ('Infix s a f)
    _ =
        ModuleName -> Associativity -> Fixity -> ConstructorInfo '[y, z]
    forall x y.
    ModuleName -> Associativity -> Fixity -> ConstructorInfo '[x, y]
    M.Infix
          (Proxy s -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy s
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy s))
          (Proxy a -> Associativity
    forall (a :: Associativity) (proxy :: Associativity -> *).
    DemoteAssociativity a =>
    proxy a -> Associativity
    forall (proxy :: Associativity -> *). proxy a -> Associativity
    demoteAssociativity (Proxy a
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy a))
          (Integer -> Fixity
    forall a. Num a => Integer -> a
    fromInteger (Proxy f -> Integer
    forall (n :: Nat) (proxy :: Nat -> *).
    KnownNat n =>
    proxy n -> Integer
    natVal (Proxy f
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy f)))

    instance (KnownSymbol s, DemoteFieldInfos fs xs) => DemoteConstructorInfo ('Record s fs) xs where
      demoteConstructorInfo :: forall (proxy :: ConstructorInfo -> *).
    proxy ('Record s fs) -> ConstructorInfo xs
    demoteConstructorInfo proxy ('Record s fs)
    _ =
        ModuleName -> NP FieldInfo xs -> ConstructorInfo xs
    forall (a :: [*]).
    SListI a =>
    ModuleName -> NP FieldInfo a -> ConstructorInfo a
    M.Record (Proxy s -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy s
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy s)) (Proxy fs -> NP FieldInfo xs
    forall (fs :: [FieldInfo]) (xs :: [*]) (proxy :: [FieldInfo] -> *).
    DemoteFieldInfos fs xs =>
    proxy fs -> NP FieldInfo xs
    forall (proxy :: [FieldInfo] -> *). proxy fs -> NP FieldInfo xs
    demoteFieldInfos (Proxy fs
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy fs))

    class DemoteStrictnessInfoss (sss :: [[StrictnessInfo]]) (xss :: [[Type]]) where
      demoteStrictnessInfoss :: proxy sss -> NP (NP M.StrictnessInfo) xss

    instance DemoteStrictnessInfoss '[] '[] where
      demoteStrictnessInfoss :: forall (proxy :: [[StrictnessInfo]] -> *).
    proxy '[] -> NP (NP StrictnessInfo) '[]
    demoteStrictnessInfoss proxy '[]
    _ = NP (NP StrictnessInfo) '[]
    forall {k} (a :: k -> *). NP a '[]
    Nil

    instance
         (DemoteStrictnessInfos ss xs, DemoteStrictnessInfoss sss xss)
      => DemoteStrictnessInfoss (ss ': sss) (xs ': xss) where
      demoteStrictnessInfoss :: forall (proxy :: [[StrictnessInfo]] -> *).
    proxy (ss : sss) -> NP (NP StrictnessInfo) (xs : xss)
    demoteStrictnessInfoss proxy (ss : sss)
    _ =
           Proxy ss -> NP StrictnessInfo xs
    forall (ss :: [StrictnessInfo]) (xs :: [*])
           (proxy :: [StrictnessInfo] -> *).
    DemoteStrictnessInfos ss xs =>
    proxy ss -> NP StrictnessInfo xs
    forall (proxy :: [StrictnessInfo] -> *).
    proxy ss -> NP StrictnessInfo xs
    demoteStrictnessInfos  (Proxy ss
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy ss )
        NP StrictnessInfo xs
    -> NP (NP StrictnessInfo) xss -> NP (NP StrictnessInfo) (xs : xss)
    forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
    a x -> NP a xs -> NP a (x : xs)
    :* Proxy sss -> NP (NP StrictnessInfo) xss
    forall (sss :: [[StrictnessInfo]]) (xss :: [[*]])
           (proxy :: [[StrictnessInfo]] -> *).
    DemoteStrictnessInfoss sss xss =>
    proxy sss -> NP (NP StrictnessInfo) xss
    forall (proxy :: [[StrictnessInfo]] -> *).
    proxy sss -> NP (NP StrictnessInfo) xss
    demoteStrictnessInfoss (Proxy sss
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy sss)

    class DemoteStrictnessInfos (ss :: [StrictnessInfo]) (xs :: [Type]) where
      demoteStrictnessInfos :: proxy ss -> NP M.StrictnessInfo xs

    instance DemoteStrictnessInfos '[] '[] where
      demoteStrictnessInfos :: forall (proxy :: [StrictnessInfo] -> *).
    proxy '[] -> NP StrictnessInfo '[]
    demoteStrictnessInfos proxy '[]
    _ = NP StrictnessInfo '[]
    forall {k} (a :: k -> *). NP a '[]
    Nil

    instance
         (DemoteStrictnessInfo s x, DemoteStrictnessInfos ss xs)
      => DemoteStrictnessInfos (s ': ss) (x ': xs) where
      demoteStrictnessInfos :: forall (proxy :: [StrictnessInfo] -> *).
    proxy (s : ss) -> NP StrictnessInfo (x : xs)
    demoteStrictnessInfos proxy (s : ss)
    _ =
           Proxy s -> StrictnessInfo x
    forall (s :: StrictnessInfo) x (proxy :: StrictnessInfo -> *).
    DemoteStrictnessInfo s x =>
    proxy s -> StrictnessInfo x
    forall (proxy :: StrictnessInfo -> *). proxy s -> StrictnessInfo x
    demoteStrictnessInfo  (Proxy s
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy s )
        StrictnessInfo x
    -> NP StrictnessInfo xs -> NP StrictnessInfo (x : xs)
    forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
    a x -> NP a xs -> NP a (x : xs)
    :* Proxy ss -> NP StrictnessInfo xs
    forall (ss :: [StrictnessInfo]) (xs :: [*])
           (proxy :: [StrictnessInfo] -> *).
    DemoteStrictnessInfos ss xs =>
    proxy ss -> NP StrictnessInfo xs
    forall (proxy :: [StrictnessInfo] -> *).
    proxy ss -> NP StrictnessInfo xs
    demoteStrictnessInfos (Proxy ss
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy ss)

    class DemoteStrictnessInfo (s :: StrictnessInfo) (x :: Type) where
      demoteStrictnessInfo :: proxy s -> M.StrictnessInfo x

    instance
         ( DemoteSourceUnpackedness su
         , DemoteSourceStrictness   ss
         , DemoteDecidedStrictness  ds
         )
      => DemoteStrictnessInfo ('StrictnessInfo su ss ds) x where
      demoteStrictnessInfo :: forall (proxy :: StrictnessInfo -> *).
    proxy ('StrictnessInfo su ss ds) -> StrictnessInfo x
    demoteStrictnessInfo proxy ('StrictnessInfo su ss ds)
    _ =
        SourceUnpackedness
    -> SourceStrictness -> DecidedStrictness -> StrictnessInfo x
    forall a.
    SourceUnpackedness
    -> SourceStrictness -> DecidedStrictness -> StrictnessInfo a
    M.StrictnessInfo
          (Proxy su -> SourceUnpackedness
    forall (a :: SourceUnpackedness)
           (proxy :: SourceUnpackedness -> *).
    DemoteSourceUnpackedness a =>
    proxy a -> SourceUnpackedness
    forall (proxy :: SourceUnpackedness -> *).
    proxy su -> SourceUnpackedness
    demoteSourceUnpackedness (Proxy su
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy su))
          (Proxy ss -> SourceStrictness
    forall (a :: SourceStrictness) (proxy :: SourceStrictness -> *).
    DemoteSourceStrictness a =>
    proxy a -> SourceStrictness
    forall (proxy :: SourceStrictness -> *).
    proxy ss -> SourceStrictness
    demoteSourceStrictness   (Proxy ss
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy ss))
          (Proxy ds -> DecidedStrictness
    forall (a :: DecidedStrictness) (proxy :: DecidedStrictness -> *).
    DemoteDecidedStrictness a =>
    proxy a -> DecidedStrictness
    forall (proxy :: DecidedStrictness -> *).
    proxy ds -> DecidedStrictness
    demoteDecidedStrictness  (Proxy ds
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy ds))

    -- | Class for computing term-level field information from
    -- type-level field information.
    --
    -- @since 0.3.0.0
    --
    class SListI xs => DemoteFieldInfos (fs :: [FieldInfo]) (xs :: [Type]) where
      -- | Given a proxy of some type-level field information,
      -- return the corresponding term-level information as a product.
      --
      -- @since 0.3.0.0
      --
      demoteFieldInfos :: proxy fs -> NP M.FieldInfo xs

    instance DemoteFieldInfos '[] '[] where
      demoteFieldInfos :: forall (proxy :: [FieldInfo] -> *). proxy '[] -> NP FieldInfo '[]
    demoteFieldInfos proxy '[]
    _ = NP FieldInfo '[]
    forall {k} (a :: k -> *). NP a '[]
    Nil

    instance
         (DemoteFieldInfo f x, DemoteFieldInfos fs xs)
      => DemoteFieldInfos (f ': fs) (x ': xs) where
      demoteFieldInfos :: forall (proxy :: [FieldInfo] -> *).
    proxy (f : fs) -> NP FieldInfo (x : xs)
    demoteFieldInfos proxy (f : fs)
    _ = Proxy f -> FieldInfo x
    forall (x :: FieldInfo) a (proxy :: FieldInfo -> *).
    DemoteFieldInfo x a =>
    proxy x -> FieldInfo a
    forall (proxy :: FieldInfo -> *). proxy f -> FieldInfo x
    demoteFieldInfo (Proxy f
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy f) FieldInfo x -> NP FieldInfo xs -> NP FieldInfo (x : xs)
    forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
    a x -> NP a xs -> NP a (x : xs)
    :* Proxy fs -> NP FieldInfo xs
    forall (fs :: [FieldInfo]) (xs :: [*]) (proxy :: [FieldInfo] -> *).
    DemoteFieldInfos fs xs =>
    proxy fs -> NP FieldInfo xs
    forall (proxy :: [FieldInfo] -> *). proxy fs -> NP FieldInfo xs
    demoteFieldInfos (Proxy fs
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy fs)

    -- | Class for computing term-level field information from
    -- type-level field information.
    --
    -- @since 0.3.0.0
    --
    class DemoteFieldInfo (x :: FieldInfo) (a :: Type) where
      -- | Given a proxy of some type-level field information,
      -- return the corresponding term-level information.
      --
      -- @since 0.3.0.0
      --
      demoteFieldInfo :: proxy x -> M.FieldInfo a

    instance KnownSymbol s => DemoteFieldInfo ('FieldInfo s) a where
      demoteFieldInfo :: forall (proxy :: FieldInfo -> *).
    proxy ('FieldInfo s) -> FieldInfo a
    demoteFieldInfo proxy ('FieldInfo s)
    _ = ModuleName -> FieldInfo a
    forall a. ModuleName -> FieldInfo a
    M.FieldInfo (Proxy s -> ModuleName
    forall (n :: Symbol) (proxy :: Symbol -> *).
    KnownSymbol n =>
    proxy n -> ModuleName
    symbolVal (Proxy s
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy s))

    -- | Class for computing term-level associativity information
    -- from type-level associativity information.
    --
    -- @since 0.3.0.0
    --
    class DemoteAssociativity (a :: Associativity) where
      -- | Given a proxy of some type-level associativity information,
      -- return the corresponding term-level information.
      --
      -- @since 0.3.0.0
      --
      demoteAssociativity :: proxy a -> M.Associativity

    instance DemoteAssociativity 'LeftAssociative where
      demoteAssociativity :: forall (proxy :: Associativity -> *).
    proxy 'LeftAssociative -> Associativity
    demoteAssociativity proxy 'LeftAssociative
    _ = Associativity
    M.LeftAssociative

    instance DemoteAssociativity 'RightAssociative where
      demoteAssociativity :: forall (proxy :: Associativity -> *).
    proxy 'RightAssociative -> Associativity
    demoteAssociativity proxy 'RightAssociative
    _ = Associativity
    M.RightAssociative

    instance DemoteAssociativity 'NotAssociative where
      demoteAssociativity :: forall (proxy :: Associativity -> *).
    proxy 'NotAssociative -> Associativity
    demoteAssociativity proxy 'NotAssociative
    _ = Associativity
    M.NotAssociative

    -- | Class for computing term-level source unpackedness information
    -- from type-level source unpackedness information.
    --
    -- @since 0.4.0.0
    --
    class DemoteSourceUnpackedness (a :: SourceUnpackedness) where
      -- | Given a proxy of some type-level source unpackedness information,
      -- return the corresponding term-level information.
      --
      -- @since 0.4.0.0
      --
      demoteSourceUnpackedness :: proxy a -> M.SourceUnpackedness

    instance DemoteSourceUnpackedness 'NoSourceUnpackedness where
      demoteSourceUnpackedness :: forall (proxy :: SourceUnpackedness -> *).
    proxy 'NoSourceUnpackedness -> SourceUnpackedness
    demoteSourceUnpackedness proxy 'NoSourceUnpackedness
    _ = SourceUnpackedness
    M.NoSourceUnpackedness

    instance DemoteSourceUnpackedness 'SourceNoUnpack where
      demoteSourceUnpackedness :: forall (proxy :: SourceUnpackedness -> *).
    proxy 'SourceNoUnpack -> SourceUnpackedness
    demoteSourceUnpackedness proxy 'SourceNoUnpack
    _ = SourceUnpackedness
    M.SourceNoUnpack

    instance DemoteSourceUnpackedness 'SourceUnpack where
      demoteSourceUnpackedness :: forall (proxy :: SourceUnpackedness -> *).
    proxy 'SourceUnpack -> SourceUnpackedness
    demoteSourceUnpackedness proxy 'SourceUnpack
    _ = SourceUnpackedness
    M.SourceUnpack

    -- | Class for computing term-level source strictness information
    -- from type-level source strictness information.
    --
    -- @since 0.4.0.0
    --
    class DemoteSourceStrictness (a :: SourceStrictness) where
      -- | Given a proxy of some type-level source strictness information,
      -- return the corresponding term-level information.
      --
      -- @since 0.4.0.0
      --
      demoteSourceStrictness :: proxy a -> M.SourceStrictness

    instance DemoteSourceStrictness 'NoSourceStrictness where
      demoteSourceStrictness :: forall (proxy :: SourceStrictness -> *).
    proxy 'NoSourceStrictness -> SourceStrictness
    demoteSourceStrictness proxy 'NoSourceStrictness
    _ = SourceStrictness
    M.NoSourceStrictness

    instance DemoteSourceStrictness 'SourceLazy where
      demoteSourceStrictness :: forall (proxy :: SourceStrictness -> *).
    proxy 'SourceLazy -> SourceStrictness
    demoteSourceStrictness proxy 'SourceLazy
    _ = SourceStrictness
    M.SourceLazy

    instance DemoteSourceStrictness 'SourceStrict where
      demoteSourceStrictness :: forall (proxy :: SourceStrictness -> *).
    proxy 'SourceStrict -> SourceStrictness
    demoteSourceStrictness proxy 'SourceStrict
    _ = SourceStrictness
    M.SourceStrict

    -- | Class for computing term-level decided strictness information
    -- from type-level decided strictness information.
    --
    -- @since 0.4.0.0
    --
    class DemoteDecidedStrictness (a :: DecidedStrictness) where
      -- | Given a proxy of some type-level source strictness information,
      -- return the corresponding term-level information.
      --
      -- @since 0.4.0.0
      --
      demoteDecidedStrictness :: proxy a -> M.DecidedStrictness

    instance DemoteDecidedStrictness 'DecidedLazy where
      demoteDecidedStrictness :: forall (proxy :: DecidedStrictness -> *).
    proxy 'DecidedLazy -> DecidedStrictness
    demoteDecidedStrictness proxy 'DecidedLazy
    _ = DecidedStrictness
    M.DecidedLazy

    instance DemoteDecidedStrictness 'DecidedStrict where
      demoteDecidedStrictness :: forall (proxy :: DecidedStrictness -> *).
    proxy 'DecidedStrict -> DecidedStrictness
    demoteDecidedStrictness proxy 'DecidedStrict
    _ = DecidedStrictness
    M.DecidedStrict

    instance DemoteDecidedStrictness 'DecidedUnpack where
      demoteDecidedStrictness :: forall (proxy :: DecidedStrictness -> *).
    proxy 'DecidedUnpack -> DecidedStrictness
    demoteDecidedStrictness proxy 'DecidedUnpack
    _ = DecidedStrictness
    M.DecidedUnpack