    {-# LANGUAGE AllowAmbiguousTypes #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE StandaloneDeriving #-}
    {-# LANGUAGE TypeApplications #-}
    {-# LANGUAGE TypeOperators #-}

    -- | Generic deriving for 'Enum', 'Bounded' and 'Ix'.
    --
    -- === Warning
    --
    -- This is an internal module: it is not subject to any versioning policy,
    -- breaking changes can happen at any time.
    --
    -- If something here seems useful, please report it or create a pull request to
    -- export it from an external module.

    module Generic.Data.Internal.Enum where

    import GHC.Generics
    import Data.Ix

    -- | Generic 'toEnum' generated with the 'StandardEnum' option.
    --
    -- @
    -- instance 'Enum' MyType where
    --   'toEnum' = 'gtoEnum'
    --   'fromEnum' = 'gfromEnum'
    --   'enumFrom' = 'genumFrom'
    --   'enumFromThen' = 'genumFromThen'
    --   'enumFromTo' = 'genumFromTo'
    --   'enumFromThenTo' = 'genumFromThenTo'
    -- @
    gtoEnum :: (Generic a, GEnum StandardEnum (Rep a)) => Int -> a
    gtoEnum :: forall a. (Generic a, GEnum StandardEnum (Rep a)) => Int -> a
    gtoEnum = forall opts a.
    (Generic a, GEnum opts (Rep a)) =>
    String -> Int -> a
    gtoEnum' @StandardEnum String
    "gtoEnum"

    -- | Generic 'fromEnum' generated with the 'StandardEnum' option.
    --
    -- See also 'gtoEnum'.
    gfromEnum :: (Generic a, GEnum StandardEnum (Rep a)) => a -> Int
    gfromEnum :: forall a. (Generic a, GEnum StandardEnum (Rep a)) => a -> Int
    gfromEnum = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum' @StandardEnum

    -- | Generic 'enumFrom' generated with the 'StandardEnum' option.
    --
    -- See also 'gtoEnum'.
    genumFrom :: (Generic a, GEnum StandardEnum (Rep a)) => a -> [a]
    genumFrom :: forall a. (Generic a, GEnum StandardEnum (Rep a)) => a -> [a]
    genumFrom = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> [a]
    genumFrom' @StandardEnum

    -- | Generic 'enumFromThen' generated with the 'StandardEnum' option.
    --
    -- See also 'gtoEnum'.
    genumFromThen :: (Generic a, GEnum StandardEnum (Rep a)) => a -> a -> [a]
    genumFromThen :: forall a. (Generic a, GEnum StandardEnum (Rep a)) => a -> a -> [a]
    genumFromThen = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromThen' @StandardEnum

    -- | Generic 'enumFromTo' generated with the 'StandardEnum' option.
    --
    -- See also 'gtoEnum'.
    genumFromTo :: (Generic a, GEnum StandardEnum (Rep a)) => a -> a -> [a]
    genumFromTo :: forall a. (Generic a, GEnum StandardEnum (Rep a)) => a -> a -> [a]
    genumFromTo = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromTo' @StandardEnum

    -- | Generic 'enumFromThenTo' generated with the 'StandardEnum' option.
    --
    -- See also 'gtoEnum'.
    genumFromThenTo :: (Generic a, GEnum StandardEnum (Rep a)) => a -> a -> a -> [a]
    genumFromThenTo :: forall a.
    (Generic a, GEnum StandardEnum (Rep a)) =>
    a -> a -> a -> [a]
    genumFromThenTo = forall opts a.
    (Generic a, GEnum opts (Rep a)) =>
    a -> a -> a -> [a]
    genumFromThenTo' @StandardEnum

    -- | Generic 'toEnum' generated with the 'FiniteEnum' option.
    --
    -- @
    -- instance 'Enum' MyType where
    --   'toEnum' = 'gtoFiniteEnum'
    --   'fromEnum' = 'gfromFiniteEnum'
    --   'enumFrom' = 'gfiniteEnumFrom'
    --   'enumFromThen' = 'gfiniteEnumFromThen'
    --   'enumFromTo' = 'gfiniteEnumFromTo'
    --   'enumFromThenTo' = 'gfiniteEnumFromThenTo'
    -- @
    gtoFiniteEnum :: (Generic a, GEnum FiniteEnum (Rep a)) => Int -> a
    gtoFiniteEnum :: forall a. (Generic a, GEnum FiniteEnum (Rep a)) => Int -> a
    gtoFiniteEnum = forall opts a.
    (Generic a, GEnum opts (Rep a)) =>
    String -> Int -> a
    gtoEnum' @FiniteEnum String
    "gtoFiniteEnum"

    -- | Generic 'fromEnum' generated with the 'FiniteEnum' option.
    --
    -- See also 'gtoFiniteEnum'.
    gfromFiniteEnum :: (Generic a, GEnum FiniteEnum (Rep a)) => a -> Int
    gfromFiniteEnum :: forall a. (Generic a, GEnum FiniteEnum (Rep a)) => a -> Int
    gfromFiniteEnum = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum' @FiniteEnum

    -- | Generic 'enumFrom' generated with the 'FiniteEnum' option.
    --
    -- See also 'gtoFiniteEnum'.
    gfiniteEnumFrom :: (Generic a, GEnum FiniteEnum (Rep a)) => a -> [a]
    gfiniteEnumFrom :: forall a. (Generic a, GEnum FiniteEnum (Rep a)) => a -> [a]
    gfiniteEnumFrom = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> [a]
    genumFrom' @FiniteEnum

    -- | Generic 'enumFromThen' generated with the 'FiniteEnum' option.
    --
    -- See also 'gtoFiniteEnum'.
    gfiniteEnumFromThen :: (Generic a, GEnum FiniteEnum (Rep a)) => a -> a -> [a]
    gfiniteEnumFromThen :: forall a. (Generic a, GEnum FiniteEnum (Rep a)) => a -> a -> [a]
    gfiniteEnumFromThen = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromThen' @FiniteEnum

    -- | Generic 'enumFromTo' generated with the 'FiniteEnum' option.
    --
    -- See also 'gtoFiniteEnum'.
    gfiniteEnumFromTo :: (Generic a, GEnum FiniteEnum (Rep a)) => a -> a -> [a]
    gfiniteEnumFromTo :: forall a. (Generic a, GEnum FiniteEnum (Rep a)) => a -> a -> [a]
    gfiniteEnumFromTo = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromTo' @FiniteEnum

    -- | Generic 'enumFromThenTo' generated with the 'FiniteEnum' option.
    --
    -- See also 'gtoFiniteEnum'.
    gfiniteEnumFromThenTo :: (Generic a, GEnum FiniteEnum (Rep a)) => a -> a -> a -> [a]
    gfiniteEnumFromThenTo :: forall a.
    (Generic a, GEnum FiniteEnum (Rep a)) =>
    a -> a -> a -> [a]
    gfiniteEnumFromThenTo = forall opts a.
    (Generic a, GEnum opts (Rep a)) =>
    a -> a -> a -> [a]
    genumFromThenTo' @FiniteEnum

    -- | Unsafe generic 'toEnum'. Does not check whether the argument is within
    -- valid bounds. Use 'gtoEnum' or 'gtoFiniteEnum' instead.
    gtoEnumRaw' :: forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' :: forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' = Rep a (ZonkAny 6) -> a
    forall a x. Generic a => Rep a x -> a
    forall x. Rep a x -> a
    to (Rep a (ZonkAny 6) -> a) -> (Int -> Rep a (ZonkAny 6)) -> Int -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @opts

    -- | Generic 'toEnum'. Use 'gfromEnum' or 'gfromFiniteEnum' instead.
    gtoEnum' :: forall opts a. (Generic a, GEnum opts (Rep a)) => String -> Int -> a
    gtoEnum' :: forall opts a.
    (Generic a, GEnum opts (Rep a)) =>
    String -> Int -> a
    gtoEnum' String
    name Int
    n
      | Int
    0 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    n Bool -> Bool -> Bool
    && Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    card = forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' @opts Int
    n
      | Bool
    otherwise = String -> a
    forall a. HasCallStack => String -> a
    error (String -> a) -> String -> a
    forall a b. (a -> b) -> a -> b
    $
          String
    name String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ": out of bounds, index " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show Int
    n String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ", cardinality " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show Int
    card
      where
        card :: Int
    card = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @(Rep a)

    -- | Generic 'fromEnum'. Use 'gfromEnum' or 'gfromFiniteEnum' instead.
    gfromEnum' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum' = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @opts (Rep a (ZonkAny 5) -> Int) -> (a -> Rep a (ZonkAny 5)) -> a -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Rep a (ZonkAny 5)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from

    -- | > genumMin == gfromEnum gminBound
    genumMin :: Int
    genumMin :: Int
    genumMin = Int
    0

    -- | > genumMax == gfromEnum gmaxBound
    genumMax :: forall opts a. (Generic a, GEnum opts (Rep a)) => Int
    genumMax :: forall opts a. (Generic a, GEnum opts (Rep a)) => Int
    genumMax = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @(Rep a) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1

    -- | Generic 'enumFrom'. Use 'genumFrom' or 'gfiniteEnumFrom' instead.
    genumFrom' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> [a]
    genumFrom' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> [a]
    genumFrom' a
    x = (Int -> a) -> [Int] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> a
    toE [ Int
    i_x .. forall opts a. (Generic a, GEnum opts (Rep a)) => Int
    genumMax @opts @a ]
      where
        toE :: Int -> a
    toE = forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' @opts
        i_x :: Int
    i_x = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    x

    -- | Generic 'enumFromThen'. Use 'genumFromThen' or 'gfiniteEnumFromThen' instead.
    genumFromThen' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromThen' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromThen' a
    x1 a
    x2 = (Int -> a) -> [Int] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> a
    toE [ Int
    i_x1, Int
    i_x2 .. Int
    bound ]
      where
        toE :: Int -> a
    toE  = forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' @opts
        i_x1 :: Int
    i_x1 = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    x1
        i_x2 :: Int
    i_x2 = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    x2
        bound :: Int
    bound | Int
    i_x1 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    i_x2 = Int
    genumMin
              | Bool
    otherwise    = forall opts a. (Generic a, GEnum opts (Rep a)) => Int
    genumMax @opts @a

    -- | Generic 'enumFromTo'. Use 'genumFromTo' or 'gfiniteEnumFromTo' instead.
    genumFromTo' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromTo' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> [a]
    genumFromTo' a
    x a
    y = (Int -> a) -> [Int] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> a
    toE [ Int
    i_x .. Int
    i_y ]
      where
        toE :: Int -> a
    toE = forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' @opts
        i_x :: Int
    i_x = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    x
        i_y :: Int
    i_y = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    y

    -- | Generic 'enumFromThenTo'. Use 'genumFromThenTo' or 'gfiniteEnumFromThenTo' instead.
    genumFromThenTo' :: forall opts a. (Generic a, GEnum opts (Rep a)) => a -> a -> a -> [a]
    genumFromThenTo' :: forall opts a.
    (Generic a, GEnum opts (Rep a)) =>
    a -> a -> a -> [a]
    genumFromThenTo' a
    x1 a
    x2 a
    y = (Int -> a) -> [Int] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> a
    toE [ Int
    i_x1, Int
    i_x2 .. Int
    i_y ]
      where
        toE :: Int -> a
    toE  = forall opts a. (Generic a, GEnum opts (Rep a)) => Int -> a
    gtoEnumRaw' @opts
        i_x1 :: Int
    i_x1 = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    x1
        i_x2 :: Int
    i_x2 = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    x2
        i_y :: Int
    i_y  = forall opts a. (Generic a, GEnum opts (Rep a)) => a -> Int
    gfromEnum'  @opts a
    y

    -- | Generic 'minBound'.
    --
    -- @
    -- instance 'Bounded' MyType where
    --   'minBound' = 'gminBound'
    --   'maxBound' = 'gmaxBound'
    -- @
    gminBound :: (Generic a, GBounded (Rep a)) => a
    gminBound :: forall a. (Generic a, GBounded (Rep a)) => a
    gminBound = Rep a (ZonkAny 4) -> a
    forall a x. Generic a => Rep a x -> a
    forall x. Rep a x -> a
    to Rep a (ZonkAny 4)
    forall p. Rep a p
    forall (f :: * -> *) p. GBounded f => f p
    gMinBound

    -- | Generic 'maxBound'.
    --
    -- See also 'gminBound'.
    gmaxBound :: (Generic a, GBounded (Rep a)) => a
    gmaxBound :: forall a. (Generic a, GBounded (Rep a)) => a
    gmaxBound = Rep a (ZonkAny 3) -> a
    forall a x. Generic a => Rep a x -> a
    forall x. Rep a x -> a
    to Rep a (ZonkAny 3)
    forall p. Rep a p
    forall (f :: * -> *) p. GBounded f => f p
    gMaxBound

    -- | Generic 'range'.
    --
    -- @
    -- import "Data.Ix"
    -- instance 'Ix' MyType where
    --   'range' = 'grange'
    --   'index' = 'gindex'
    --   'inRange' = 'ginRange'
    -- @
    grange :: (Generic a, GIx (Rep a)) => (a, a) -> [a]
    grange :: forall a. (Generic a, GIx (Rep a)) => (a, a) -> [a]
    grange (a
    m, a
    n) = (Rep a (ZonkAny 2) -> a) -> [Rep a (ZonkAny 2)] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map Rep a (ZonkAny 2) -> a
    forall a x. Generic a => Rep a x -> a
    forall x. Rep a x -> a
    to ([Rep a (ZonkAny 2)] -> [a]) -> [Rep a (ZonkAny 2)] -> [a]
    forall a b. (a -> b) -> a -> b
    $ (Rep a (ZonkAny 2), Rep a (ZonkAny 2)) -> [Rep a (ZonkAny 2)]
    forall p. (Rep a p, Rep a p) -> [Rep a p]
    forall (f :: * -> *) p. GIx f => (f p, f p) -> [f p]
    gRange (a -> Rep a (ZonkAny 2)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    m, a -> Rep a (ZonkAny 2)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    n)

    -- | Generic 'index'.
    --
    -- See also 'grange'.
    gindex :: (Generic a, GIx (Rep a)) => (a, a) -> a -> Int
    gindex :: forall a. (Generic a, GIx (Rep a)) => (a, a) -> a -> Int
    gindex (a, a)
    b a
    i
      | (a, a) -> a -> Bool
    forall a. (Generic a, GIx (Rep a)) => (a, a) -> a -> Bool
    ginRange (a, a)
    b a
    i = (a, a) -> a -> Int
    forall a. (Generic a, GIx (Rep a)) => (a, a) -> a -> Int
    gunsafeIndex (a, a)
    b a
    i
      | Bool
    otherwise = String -> Int
    forall a. String -> a
    errorWithoutStackTrace String
    "gindex: out of bounds"

    -- | Generic @unsafeIndex@.
    --
    -- === __Details__
    --
    -- The functions @unsafeIndex@ and @unsafeRangeSize@ belong to 'Ix' but are
    -- internal to GHC and hence not exported from the module "Data.Ix". However they
    -- are exported from the module @GHC.Arr@.
    -- See 'grange' for how to define an instance of 'Ix' such that it does not
    -- depend on the stability of GHCs internal API. Unfortunately this results in
    -- additional (unnecessary) bound checks.
    -- With the danger of having no stability guarantees for GHC's internal API one
    -- can alternatively define an instance of 'Ix' as
    --
    -- @
    -- import GHC.Arr
    -- instance 'Ix' MyType where
    --   'range' = 'grange'
    --   unsafeIndex = 'gunsafeIndex'
    --   'inRange' = 'ginRange'
    -- @
    gunsafeIndex :: (Generic a, GIx (Rep a)) => (a, a) -> a -> Int
    gunsafeIndex :: forall a. (Generic a, GIx (Rep a)) => (a, a) -> a -> Int
    gunsafeIndex (a
    m, a
    n) a
    i = (Rep a (ZonkAny 1), Rep a (ZonkAny 1)) -> Rep a (ZonkAny 1) -> Int
    forall p. (Rep a p, Rep a p) -> Rep a p -> Int
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Int
    gUnsafeIndex (a -> Rep a (ZonkAny 1)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    m, a -> Rep a (ZonkAny 1)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    n) (a -> Rep a (ZonkAny 1)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    i)

    -- | Generic 'inRange'.
    --
    -- See also 'grange'.
    ginRange :: (Generic a, GIx (Rep a)) => (a, a) -> a -> Bool
    ginRange :: forall a. (Generic a, GIx (Rep a)) => (a, a) -> a -> Bool
    ginRange (a
    m, a
    n) a
    i = (Rep a (ZonkAny 0), Rep a (ZonkAny 0)) -> Rep a (ZonkAny 0) -> Bool
    forall p. (Rep a p, Rep a p) -> Rep a p -> Bool
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Bool
    gInRange (a -> Rep a (ZonkAny 0)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    m, a -> Rep a (ZonkAny 0)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    n) (a -> Rep a (ZonkAny 0)
    forall x. a -> Rep a x
    forall a x. Generic a => a -> Rep a x
    from a
    i)

    -- | Generic representation of 'Enum' types.
    --
    -- The @opts@ parameter is a type-level option to select different
    -- implementations.
    class GEnum opts f where
      gCardinality :: Int
      gFromEnum :: f p -> Int
      gToEnum :: Int -> f p

    -- | Standard option for 'GEnum': derive 'Enum' for types with only nullary
    -- constructors (the same restrictions as in the [Haskell 2010
    -- report](https://www.haskell.org/onlinereport/haskell2010/haskellch11.html#x18-18400011.2)).
    data StandardEnum

    -- | Extends the 'StandardEnum' option for 'GEnum' to allow all constructors to
    -- have arbitrary many fields. Each field type must be an instance of
    -- both 'Enum' and 'Bounded'. Avoid fields of types 'Int' and 'Word'.
    --
    -- === __Details__
    --
    -- Two restrictions require the user's attention:
    --
    -- * The 'Enum' instances of the field types need to start enumerating from 0.
    -- In particular, 'Int' is an unfit field type, because the enumeration of the
    -- negative values starts before 0.
    --
    -- * There can only be up to @'maxBound' :: 'Int'@ values (because the implementation
    -- represents the cardinality explicitly as an 'Int'). This restriction makes
    -- 'Word' an invalid field type as well. Notably, it is insufficient for each
    -- individual field types to stay below this limit. Instead it applies to the
    -- generic type as a whole.
    --
    -- Elements are numbered by 'toEnum', from @0@ up to @(cardinality - 1)@.
    -- The resulting ordering matches the generic 'Ord' instance defined by
    -- 'Generic.Data.gcompare'.
    -- The values from different constructors are enumerated sequentially.
    --
    -- @
    -- data Example = C0 Bool Bool | C1 Bool
    --   deriving ('Eq', 'Ord', 'Show', 'Generic')
    --
    -- cardinality = 6  -- 2    * 2    + 2
    --                  -- Bool * Bool | Bool
    --
    -- enumeration =
    --     [ C0 False False
    --     , C0 False  True
    --     , C0  True False
    --     , C0  True  True
    --     , C1 False
    --     , C1 True
    --     ]
    --
    -- enumeration == map 'gtoFiniteEnum' [0 .. 5]
    -- [0 .. 5] == map 'gfromFiniteEnum' enumeration
    -- @
    data FiniteEnum

    instance GEnum opts f => GEnum opts (M1 i c f) where
      gCardinality :: Int
    gCardinality = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @f
      gFromEnum :: forall p. M1 i c f p -> Int
    gFromEnum = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @opts (f p -> Int) -> (M1 i c f p -> f p) -> M1 i c f p -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . M1 i c f p -> f p
    forall k i (c :: Meta) (f :: k -> *) (p :: k). M1 i c f p -> f p
    unM1
      gToEnum :: forall p. Int -> M1 i c f p
    gToEnum = f p -> M1 i c f p
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 (f p -> M1 i c f p) -> (Int -> f p) -> Int -> M1 i c f p
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @opts

    instance (GEnum opts f, GEnum opts g) => GEnum opts (f :+: g) where
      gCardinality :: Int
    gCardinality = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @f Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @g
      gFromEnum :: forall p. (:+:) f g p -> Int
    gFromEnum (L1 f p
    x) = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @opts f p
    x
      gFromEnum (R1 g p
    y) = Int
    cardF Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @opts g p
    y
        where
          cardF :: Int
    cardF = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @f
      gToEnum :: forall p. Int -> (:+:) f g p
    gToEnum Int
    n
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    cardF = f p -> (:+:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
    L1 (forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @opts Int
    n)
        | Bool
    otherwise = g p -> (:+:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
    R1 (forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @opts (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    cardF))
        where
          cardF :: Int
    cardF = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @opts @f

    instance (GEnum FiniteEnum f, GEnum FiniteEnum g) => GEnum FiniteEnum (f :*: g) where
      gCardinality :: Int
    gCardinality = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @FiniteEnum @f Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @FiniteEnum @g
      gFromEnum :: forall p. (:*:) f g p -> Int
    gFromEnum (f p
    x :*: g p
    y) = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @FiniteEnum f p
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    cardG Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @FiniteEnum g p
    y
        where
          cardG :: Int
    cardG = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @FiniteEnum @g
      gToEnum :: forall p. Int -> (:*:) f g p
    gToEnum Int
    n = forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @FiniteEnum Int
    x f p -> g p -> (:*:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    :*: forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @FiniteEnum Int
    y
        where
          (Int
    x, Int
    y) = Int
    n Int -> Int -> (Int, Int)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` Int
    cardG
          cardG :: Int
    cardG = forall opts (f :: * -> *). GEnum opts f => Int
    gCardinality @FiniteEnum @g

    instance GEnum opts U1 where
      gCardinality :: Int
    gCardinality = Int
    1
      gFromEnum :: forall p. U1 p -> Int
    gFromEnum U1 p
    U1 = Int
    0
      gToEnum :: forall p. Int -> U1 p
    gToEnum Int
    _ = U1 p
    forall k (p :: k). U1 p
    U1

    instance (Bounded c, Enum c) => GEnum FiniteEnum (K1 i c) where
      gCardinality :: Int
    gCardinality = c -> Int
    forall a. Enum a => a -> Int
    fromEnum (c
    forall a. Bounded a => a
    maxBound :: c) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
      gFromEnum :: forall p. K1 i c p -> Int
    gFromEnum = c -> Int
    forall a. Enum a => a -> Int
    fromEnum (c -> Int) -> (K1 i c p -> c) -> K1 i c p -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . K1 i c p -> c
    forall k i c (p :: k). K1 i c p -> c
    unK1
      gToEnum :: forall p. Int -> K1 i c p
    gToEnum = c -> K1 i c p
    forall k i c (p :: k). c -> K1 i c p
    K1 (c -> K1 i c p) -> (Int -> c) -> Int -> K1 i c p
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> c
    forall a. Enum a => Int -> a
    toEnum

    -- | Generic representation of 'Bounded' types.
    class GBounded f where
      gMinBound :: f p
      gMaxBound :: f p

    deriving instance GBounded f => GBounded (M1 i c f)

    instance GBounded U1 where
      gMinBound :: forall p. U1 p
    gMinBound = U1 p
    forall k (p :: k). U1 p
    U1
      gMaxBound :: forall p. U1 p
    gMaxBound = U1 p
    forall k (p :: k). U1 p
    U1

    instance Bounded c => GBounded (K1 i c) where
      gMinBound :: forall p. K1 i c p
    gMinBound = c -> K1 i c p
    forall k i c (p :: k). c -> K1 i c p
    K1 c
    forall a. Bounded a => a
    minBound
      gMaxBound :: forall p. K1 i c p
    gMaxBound = c -> K1 i c p
    forall k i c (p :: k). c -> K1 i c p
    K1 c
    forall a. Bounded a => a
    maxBound

    instance (GBounded f, GBounded g) => GBounded (f :+: g) where
      gMinBound :: forall p. (:+:) f g p
    gMinBound = f p -> (:+:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
    L1 f p
    forall p. f p
    forall (f :: * -> *) p. GBounded f => f p
    gMinBound
      gMaxBound :: forall p. (:+:) f g p
    gMaxBound = g p -> (:+:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
    R1 g p
    forall p. g p
    forall (f :: * -> *) p. GBounded f => f p
    gMaxBound

    instance (GBounded f, GBounded g) => GBounded (f :*: g) where
      gMinBound :: forall p. (:*:) f g p
    gMinBound = f p
    forall p. f p
    forall (f :: * -> *) p. GBounded f => f p
    gMinBound f p -> g p -> (:*:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    :*: g p
    forall p. g p
    forall (f :: * -> *) p. GBounded f => f p
    gMinBound
      gMaxBound :: forall p. (:*:) f g p
    gMaxBound = f p
    forall p. f p
    forall (f :: * -> *) p. GBounded f => f p
    gMaxBound f p -> g p -> (:*:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    :*: g p
    forall p. g p
    forall (f :: * -> *) p. GBounded f => f p
    gMaxBound

    -- | Generic representation of 'Ix' types.
    --
    class GIx f where
      gRange :: (f p, f p) -> [f p]
      gUnsafeIndex :: (f p, f p) -> f p -> Int
      gInRange :: (f p, f p) -> f p -> Bool

    instance GIx f => GIx (M1 i c f) where
      gRange :: forall p. (M1 i c f p, M1 i c f p) -> [M1 i c f p]
    gRange (M1 f p
    m, M1 f p
    n) = (f p -> M1 i c f p) -> [f p] -> [M1 i c f p]
    forall a b. (a -> b) -> [a] -> [b]
    map f p -> M1 i c f p
    forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
    M1 ([f p] -> [M1 i c f p]) -> [f p] -> [M1 i c f p]
    forall a b. (a -> b) -> a -> b
    $ (f p, f p) -> [f p]
    forall p. (f p, f p) -> [f p]
    forall (f :: * -> *) p. GIx f => (f p, f p) -> [f p]
    gRange (f p
    m, f p
    n)
      gUnsafeIndex :: forall p. (M1 i c f p, M1 i c f p) -> M1 i c f p -> Int
    gUnsafeIndex (M1 f p
    m, M1 f p
    n) (M1 f p
    i) = (f p, f p) -> f p -> Int
    forall p. (f p, f p) -> f p -> Int
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Int
    gUnsafeIndex (f p
    m, f p
    n) f p
    i
      gInRange :: forall p. (M1 i c f p, M1 i c f p) -> M1 i c f p -> Bool
    gInRange (M1 f p
    m, M1 f p
    n) (M1 f p
    i) = (f p, f p) -> f p -> Bool
    forall p. (f p, f p) -> f p -> Bool
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Bool
    gInRange (f p
    m, f p
    n) f p
    i

    instance (GEnum StandardEnum f, GEnum StandardEnum g) => GIx (f :+: g) where
      gRange :: forall p. ((:+:) f g p, (:+:) f g p) -> [(:+:) f g p]
    gRange ((:+:) f g p
    x, (:+:) f g p
    y) = (Int -> (:+:) f g p) -> [Int] -> [(:+:) f g p]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> (:+:) f g p
    forall {p}. Int -> (:+:) f g p
    toE [ Int
    i_x .. Int
    i_y ]
        where
          toE :: Int -> (:+:) f g p
    toE = forall opts (f :: * -> *) p. GEnum opts f => Int -> f p
    gToEnum @StandardEnum
          i_x :: Int
    i_x = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    x
          i_y :: Int
    i_y = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    y
      gUnsafeIndex :: forall p. ((:+:) f g p, (:+:) f g p) -> (:+:) f g p -> Int
    gUnsafeIndex ((:+:) f g p
    m, (:+:) f g p
    _) (:+:) f g p
    i = Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int
    i_i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    i_m)
        where
          i_m :: Int
    i_m = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    m
          i_i :: Int
    i_i = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    i
      gInRange :: forall p. ((:+:) f g p, (:+:) f g p) -> (:+:) f g p -> Bool
    gInRange ((:+:) f g p
    m, (:+:) f g p
    n) (:+:) f g p
    i = Int
    i_m Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    i_i Bool -> Bool -> Bool
    && Int
    i_i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    i_n
        where
          i_m :: Int
    i_m = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    m
          i_n :: Int
    i_n = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    n
          i_i :: Int
    i_i = forall opts (f :: * -> *) p. GEnum opts f => f p -> Int
    gFromEnum @StandardEnum (:+:) f g p
    i

    instance (GIx f, GIx g) => GIx (f :*: g) where
      gRange :: forall p. ((:*:) f g p, (:*:) f g p) -> [(:*:) f g p]
    gRange (f p
    m1 :*: g p
    m2, f p
    n1 :*: g p
    n2) =
        [ f p
    i1 f p -> g p -> (:*:) f g p
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    :*: g p
    i2 | f p
    i1 <- (f p, f p) -> [f p]
    forall p. (f p, f p) -> [f p]
    forall (f :: * -> *) p. GIx f => (f p, f p) -> [f p]
    gRange (f p
    m1, f p
    n1), g p
    i2 <- (g p, g p) -> [g p]
    forall p. (g p, g p) -> [g p]
    forall (f :: * -> *) p. GIx f => (f p, f p) -> [f p]
    gRange (g p
    m2, g p
    n2) ]
      gUnsafeIndex :: forall p. ((:*:) f g p, (:*:) f g p) -> (:*:) f g p -> Int
    gUnsafeIndex (f p
    m1 :*: g p
    m2, f p
    n1 :*: g p
    n2) (f p
    i1 :*: g p
    i2) = Int
    int1 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    rangeSize2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    int2
        where
          int1 :: Int
    int1 = (f p, f p) -> f p -> Int
    forall p. (f p, f p) -> f p -> Int
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Int
    gUnsafeIndex (f p
    m1, f p
    n1) f p
    i1
          int2 :: Int
    int2 = (g p, g p) -> g p -> Int
    forall p. (g p, g p) -> g p -> Int
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Int
    gUnsafeIndex (g p
    m2, g p
    n2) g p
    i2
          rangeSize2 :: Int
    rangeSize2 = (g p, g p) -> g p -> Int
    forall p. (g p, g p) -> g p -> Int
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Int
    gUnsafeIndex (g p
    m2, g p
    n2) g p
    n2 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
      gInRange :: forall p. ((:*:) f g p, (:*:) f g p) -> (:*:) f g p -> Bool
    gInRange (f p
    m1 :*: g p
    m2, f p
    n1 :*: g p
    n2) (f p
    i1 :*: g p
    i2) =
        (f p, f p) -> f p -> Bool
    forall p. (f p, f p) -> f p -> Bool
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Bool
    gInRange (f p
    m1, f p
    n1) f p
    i1 Bool -> Bool -> Bool
    && (g p, g p) -> g p -> Bool
    forall p. (g p, g p) -> g p -> Bool
    forall (f :: * -> *) p. GIx f => (f p, f p) -> f p -> Bool
    gInRange (g p
    m2, g p
    n2) g p
    i2

    instance GIx U1 where
      gRange :: forall p. (U1 p, U1 p) -> [U1 p]
    gRange (U1 p
    U1, U1 p
    U1) = [U1 p
    forall k (p :: k). U1 p
    U1]
      gUnsafeIndex :: forall p. (U1 p, U1 p) -> U1 p -> Int
    gUnsafeIndex (U1 p
    U1, U1 p
    U1) U1 p
    U1 = Int
    0
      gInRange :: forall p. (U1 p, U1 p) -> U1 p -> Bool
    gInRange (U1 p
    U1, U1 p
    U1) U1 p
    U1 = Bool
    True

    instance (Ix c) => GIx (K1 i c) where
      gRange :: forall p. (K1 i c p, K1 i c p) -> [K1 i c p]
    gRange (K1 c
    m, K1 c
    n) = (c -> K1 i c p) -> [c] -> [K1 i c p]
    forall a b. (a -> b) -> [a] -> [b]
    map c -> K1 i c p
    forall k i c (p :: k). c -> K1 i c p
    K1 ([c] -> [K1 i c p]) -> [c] -> [K1 i c p]
    forall a b. (a -> b) -> a -> b
    $ (c, c) -> [c]
    forall a. Ix a => (a, a) -> [a]
    range (c
    m, c
    n)
      gUnsafeIndex :: forall p. (K1 i c p, K1 i c p) -> K1 i c p -> Int
    gUnsafeIndex (K1 c
    m, K1 c
    n) (K1 c
    i) = (c, c) -> c -> Int
    forall a. Ix a => (a, a) -> a -> Int
    index (c
    m, c
    n) c
    i
      gInRange :: forall p. (K1 i c p, K1 i c p) -> K1 i c p -> Bool
    gInRange (K1 c
    m, K1 c
    n) (K1 c
    i) = (c, c) -> c -> Bool
    forall a. Ix a => (a, a) -> a -> Bool
    inRange (c
    m, c
    n) c
    i