-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Extensible records and polymorphic variants.
--   
--   <a>Data.Diverse.Many</a> is an extensible record for any size encoded
--   efficiently as (Seq Any). <a>Data.Diverse.Which</a> is a polymorphic
--   variant of possibilities encoded as (Int, Any). Provides getters,
--   setters, projection, injection, folds, and catamorphisms; accessed by
--   type, index or label. Refer to <a>ManySpec.hs</a> and
--   <a>WhichSpec.hs</a> for example usages. Iso, Lens and Prisms are
--   provided in <a>data-diverse-lens</a>
@package data-diverse
@version 2.0.1.0

module Data.Diverse.AFoldable

-- | Constrained Foldable for a specified type instead for all types.
class AFoldable t a
afoldr :: AFoldable t a => (a -> b -> b) -> b -> t a -> b
afoldl' :: AFoldable t a => (b -> a -> b) -> b -> t a -> b

module Data.Diverse.Reduce

-- | Convert something <tt>v</tt> into <tt>r</tt> using handlers. This
--   class is required in order to step through all the different types in
--   a variant.
class Reduce v handler
reduce :: Reduce v handler => handler -> v -> Reduced handler

module Data.Diverse.TypeLevel.Internal

-- | Get the first position of a type (indexed by 1) Will return 0 if
--   <tt>x</tt> doesn't exists in <tt>xs</tt>.

-- | Get the first index of a type from a list

-- | Searches for y in ys if not found, than use y, and repeat search with
--   next (y ': ys) in ctx else if found, then don't use y, then repeat
--   search with next (y ': ys) in ctx

-- | Errors if a type exists in a typelist

-- | Errors if a label exists in a typelist

-- | Ensures that the type list contain unique types. Not implemented as
--   <tt>(xs ~ Nub xs)</tt> for better type error messages.

-- | Ensures that <tt>x</tt> only ever appears once in <tt>xs</tt>

-- | Ensures that the <tt>label</tt> in <tt>tagged label v</tt> only ever
--   appears once in <tt>xs</tt>.

-- | Indexed access into the list

-- | Labelled access into the list

-- | Ensures two typelists are the same length

-- | The typelist <tt>xs</tt> without the type at Nat <tt>n</tt>.
--   <tt>n</tt> must be within bounds of <tt>xs</tt>

-- | The typelist <tt>xs</tt> without the type at Nat <tt>n</tt> replaced
--   by <tt>y</tt>. <tt>n</tt> must be within bounds of <tt>xs</tt>

-- | The typelist <tt>xs</tt> with the first <tt>x</tt> replaced by
--   <tt>y</tt>. It is okay for <tt>x</tt> not to exist in <tt>xs</tt>

-- | The typelist <tt>zs</tt> with the first <tt>xs</tt> replaced by
--   <tt>ys</tt>. <tt>xs</tt> must be the same size as <tt>ys</tt>

-- | The type <tt>x</tt> replaced by an <tt>y</tt> if an <tt>n</tt> matches
--   <tt>i</tt>.

-- | The typelist <tt>xs</tt> replaced by <tt>ys</tt> at the indices
--   <tt>ns</tt>. <tt>ns</tt> and <tt>ys</tt> must be the same length.
--   <tt>ns</tt> must be within bounds of <tt>xs</tt>

-- | Zips up <tt>xs</tt> and <tt>ys</tt>, which must be the same length

module Data.Diverse.TypeLevel

-- | Ensures that <tt>x</tt> is a unique member of <tt>xs</tt>, and that
--   <a>natVal</a> can be used.
type UniqueMember x xs = (Unique x xs, KnownNat (IndexOf x xs))

-- | Every x in <tt>xs</tt> is a `UniqueMember x ys`

-- | Ensures that <tt>x</tt> is a unique member of <tt>xs</tt>, and that
--   <a>natVal</a> can be used.
type UniqueLabelMember l xs = (UniqueLabel l xs, KnownNat (IndexOf (KindAtLabel l xs) xs))

-- | Ensures that <tt>x</tt> is a unique member of <tt>xs</tt> if it
--   exists, and that <a>natVal</a> can be used.
type MaybeUniqueMember x xs = (Unique x xs, KnownNat (PositionOf x xs))

-- | Ensures that <tt>x</tt> is a member of <tt>xs</tt> at <tt>n</tt>, and
--   that <a>natVal</a> can be used.
type MemberAt n x xs = (KnownNat n, x ~ KindAtIndex n xs)

-- | Ensures that <tt>x</tt> is a member of <tt>xs</tt> at <tt>n</tt> if it
--   exists, and that <a>natVal</a> can be used.
type MaybeMemberAt n x xs = (KnownNat n, KindAtPositionIs n x xs)

-- | Snoc <tt>x</tt> to end of <tt>xs</tt> if <tt>x</tt> doesn't already
--   exist in <tt>xs</tt>

-- | For each <tt>y</tt> in <tt>ys</tt>, snocs them to end of <tt>xs</tt>
--   if <tt>y</tt> doesn't already exist in <tt>xs</tt>

-- | Ensures x is a unique member in <tt>xs</tt> iff it exists in
--   <tt>ys</tt>

-- | Ensures that the type list contain unique types
type IsDistinct (xs :: [k]) = IsDistinctImpl xs xs

-- | Return the list of distinct types in a typelist

-- | Ensures that <tt>x</tt> only ever appears once in <tt>xs</tt>
type Unique (x :: k) (xs :: [k]) = UniqueImpl xs x xs

-- | Ensures that the <tt>label</tt> in <tt>tagged label v</tt> only ever
--   appears once in <tt>xs</tt>.
type UniqueLabel (l :: k1) (xs :: [k]) = UniqueLabelImpl xs l xs

-- | Ensures that the <tt>label</tt> list all <a>UniqueLabel</a>s

-- | Get the first index of a type (Indexed by 0) Will result in type error
--   if x doesn't exist in xs.
type IndexOf (x :: k) (xs :: [k]) = IndexOfImpl xs x xs

-- | Get the first index of a type (Indexed by 1) Will return 0 if x
--   doesn't exists in xs.
type PositionOf (x :: k) (xs :: [k]) = PositionOfImpl 0 x xs

-- | Get the type at an index
type KindAtIndex (n :: Nat) (xs :: [k]) = KindAtIndexImpl n xs n xs

-- | Get the type at a label
type KindAtLabel (l :: k1) (xs :: [k]) = KindAtLabelImpl l xs xs

-- | It's actually ok for the position to be zero, but if it's not zero
--   then the types must match

-- | Get the types at an list of index

-- | Get the types with labels <tt>ls</tt> from <tt>xs</tt>

-- | The typelist <tt>xs</tt> without first <tt>x</tt>. It is okay for
--   <tt>x</tt> not to exist in <tt>xs</tt>

-- | The typelist <tt>xs</tt> with the first <tt>x</tt> replaced by
--   <tt>y</tt>. It is okay for <tt>x</tt> not to exist in <tt>xs</tt>
type Replace (x :: k) (y :: k) (xs :: [k]) = ReplaceImpl x y xs

-- | The typelist <tt>zs</tt> with the first <tt>xs</tt> replaced by
--   <tt>ys</tt>. <tt>xs</tt> must be the same size as <tt>ys</tt>
type Replaces (xs :: [k]) (ys :: [k]) (zs :: [k]) = ReplacesImpl xs ys xs ys zs

-- | The typelist <tt>xs</tt> without the type at Nat <tt>n</tt>.
--   <tt>n</tt> must be within bounds of <tt>xs</tt>
type RemoveIndex (n :: Nat) (xs :: [k]) = RemoveIndexImpl n xs n xs

-- | The typelist <tt>xs</tt> without the type at Nat <tt>n</tt> replaced
--   by <tt>y</tt>. <tt>n</tt> must be within bounds of <tt>xs</tt>
type ReplaceIndex (n :: Nat) (y :: k) (xs :: [k]) = ReplaceIndexImpl n xs n y xs

-- | The typelist <tt>xs</tt> replaced by <tt>ys</tt> at the indices
--   <tt>ns</tt>. <tt>ns</tt> and <tt>ys</tt> must be the same length.
--   <tt>ns</tt> must be within bounds of <tt>xs</tt>
type ReplacesIndex (ns :: [Nat]) (ys :: [k]) (xs :: [k]) = ReplacesIndexImpl 0 ns ys xs

-- | Returns the typelist up to and excluding <tt>x</tt>. If <tt>x</tt>
--   doesn't exist, then the original <tt>xs</tt> is returned.

-- | Returns the typelist up to and including <tt>x</tt>. If <tt>x</tt>
--   doesn't exist, then the original <tt>xs</tt> is returned.

-- | Returns the typelist after and excluding <tt>x</tt>. If <tt>x</tt>
--   doesn't exist, then an empty '[] is returned.

-- | Returns the typelist after and including <tt>x</tt>. If <tt>x</tt>
--   doesn't exist, then an empty '[] is returned.

-- | Returns the typelist before (and exluding) index <tt>n</tt>. If
--   <tt>n</tt> is larger then the <tt>xs</tt> size, then the original
--   <tt>xs</tt> is returned.

-- | Returns the typelist up to (and including) index <tt>n</tt>. If
--   <tt>n</tt> is larger then the <tt>xs</tt> size, then the original
--   <tt>xs</tt> is returned.

-- | Returns the typelist after (and exluding) index <tt>n</tt>. If
--   <tt>n</tt> is larger then the <tt>xs</tt> size, then an empty '[] is
--   returned.

-- | Returns the typelist from (and including) index <tt>n</tt>. If
--   <tt>n</tt> is larger then the <tt>xs</tt> size, then an empty '[] is
--   returned.

-- | Get the typelist without the <a>Head</a> type

-- | Get the first type in a typelist

-- | Ensures two typelists are the same length
type SameLength (xs :: [k1]) (ys :: [k2]) = SameLengthImpl xs ys xs ys

-- | Set complement. Returns the set of things in <tt>xs</tt> that are not
--   in <tt>ys</tt>.

-- | Returns a <tt>xs</tt> appended with <tt>ys</tt>

-- | Returns the typelist without the <a>Last</a> type

-- | Takes two lists which must be the same length and returns a list of
--   corresponding pairs.
type Zip (xs :: [k]) (ys :: [k]) = ZipImpl xs ys xs ys

-- | The result from evaluating a <tt>Case</tt> with a type from a
--   typelist.

-- | Return a list of results from applying <a>CaseResult</a> to every type
--   in the <tt>xs</tt> typelist.

-- | Tests if all the types in a typelist satisfy a constraint

module Data.Diverse.Reiterate

-- | Allows iterating over the types in a typelist
class Reiterate c (xs :: [Type])

-- | Return the next iteration without the <a>Head</a> type x in (x ': xs)
reiterate :: Reiterate c xs => c xs -> c (Tail xs)

-- | Allows iterating over the types in a typelist, whilst also
--   incrementing an Nat index
class ReiterateN c (n :: Nat) (xs :: [Type])

-- | Return the next iteration without the <a>Head</a> type x in (x ': xs)
reiterateN :: ReiterateN c n xs => c n xs -> c (n + 1) (Tail xs)

module Data.Diverse.Case

-- | This class allows defining handlers that can handle the <a>Head</a>
--   type in the <tt>xs</tt> typelist. In conjunction with
--   <a>Reiterate</a>, you can define handlers that can handle all the
--   types in the <tt>xs</tt> typelist.
--   
--   See <a>Data.Diverse.CaseFunc</a> and <a>Data.Diverse.Cases</a>.
class Case c (xs :: [Type])

-- | Return the handler/continuation when x is observed.
case' :: Case c xs => c xs -> Head xs -> CaseResult c (Head xs)

module Data.Diverse.CaseFunc

-- | This handler stores a polymorphic function that returns a different
--   type.
--   
--   <pre>
--   let y = <a>pick</a> (5 :: Int) :: <a>Which</a> '[Int, Bool]
--   <a>switch</a> y (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` <a>Int</a>
--   </pre>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nul</a>
--   <a>afoldr</a> (:) [] (<a>forMany</a> (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) x) `shouldBe`
--       ["Int", "Bool", "Char", "Maybe Char", "Int", "Maybe Char"]
--   </pre>
newtype CaseFunc (k :: Type -> Constraint) r (xs :: [Type])
CaseFunc :: (forall x. k x => x -> r) -> CaseFunc r

-- | This handler stores a polymorphic function that doesn't change the
--   type.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> (6 :: Int8) <a>./</a> (7 :: Int16) <a>./</a> (8 :: Int32) <a>./</a> <a>nil</a>
--       y = (15 :: Int) <a>./</a> (16 :: Int8) <a>./</a> (17 :: Int16) <a>./</a> (18 :: Int32) <a>./</a> <a>nil</a>
--   <a>afmap</a> (<a>CaseFunc'</a> @<a>Num</a> (+10)) x `shouldBe` y
--   </pre>
newtype CaseFunc' (k :: Type -> Constraint) (xs :: [Type])
CaseFunc' :: (forall x. k x => x -> x) -> CaseFunc'
instance Data.Diverse.Reiterate.Reiterate (Data.Diverse.CaseFunc.CaseFunc' k) xs
instance k x => Data.Diverse.Case.Case (Data.Diverse.CaseFunc.CaseFunc' k) (x : xs)
instance Data.Diverse.Reiterate.Reiterate (Data.Diverse.CaseFunc.CaseFunc k r) xs
instance k x => Data.Diverse.Case.Case (Data.Diverse.CaseFunc.CaseFunc k r) (x : xs)

module Data.Diverse.AFunctor

-- | Given a <a>Case</a> that transforms each type in the typelist, convert
--   a <tt>f xs</tt> to <tt>f (CasesResult2 c xs)</tt>
class AFunctor f c xs
afmap :: AFunctor f c xs => c xs -> f xs -> f (CaseResults c xs)

module Data.Diverse.Many.Internal

-- | A Many is an anonymous product type (also know as polymorphic record),
--   with no limit on the number of fields.
--   
--   The following functions are available can be used to manipulate unique
--   fields
--   
--   <ul>
--   <li>getter/setter for single field: <a>fetch</a> and
--   <a>replace</a></li>
--   <li>getter/setter for multiple fields: <a>select</a> and
--   <a>amend</a></li>
--   <li>folds: <a>forMany</a> or <a>collect</a></li>
--   </ul>
--   
--   These functions are type specified. This means labels are not required
--   because the types themselves can be used to access the 'Many. It is a
--   compile error to use those functions for duplicate fields.
--   
--   For duplicate fields, Nat-indexed versions of the functions are
--   available:
--   
--   <ul>
--   <li>getter/setter for single field: <a>fetchN</a> and
--   <a>replaceN</a></li>
--   <li>getter/setter for multiple fields: <a>selectN</a> and
--   <a>amendN</a></li>
--   <li>folds: <a>forManyN</a> or <a>collectN</a></li>
--   </ul>
--   
--   Encoding: The record is encoded as (S.Seq Any). This encoding should
--   reasonabily efficient for any number of fields.
--   
--   The map Key is index + offset of the type in the typelist. The Offset
--   is used to allow efficient cons <a>prefix</a>.
--   
--   <pre>
--   Key = Index of type in typelist + Offset
--   </pre>
--   
--   The constructor will guarantee the correct number and types of the
--   elements. The constructor is only exported in the
--   <a>Data.Diverse.Many.Internal</a> module
newtype Many (xs :: [Type])
Many :: (Seq Any) -> Many

-- | This instance allows converting to and from Many There are instances
--   for converting tuples of up to size 15.
class IsMany t xs a
toMany :: IsMany t xs a => t xs a -> Many xs
fromMany :: IsMany t xs a => Many xs -> t xs a

-- | Converts from a Many to a value (eg a tuple), via a Tagged wrapper
fromMany' :: IsMany Tagged xs a => Many xs -> a

-- | Converts from a value (eg a tuple) to a <a>Many</a>, via a
--   <a>Tagged</a> wrapper
toMany' :: IsMany Tagged xs a => a -> Many xs

-- | Analogous to <a>null</a>. Named <a>nil</a> to avoid conflicting with
--   <a>null</a>.
nil :: Many '[]

-- | Create a Many from a single value. Analogous to <a>singleton</a>
single :: x -> Many '[x]

-- | Add an element to the left of a Many. Not named <tt>cons</tt> to avoid
--   conflict with <a>cons</a>
prefix :: x -> Many xs -> Many (x : xs)
infixr 5 `prefix`

-- | Infix version of <a>prefix</a>.
--   
--   Mnemonic: Element on the left is smaller <a>./</a> than the larger
--   <a>Many</a> to the right.
(./) :: x -> Many xs -> Many (x : xs)
infixr 5 ./

-- | Add an element to the right of a Many Not named <tt>snoc</tt> to avoid
--   conflict with <a>snoc</a>
postfix :: Many xs -> y -> Many (Append xs '[y])
infixl 5 `postfix`

-- | Add an element to the right of a Many iff the field doesn't already
--   exist.
postfix' :: forall y xs. MaybeUniqueMember y xs => Many xs -> y -> Many (SnocUnique xs y)
infixl 5 `postfix'`

-- | Infix version of <a>postfix</a>.
--   
--   Mnemonic: Many is larger <a>\.</a> than the smaller element
(\.) :: Many xs -> y -> Many (Append xs '[y])
infixl 5 \.

-- | Appends two Manys together
append :: Many xs -> Many ys -> Many (Append xs ys)
infixr 5 `append`
class CanAppendUnique xs ys

-- | Appends the unique fields fields from the right Many using
--   <a>postfix'</a>
append' :: CanAppendUnique xs ys => Many xs -> Many ys -> Many (AppendUnique xs ys)

-- | Infix version of <a>append</a>.
--   
--   Mnemonic: <a>prefix</a> <a>./</a> with an extra slash (meaning
--   <a>Many</a>) in front.
(/./) :: Many xs -> Many ys -> Many (Append xs ys)
infixr 5 /./

-- | Split a non-empty Many into the first element, then the rest of the
--   Many. Analogous to <a>viewl</a>
viewf :: Many (x : xs) -> (x, Many xs)

-- | Split a non-empty Many into initial part of Many, and the last
--   element. Analogous to <a>viewr</a>
viewb :: Many (x : xs) -> (Many (Init (x : xs)), Last (x : xs))

-- | Extract the first element of a Many, which guaranteed to be non-empty.
--   Analogous to <a>head</a>
front :: Many (x : xs) -> x

-- | Extract the <a>back</a> element of a Many, which guaranteed to be
--   non-empty. Analogous to <a>last</a>
back :: Many (x : xs) -> Last (x : xs)

-- | Extract the elements after the front of a Many, which guaranteed to be
--   non-empty. Analogous to <a>tail</a>
aft :: Many (x : xs) -> Many xs

-- | Return all the elements of a Many except the <a>back</a> one, which
--   guaranteed to be non-empty. Analogous to <a>init</a>
fore :: Many (x : xs) -> Many (Init (x : xs))

-- | Getter by unique type. Get the field with type <tt>x</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>fetch</a> @Int x `shouldBe` 5
--   </pre>
fetch :: forall x xs. UniqueMember x xs => Many xs -> x

-- | Getter by label. Get the value of the field with tag <tt>label</tt>
--   which can be any type not just <tt>KnownSymbol</tt>.
--   
--   <pre>
--   let y = False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @<a>Hi</a> True <a>./</a> <a>nil</a>
--   <a>fetchL</a> @Foo y `shouldBe` Tagged @Foo 'X'
--   <a>fetchL</a> @<a>Hi</a> y `shouldBe` Tagged @<a>Hi</a> True
--   </pre>
fetchL :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> x

-- | Variation of <a>fetchL</a> specialized for <a>Tagged</a> that untags
--   the field.
fetchTag :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Many xs -> x

-- | Getter by index. Get the value of the field at index type-level Nat
--   <tt>n</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>fetchN</a> @1 x `shouldBe` False
--   </pre>
fetchN :: forall n x xs. MemberAt n x xs => Many xs -> x

-- | Polymorphic setter by unique type. Set the field with type <tt>x</tt>,
--   and replace with type <tt>y</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>replace</a> @Int x (Just True) `shouldBe` Just True <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   </pre>
replace :: forall x y xs. UniqueMember x xs => Many xs -> y -> Many (Replace x y xs)

-- | Setter by unique type. Set the field with type <tt>x</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>replace'</a> @Int x 6 `shouldBe` (6 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   </pre>
replace' :: forall x xs. UniqueMember x xs => Many xs -> x -> Many xs

-- | Polymorphic setter by unique type. Set the field with type <tt>x</tt>,
--   and replace with type <tt>y</tt>
--   
--   <pre>
--   let y = (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" (6 :: Int) <a>./</a> <a>nil</a>
--   replaceL @Foo y (Tagged @Bar 'Y') <tt>shouldBe</tt>
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged <tt>Bar <tt>Y</tt> <a>./</a> Tagged </tt><a>Hello</a> (6 :: Int) <a>./</a> <a>nil</a>
--   replaceL @"Hello" y (Tagged @"Hello" False) `shouldBe`
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" False <a>./</a> <a>nil</a>
--   </pre>
replaceL :: forall l y xs x. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> y -> Many (Replace x y xs)

-- | Setter by unique label. Set the field with label <tt>l</tt>.
--   
--   <pre>
--   let y = (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" (6 :: Int) <a>./</a> <a>nil</a>
--   <a>replaceL'</a> @Foo y (Tagged @Foo 'Y') `shouldBe`
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'Y' <a>./</a> Tagged @"Hello" (6 :: Int) <a>./</a> <a>nil</a>
--   <a>replaceL'</a> @"Hello" y (Tagged @"Hello" 7) `shouldBe`
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" (7 :: Int) <a>./</a> <a>nil</a>
--   </pre>
replaceL' :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> x -> Many xs

-- | Variation of <a>replaceL</a> specialized to <a>Tagged</a> that
--   automatically tags the value to be replaced.
replaceTag :: forall l x y xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> y -> Many (Replace x (Tagged l y) xs)

-- | Variation of <a>replaceL'</a> specialized to <a>Tagged</a> that
--   automatically tags the value to be replaced.
replaceTag' :: forall l xs x. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Many xs -> x -> Many xs

-- | Polymorphic version of <a>replaceN'</a>
replaceN :: forall n x y xs. MemberAt n x xs => Many xs -> y -> Many (ReplaceIndex n y xs)

-- | Setter by index. Set the value of the field at index type-level Nat
--   <tt>n</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>replaceN'</a> @0 x 7 <tt>shouldBe</tt>
--   </pre>
replaceN' :: forall n x xs. MemberAt n x xs => Many xs -> x -> Many xs

-- | A friendlier type constraint synomyn for <a>select</a>
type Select (smaller :: [Type]) (larger :: [Type]) = (AFoldable (CollectorAny (CaseSelect smaller larger) larger) (Maybe (Int, WrappedAny)))

-- | Construct a <a>Many</a> with a smaller number of fields than the
--   original. Analogous to <a>fetch</a> getter but for multiple fields.
--   
--   This can also be used to reorder fields in the original <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   <a>select</a> @'[Bool, Char] x `shouldBe` False <a>./</a> 'X' <a>./</a> <a>nil</a>
--   </pre>
select :: forall smaller larger. Select smaller larger => Many larger -> Many smaller

-- | A variation of <a>select</a> which selects by labels
--   
--   <pre>
--   let x = False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Bye" <tt>O</tt> <a>./</a> <a>nil</a>
--   <a>selectL</a> @'[Foo, Bar] x `shouldBe` Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> <a>nil</a>
--   <a>selectL</a> @'["Hi", "Bye"] x `shouldBe` Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   </pre>
selectL :: forall ls smaller larger. (Select smaller larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger) => Many larger -> Many smaller

-- | A friendlier type constraint synomyn for <a>selectN</a>
type SelectN (ns :: [Nat]) (smaller :: [Type]) (larger :: [Type]) = (AFoldable (CollectorAnyN (CaseSelectN ns smaller) 0 larger) (Maybe (Int, WrappedAny)), smaller ~ KindsAtIndices ns larger, IsDistinct ns)

-- | A variation of <a>select</a> which uses a Nat list <tt>n</tt> to
--   specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx@
--   </pre>
--   
--   This variation allows <tt>smaller</tt> or <tt>larger</tt> to contain
--   indistinct since the mapping is specified by <tt>indicies</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   <a>selectN</a> @'[5, 4, 0] x `shouldBe` Just 'A' <a>./</a> (6 :: Int) <a>./</a> (5 ::Int) <a>./</a> <a>nil</a>
--   </pre>
selectN :: forall ns smaller larger. SelectN ns smaller larger => Many larger -> Many smaller

-- | A friendlier type constraint synomyn for <a>amend</a>
type Amend smaller smaller' larger = (AFoldable (CollectorAny (CaseAmend larger) (Zip smaller smaller')) (Int, WrappedAny), IsDistinct smaller)

-- | Polymorphic version of <a>amend'</a>. Analogous to <a>replace</a>
--   setter but for multiple fields.
amend :: forall smaller smaller' larger larger'. (Amend smaller smaller' larger, larger' ~ Replaces smaller smaller' larger) => Many larger -> Many smaller' -> Many larger'

-- | A friendlier type constraint synomyn for <a>amend'</a>
type Amend' smaller larger = (AFoldable (CollectorAny (CaseAmend' larger) smaller) (Int, WrappedAny), IsDistinct smaller)

-- | Sets the subset of <a>Many</a> in the larger <a>Many</a>. Analogous to
--   <a>replace</a> setter but for multiple fields.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>amend'</a> @'[Int, Maybe Char] x ((6 :: Int) <a>./</a> Just 'P' <a>./</a> <a>nil</a>) `shouldBe`
--       (6 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'P' <a>./</a> <a>nil</a>
--   </pre>
amend' :: forall smaller larger. Amend' smaller larger => Many larger -> Many smaller -> Many larger

-- | A variation of <a>amend</a> which amends via labels.
--   
--   <pre>
--   let x = False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar <tt>X</tt> <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   <a>amendL</a> @'[Foo, Bar] x ('Y' <a>./</a> True <a>./</a> <tt>ni</tt>l) `shouldBe`
--       False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> 'Y' <a>./</a> True <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   <a>amendL</a> @'["Hi", "Bye"] x (True <a>./</a> Tagged @"Changed" True <a>./</a> <a>nil</a>) `shouldBe`
--       False <a>./</a> True <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Changed" True <a>./</a> <a>nil</a>
--   </pre>
amendL :: forall ls smaller smaller' larger larger'. (Amend smaller smaller' larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger, larger' ~ Replaces smaller smaller' larger) => Many larger -> Many smaller' -> Many larger'

-- | A variation of <a>amend'</a> which amends via labels.
--   
--   <pre>
--   let x = False .<i> Tagged @"Hi" (5 :: Int) .</i> Tagged @Foo False .<i> Tagged @Bar 'X' .</i> Tagged @"Bye" 'O' ./ <a>nil</a>
--   <a>amendL</a> @'[Foo, Bar] x (Tagged @Foo True .<i> Tagged @Bar 'Y' .</i> nil) <tt>shouldBe</tt>
--       False .<i> Tagged @"Hi" (5 :: Int) .</i> Tagged @Foo True .<i> Tagged @Bar 'Y' .</i> Tagged @"Bye" 'O' ./ <a>nil</a>
--   <a>amendL</a> @'["Hi", "Bye"] x (Tagged @"Hi" (6 :: Int) .<i> Tagged @"Bye" 'P' .</i> nil) <tt>shouldBe</tt>
--       False .<i> Tagged @"Hi" (6 :: Int) .</i> Tagged @Foo False .<i> Tagged @Bar 'X' .</i> Tagged @"Bye" 'P' ./ <a>nil</a>
--   </pre>
amendL' :: forall ls smaller larger. (Amend' smaller larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger) => Many larger -> Many smaller -> Many larger

-- | A friendlier type constraint synomyn for <a>amendN</a>
type AmendN ns smaller smaller' larger = (AFoldable (CollectorAnyN (CaseAmendN ns larger) 0 (Zip smaller smaller')) (Int, WrappedAny), smaller ~ KindsAtIndices ns larger, IsDistinct ns)

-- | A polymorphic variation of <a>amendN'</a>
amendN :: forall ns smaller smaller' larger larger'. (AmendN ns smaller smaller' larger, larger' ~ ReplacesIndex ns smaller' larger) => Many larger -> Many smaller' -> Many larger'

-- | A friendlier type constraint synomyn for <a>amendN'</a>
type AmendN' ns smaller larger = (AFoldable (CollectorAnyN (CaseAmendN' ns larger) 0 smaller) (Int, WrappedAny), smaller ~ KindsAtIndices ns larger, IsDistinct ns)

-- | A variation of <a>amend'</a> which uses a Nat list <tt>n</tt> to
--   specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx@
--   </pre>
--   
--   This variation allows <tt>smaller</tt> or <tt>larger</tt> to contain
--   indistinct since the mapping is specified by <tt>indicies</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   <a>amendN'</a> @'[5, 4, 0] x (Just 'B' <a>./</a> (8 :: Int) <a>./</a> (4 ::Int) <a>./</a> <a>nil</a>) `shouldBe`
--       (4 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (8 :: Int) <a>./</a> Just 'B' <a>./</a> <a>nil</a>
--   </pre>
amendN' :: forall ns smaller larger. (AmendN' ns smaller larger) => Many larger -> Many smaller -> Many larger

-- | A friendlier type constraint synomyn for <a>collect</a> and
--   <a>forMany</a>
type Collect c r (xs :: [Type]) = (AFoldable (Collector c xs) r, Case (c r) xs)

-- | Collects the output from <a>case'</a>ing each field in a <a>Many</a>.
--   Uses <a>Reiterate</a> to prepare the <a>Case</a> to accept the next
--   type in the <tt>xs</tt> typelist.
--   
--   Internally, this holds the left-over [(k, v)] from the original
--   <a>Many</a> for the remaining typelist <tt>xs</tt>.
--   
--   That is, the first v in the (k, v) is of type <tt>x</tt>, and the
--   length of the list is equal to the length of <tt>xs</tt>.
data Collector c (xs :: [Type]) r

-- | Folds any <a>Many</a>, even with indistinct types. Given
--   <b>distinct</b> handlers for the fields in <a>Many</a>, create
--   <a>AFoldable</a> of the results of running the handlers over the
--   fields in <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Bool <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>forMany</a> (<a>cases</a> y) x) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
forMany :: Collect c r xs => c r xs -> Many xs -> Collector c xs r

-- | This is <tt>flip <a>forMany</a></tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Bool <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>collect</a> x (<a>cases</a> y)) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
collect :: (Collect c r xs) => Many xs -> c r xs -> Collector c xs r

-- | A friendlier type constraint synomyn for <a>collect</a> and
--   <a>forMany</a>
type CollectN c r (n :: Nat) (xs :: [Type]) = (AFoldable (CollectorN c n xs) r, Case (c r n) xs)

-- | A variation of <a>Collector</a> which uses <a>ReiterateN</a> instead
--   of <a>Reiterate</a>
data CollectorN c (n :: Nat) (xs :: [Type]) r

-- | Folds any <a>Many</a>, even with indistinct types. Given <b>index</b>
--   handlers for the fields in <a>Many</a>, create <a>AFoldable</a> of the
--   results of running the handlers over the fields in <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Bool <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Int <a>./</a> show @(Maybe Char) <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>forManyN</a> (<a>casesN</a> y) x) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
forManyN :: CollectN c r n xs => c r n xs -> Many xs -> CollectorN c n xs r

-- | This is <tt>flip <a>forManyN</a></tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Bool <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Int <a>./</a> show @(Maybe Char) <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>collectN</a> x (<a>casesN</a> y)) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
collectN :: CollectN c r n xs => Many xs -> c r n xs -> CollectorN c n xs r
instance (Data.Diverse.TypeLevel.UniqueIfExists smaller x larger, Data.Diverse.TypeLevel.MaybeUniqueMember x smaller) => Data.Diverse.Many.Internal.CaseAny (Data.Diverse.Many.Internal.CaseSelect smaller larger (GHC.Base.Maybe (GHC.Types.Int, Data.Diverse.Many.Internal.WrappedAny))) (x : xs)
instance (Data.Diverse.TypeLevel.MaybeMemberAt n' x smaller, n' ~ Data.Diverse.TypeLevel.PositionOf n indices) => Data.Diverse.Many.Internal.CaseAny (Data.Diverse.Many.Internal.CaseSelectN indices smaller (GHC.Base.Maybe (GHC.Types.Int, Data.Diverse.Many.Internal.WrappedAny)) n) (x : xs)
instance Data.Diverse.TypeLevel.UniqueMember x larger => Data.Diverse.Many.Internal.CaseAny (Data.Diverse.Many.Internal.CaseAmend' larger (GHC.Types.Int, Data.Diverse.Many.Internal.WrappedAny)) (x : xs)
instance Data.Diverse.TypeLevel.UniqueMember x larger => Data.Diverse.Many.Internal.CaseAny (Data.Diverse.Many.Internal.CaseAmend larger (GHC.Types.Int, Data.Diverse.Many.Internal.WrappedAny)) ((x, y) : zs)
instance (Data.Diverse.TypeLevel.MemberAt n' x larger, n' ~ Data.Diverse.TypeLevel.KindAtIndex n indices) => Data.Diverse.Many.Internal.CaseAny (Data.Diverse.Many.Internal.CaseAmendN' indices larger (GHC.Types.Int, Data.Diverse.Many.Internal.WrappedAny) n) (x : xs)
instance (Data.Diverse.TypeLevel.MemberAt n' x larger, n' ~ Data.Diverse.TypeLevel.KindAtIndex n indices) => Data.Diverse.Many.Internal.CaseAny (Data.Diverse.Many.Internal.CaseAmendN indices larger (GHC.Types.Int, Data.Diverse.Many.Internal.WrappedAny) n) ((x, y) : zs)
instance forall k (indices :: [GHC.Types.Nat]) (larger :: [*]) (r :: k) (n :: GHC.Types.Nat) z (zs :: [*]). Data.Diverse.Reiterate.ReiterateN (Data.Diverse.Many.Internal.CaseAmendN indices larger r) n (z : zs)
instance forall k (indices :: [GHC.Types.Nat]) (larger :: [*]) (r :: k) (n :: GHC.Types.Nat) x (xs :: [*]). Data.Diverse.Reiterate.ReiterateN (Data.Diverse.Many.Internal.CaseAmendN' indices larger r) n (x : xs)
instance forall k (larger :: [*]) (r :: k) z (zs :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Many.Internal.CaseAmend larger r) (z : zs)
instance forall k (larger :: [*]) (r :: k) x (xs :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Many.Internal.CaseAmend' larger r) (x : xs)
instance forall k (indices :: [GHC.Types.Nat]) (smaller :: [*]) (r :: k) (n :: GHC.Types.Nat) x (xs :: [*]). Data.Diverse.Reiterate.ReiterateN (Data.Diverse.Many.Internal.CaseSelectN indices smaller r) n (x : xs)
instance forall k (smaller :: [*]) (larger :: [*]) (r :: k) x (xs :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Many.Internal.CaseSelect smaller larger r) (x : xs)
instance Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorN c n '[]) r
instance (Data.Diverse.Case.Case (c r n) (x : xs), Data.Diverse.Reiterate.ReiterateN (c r) n (x : xs), Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorN c (n GHC.TypeNats.+ 1) xs) r, r ~ Data.Diverse.TypeLevel.CaseResult (c r n) x) => Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorN c n (x : xs)) r
instance Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.Collector c '[]) r
instance (Data.Diverse.Case.Case (c r) (x : xs), Data.Diverse.Reiterate.Reiterate (c r) (x : xs), Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.Collector c xs) r, r ~ Data.Diverse.TypeLevel.CaseResult (c r) x) => Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.Collector c (x : xs)) r
instance forall k (c :: * -> k -> [*] -> *) (n :: k) r. Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorAnyN c n '[]) r
instance (Data.Diverse.Many.Internal.CaseAny (c r n) (x : xs), Data.Diverse.Reiterate.ReiterateN (c r) n (x : xs), Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorAnyN c (n GHC.TypeNats.+ 1) xs) r, r ~ Data.Diverse.TypeLevel.CaseResult (c r n) GHC.Types.Any) => Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorAnyN c n (x : xs)) r
instance Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorAny c '[]) r
instance (Data.Diverse.Many.Internal.CaseAny (c r) (x : xs), Data.Diverse.Reiterate.Reiterate (c r) (x : xs), Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorAny c xs) r, r ~ Data.Diverse.TypeLevel.CaseResult (c r) GHC.Types.Any) => Data.Diverse.AFoldable.AFoldable (Data.Diverse.Many.Internal.CollectorAny c (x : xs)) r
instance Data.Diverse.Many.Internal.CanAppendUnique xs '[]
instance (Data.Diverse.TypeLevel.MaybeUniqueMember y xs, Data.Diverse.Many.Internal.CanAppendUnique (Data.Diverse.TypeLevel.SnocUnique xs y) ys, Data.Diverse.TypeLevel.AppendUnique (Data.Diverse.TypeLevel.SnocUnique xs y) ys ~ Data.Diverse.TypeLevel.AppendUnique xs (y : ys)) => Data.Diverse.Many.Internal.CanAppendUnique xs (y : ys)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[] ()
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a] a
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b] (a, b)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c] (a, b, c)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d] (a, b, c, d)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e] (a, b, c, d, e)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f] (a, b, c, d, e, f)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g] (a, b, c, d, e, f, g)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h] (a, b, c, d, e, f, g, h)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i] (a, b, c, d, e, f, g, h, i)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i, j] (a, b, c, d, e, f, g, h, i, j)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i, j, k] (a, b, c, d, e, f, g, h, i, j, k)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i, j, k, l] (a, b, c, d, e, f, g, h, i, j, k, l)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i, j, k, l, m] (a, b, c, d, e, f, g, h, i, j, k, l, m)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i, j, k, l, m, n] (a, b, c, d, e, f, g, h, i, j, k, l, m, n)
instance Data.Diverse.Many.Internal.IsMany Data.Tagged.Tagged '[a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
instance Data.Diverse.AFunctor.AFunctor Data.Diverse.Many.Internal.Many_ c '[]
instance (Data.Diverse.Reiterate.Reiterate c (a : as), Data.Diverse.AFunctor.AFunctor Data.Diverse.Many.Internal.Many_ c as, Data.Diverse.Case.Case c (a : as)) => Data.Diverse.AFunctor.AFunctor Data.Diverse.Many.Internal.Many_ c (a : as)
instance Data.Diverse.AFunctor.AFunctor Data.Diverse.Many.Internal.Many_ c as => Data.Diverse.AFunctor.AFunctor Data.Diverse.Many.Internal.Many c as
instance GHC.Classes.Eq (Data.Diverse.Many.Internal.Many_ '[])
instance (GHC.Classes.Eq x, GHC.Classes.Eq (Data.Diverse.Many.Internal.Many_ xs)) => GHC.Classes.Eq (Data.Diverse.Many.Internal.Many_ (x : xs))
instance GHC.Classes.Eq (Data.Diverse.Many.Internal.Many_ xs) => GHC.Classes.Eq (Data.Diverse.Many.Internal.Many xs)
instance GHC.Classes.Ord (Data.Diverse.Many.Internal.Many_ '[])
instance (GHC.Classes.Ord x, GHC.Classes.Ord (Data.Diverse.Many.Internal.Many_ xs)) => GHC.Classes.Ord (Data.Diverse.Many.Internal.Many_ (x : xs))
instance GHC.Classes.Ord (Data.Diverse.Many.Internal.Many_ xs) => GHC.Classes.Ord (Data.Diverse.Many.Internal.Many xs)
instance Data.Semigroup.Semigroup (Data.Diverse.Many.Internal.Many_ '[])
instance (Data.Semigroup.Semigroup x, Data.Semigroup.Semigroup (Data.Diverse.Many.Internal.Many_ xs)) => Data.Semigroup.Semigroup (Data.Diverse.Many.Internal.Many_ (x : xs))
instance Data.Semigroup.Semigroup (Data.Diverse.Many.Internal.Many_ xs) => Data.Semigroup.Semigroup (Data.Diverse.Many.Internal.Many xs)
instance GHC.Base.Monoid (Data.Diverse.Many.Internal.Many_ '[])
instance (GHC.Base.Monoid x, GHC.Base.Monoid (Data.Diverse.Many.Internal.Many_ xs)) => GHC.Base.Monoid (Data.Diverse.Many.Internal.Many_ (x : xs))
instance GHC.Base.Monoid (Data.Diverse.Many.Internal.Many_ xs) => GHC.Base.Monoid (Data.Diverse.Many.Internal.Many xs)
instance GHC.Show.Show (Data.Diverse.Many.Internal.Many_ '[])
instance (GHC.Show.Show x, GHC.Show.Show (Data.Diverse.Many.Internal.Many_ xs)) => GHC.Show.Show (Data.Diverse.Many.Internal.Many_ (x : xs))
instance GHC.Show.Show (Data.Diverse.Many.Internal.Many_ xs) => GHC.Show.Show (Data.Diverse.Many.Internal.Many xs)
instance GHC.Read.Read (Data.Diverse.Many.Internal.Many_ '[])
instance (GHC.Read.Read x, GHC.Read.Read (Data.Diverse.Many.Internal.Many_ xs)) => GHC.Read.Read (Data.Diverse.Many.Internal.Many_ (x : xs))
instance GHC.Read.Read (Data.Diverse.Many.Internal.Many_ xs) => GHC.Read.Read (Data.Diverse.Many.Internal.Many xs)
instance GHC.Generics.Generic (Data.Diverse.Many.Internal.Many '[])
instance GHC.Generics.Generic (Data.Diverse.Many.Internal.Many (x : xs))
instance Control.DeepSeq.NFData (Data.Diverse.Many.Internal.Many '[])
instance (Control.DeepSeq.NFData x, Control.DeepSeq.NFData (Data.Diverse.Many.Internal.Many xs)) => Control.DeepSeq.NFData (Data.Diverse.Many.Internal.Many (x : xs))


-- | Re-export Many without the constructor
module Data.Diverse.Many

-- | A Many is an anonymous product type (also know as polymorphic record),
--   with no limit on the number of fields.
--   
--   The following functions are available can be used to manipulate unique
--   fields
--   
--   <ul>
--   <li>getter/setter for single field: <a>fetch</a> and
--   <a>replace</a></li>
--   <li>getter/setter for multiple fields: <a>select</a> and
--   <a>amend</a></li>
--   <li>folds: <a>forMany</a> or <a>collect</a></li>
--   </ul>
--   
--   These functions are type specified. This means labels are not required
--   because the types themselves can be used to access the 'Many. It is a
--   compile error to use those functions for duplicate fields.
--   
--   For duplicate fields, Nat-indexed versions of the functions are
--   available:
--   
--   <ul>
--   <li>getter/setter for single field: <a>fetchN</a> and
--   <a>replaceN</a></li>
--   <li>getter/setter for multiple fields: <a>selectN</a> and
--   <a>amendN</a></li>
--   <li>folds: <a>forManyN</a> or <a>collectN</a></li>
--   </ul>
--   
--   Encoding: The record is encoded as (S.Seq Any). This encoding should
--   reasonabily efficient for any number of fields.
--   
--   The map Key is index + offset of the type in the typelist. The Offset
--   is used to allow efficient cons <a>prefix</a>.
--   
--   <pre>
--   Key = Index of type in typelist + Offset
--   </pre>
--   
--   The constructor will guarantee the correct number and types of the
--   elements. The constructor is only exported in the
--   <a>Data.Diverse.Many.Internal</a> module
data Many (xs :: [Type])

-- | This instance allows converting to and from Many There are instances
--   for converting tuples of up to size 15.
class IsMany t xs a
toMany :: IsMany t xs a => t xs a -> Many xs
fromMany :: IsMany t xs a => Many xs -> t xs a

-- | Converts from a Many to a value (eg a tuple), via a Tagged wrapper
fromMany' :: IsMany Tagged xs a => Many xs -> a

-- | Converts from a value (eg a tuple) to a <a>Many</a>, via a
--   <a>Tagged</a> wrapper
toMany' :: IsMany Tagged xs a => a -> Many xs

-- | Analogous to <a>null</a>. Named <a>nil</a> to avoid conflicting with
--   <a>null</a>.
nil :: Many '[]

-- | Create a Many from a single value. Analogous to <a>singleton</a>
single :: x -> Many '[x]

-- | Add an element to the left of a Many. Not named <tt>cons</tt> to avoid
--   conflict with <a>cons</a>
prefix :: x -> Many xs -> Many (x : xs)
infixr 5 `prefix`

-- | Infix version of <a>prefix</a>.
--   
--   Mnemonic: Element on the left is smaller <a>./</a> than the larger
--   <a>Many</a> to the right.
(./) :: x -> Many xs -> Many (x : xs)
infixr 5 ./

-- | Add an element to the right of a Many Not named <tt>snoc</tt> to avoid
--   conflict with <a>snoc</a>
postfix :: Many xs -> y -> Many (Append xs '[y])
infixl 5 `postfix`

-- | Add an element to the right of a Many iff the field doesn't already
--   exist.
postfix' :: forall y xs. MaybeUniqueMember y xs => Many xs -> y -> Many (SnocUnique xs y)
infixl 5 `postfix'`

-- | Infix version of <a>postfix</a>.
--   
--   Mnemonic: Many is larger <a>\.</a> than the smaller element
(\.) :: Many xs -> y -> Many (Append xs '[y])
infixl 5 \.

-- | Appends two Manys together
append :: Many xs -> Many ys -> Many (Append xs ys)
infixr 5 `append`
class CanAppendUnique xs ys

-- | Appends the unique fields fields from the right Many using
--   <a>postfix'</a>
append' :: CanAppendUnique xs ys => Many xs -> Many ys -> Many (AppendUnique xs ys)

-- | Infix version of <a>append</a>.
--   
--   Mnemonic: <a>prefix</a> <a>./</a> with an extra slash (meaning
--   <a>Many</a>) in front.
(/./) :: Many xs -> Many ys -> Many (Append xs ys)
infixr 5 /./

-- | Split a non-empty Many into the first element, then the rest of the
--   Many. Analogous to <a>viewl</a>
viewf :: Many (x : xs) -> (x, Many xs)

-- | Split a non-empty Many into initial part of Many, and the last
--   element. Analogous to <a>viewr</a>
viewb :: Many (x : xs) -> (Many (Init (x : xs)), Last (x : xs))

-- | Extract the first element of a Many, which guaranteed to be non-empty.
--   Analogous to <a>head</a>
front :: Many (x : xs) -> x

-- | Extract the <a>back</a> element of a Many, which guaranteed to be
--   non-empty. Analogous to <a>last</a>
back :: Many (x : xs) -> Last (x : xs)

-- | Extract the elements after the front of a Many, which guaranteed to be
--   non-empty. Analogous to <a>tail</a>
aft :: Many (x : xs) -> Many xs

-- | Return all the elements of a Many except the <a>back</a> one, which
--   guaranteed to be non-empty. Analogous to <a>init</a>
fore :: Many (x : xs) -> Many (Init (x : xs))

-- | Getter by unique type. Get the field with type <tt>x</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>fetch</a> @Int x `shouldBe` 5
--   </pre>
fetch :: forall x xs. UniqueMember x xs => Many xs -> x

-- | Getter by label. Get the value of the field with tag <tt>label</tt>
--   which can be any type not just <tt>KnownSymbol</tt>.
--   
--   <pre>
--   let y = False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @<a>Hi</a> True <a>./</a> <a>nil</a>
--   <a>fetchL</a> @Foo y `shouldBe` Tagged @Foo 'X'
--   <a>fetchL</a> @<a>Hi</a> y `shouldBe` Tagged @<a>Hi</a> True
--   </pre>
fetchL :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> x

-- | Variation of <a>fetchL</a> specialized for <a>Tagged</a> that untags
--   the field.
fetchTag :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Many xs -> x

-- | Getter by index. Get the value of the field at index type-level Nat
--   <tt>n</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>fetchN</a> @1 x `shouldBe` False
--   </pre>
fetchN :: forall n x xs. MemberAt n x xs => Many xs -> x

-- | Polymorphic setter by unique type. Set the field with type <tt>x</tt>,
--   and replace with type <tt>y</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>replace</a> @Int x (Just True) `shouldBe` Just True <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   </pre>
replace :: forall x y xs. UniqueMember x xs => Many xs -> y -> Many (Replace x y xs)

-- | Setter by unique type. Set the field with type <tt>x</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>replace'</a> @Int x 6 `shouldBe` (6 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   </pre>
replace' :: forall x xs. UniqueMember x xs => Many xs -> x -> Many xs

-- | Polymorphic setter by unique type. Set the field with type <tt>x</tt>,
--   and replace with type <tt>y</tt>
--   
--   <pre>
--   let y = (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" (6 :: Int) <a>./</a> <a>nil</a>
--   replaceL @Foo y (Tagged @Bar 'Y') <tt>shouldBe</tt>
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged <tt>Bar <tt>Y</tt> <a>./</a> Tagged </tt><a>Hello</a> (6 :: Int) <a>./</a> <a>nil</a>
--   replaceL @"Hello" y (Tagged @"Hello" False) `shouldBe`
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" False <a>./</a> <a>nil</a>
--   </pre>
replaceL :: forall l y xs x. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> y -> Many (Replace x y xs)

-- | Setter by unique label. Set the field with label <tt>l</tt>.
--   
--   <pre>
--   let y = (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" (6 :: Int) <a>./</a> <a>nil</a>
--   <a>replaceL'</a> @Foo y (Tagged @Foo 'Y') `shouldBe`
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'Y' <a>./</a> Tagged @"Hello" (6 :: Int) <a>./</a> <a>nil</a>
--   <a>replaceL'</a> @"Hello" y (Tagged @"Hello" 7) `shouldBe`
--       (5 :: Int) <a>./</a> False <a>./</a> Tagged @Foo 'X' <a>./</a> Tagged @"Hello" (7 :: Int) <a>./</a> <a>nil</a>
--   </pre>
replaceL' :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> x -> Many xs

-- | Variation of <a>replaceL</a> specialized to <a>Tagged</a> that
--   automatically tags the value to be replaced.
replaceTag :: forall l x y xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Many xs -> y -> Many (Replace x (Tagged l y) xs)

-- | Variation of <a>replaceL'</a> specialized to <a>Tagged</a> that
--   automatically tags the value to be replaced.
replaceTag' :: forall l xs x. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Many xs -> x -> Many xs

-- | Polymorphic version of <a>replaceN'</a>
replaceN :: forall n x y xs. MemberAt n x xs => Many xs -> y -> Many (ReplaceIndex n y xs)

-- | Setter by index. Set the value of the field at index type-level Nat
--   <tt>n</tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>replaceN'</a> @0 x 7 <tt>shouldBe</tt>
--   </pre>
replaceN' :: forall n x xs. MemberAt n x xs => Many xs -> x -> Many xs

-- | A friendlier type constraint synomyn for <a>select</a>
type Select (smaller :: [Type]) (larger :: [Type]) = (AFoldable (CollectorAny (CaseSelect smaller larger) larger) (Maybe (Int, WrappedAny)))

-- | Construct a <a>Many</a> with a smaller number of fields than the
--   original. Analogous to <a>fetch</a> getter but for multiple fields.
--   
--   This can also be used to reorder fields in the original <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   <a>select</a> @'[Bool, Char] x `shouldBe` False <a>./</a> 'X' <a>./</a> <a>nil</a>
--   </pre>
select :: forall smaller larger. Select smaller larger => Many larger -> Many smaller

-- | A variation of <a>select</a> which selects by labels
--   
--   <pre>
--   let x = False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Bye" <tt>O</tt> <a>./</a> <a>nil</a>
--   <a>selectL</a> @'[Foo, Bar] x `shouldBe` Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> <a>nil</a>
--   <a>selectL</a> @'["Hi", "Bye"] x `shouldBe` Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   </pre>
selectL :: forall ls smaller larger. (Select smaller larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger) => Many larger -> Many smaller

-- | A friendlier type constraint synomyn for <a>selectN</a>
type SelectN (ns :: [Nat]) (smaller :: [Type]) (larger :: [Type]) = (AFoldable (CollectorAnyN (CaseSelectN ns smaller) 0 larger) (Maybe (Int, WrappedAny)), smaller ~ KindsAtIndices ns larger, IsDistinct ns)

-- | A variation of <a>select</a> which uses a Nat list <tt>n</tt> to
--   specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx@
--   </pre>
--   
--   This variation allows <tt>smaller</tt> or <tt>larger</tt> to contain
--   indistinct since the mapping is specified by <tt>indicies</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   <a>selectN</a> @'[5, 4, 0] x `shouldBe` Just 'A' <a>./</a> (6 :: Int) <a>./</a> (5 ::Int) <a>./</a> <a>nil</a>
--   </pre>
selectN :: forall ns smaller larger. SelectN ns smaller larger => Many larger -> Many smaller

-- | A friendlier type constraint synomyn for <a>amend</a>
type Amend smaller smaller' larger = (AFoldable (CollectorAny (CaseAmend larger) (Zip smaller smaller')) (Int, WrappedAny), IsDistinct smaller)

-- | Polymorphic version of <a>amend'</a>. Analogous to <a>replace</a>
--   setter but for multiple fields.
amend :: forall smaller smaller' larger larger'. (Amend smaller smaller' larger, larger' ~ Replaces smaller smaller' larger) => Many larger -> Many smaller' -> Many larger'

-- | A friendlier type constraint synomyn for <a>amend'</a>
type Amend' smaller larger = (AFoldable (CollectorAny (CaseAmend' larger) smaller) (Int, WrappedAny), IsDistinct smaller)

-- | Sets the subset of <a>Many</a> in the larger <a>Many</a>. Analogous to
--   <a>replace</a> setter but for multiple fields.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> <a>nil</a>
--   <a>amend'</a> @'[Int, Maybe Char] x ((6 :: Int) <a>./</a> Just 'P' <a>./</a> <a>nil</a>) `shouldBe`
--       (6 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'P' <a>./</a> <a>nil</a>
--   </pre>
amend' :: forall smaller larger. Amend' smaller larger => Many larger -> Many smaller -> Many larger

-- | A variation of <a>amend</a> which amends via labels.
--   
--   <pre>
--   let x = False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar <tt>X</tt> <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   <a>amendL</a> @'[Foo, Bar] x ('Y' <a>./</a> True <a>./</a> <tt>ni</tt>l) `shouldBe`
--       False <a>./</a> Tagged @"Hi" (5 :: Int) <a>./</a> 'Y' <a>./</a> True <a>./</a> Tagged @"Bye" 'O' <a>./</a> <a>nil</a>
--   <a>amendL</a> @'["Hi", "Bye"] x (True <a>./</a> Tagged @"Changed" True <a>./</a> <a>nil</a>) `shouldBe`
--       False <a>./</a> True <a>./</a> Tagged @Foo False <a>./</a> Tagged @Bar 'X' <a>./</a> Tagged @"Changed" True <a>./</a> <a>nil</a>
--   </pre>
amendL :: forall ls smaller smaller' larger larger'. (Amend smaller smaller' larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger, larger' ~ Replaces smaller smaller' larger) => Many larger -> Many smaller' -> Many larger'

-- | A variation of <a>amend'</a> which amends via labels.
--   
--   <pre>
--   let x = False .<i> Tagged @"Hi" (5 :: Int) .</i> Tagged @Foo False .<i> Tagged @Bar 'X' .</i> Tagged @"Bye" 'O' ./ <a>nil</a>
--   <a>amendL</a> @'[Foo, Bar] x (Tagged @Foo True .<i> Tagged @Bar 'Y' .</i> nil) <tt>shouldBe</tt>
--       False .<i> Tagged @"Hi" (5 :: Int) .</i> Tagged @Foo True .<i> Tagged @Bar 'Y' .</i> Tagged @"Bye" 'O' ./ <a>nil</a>
--   <a>amendL</a> @'["Hi", "Bye"] x (Tagged @"Hi" (6 :: Int) .<i> Tagged @"Bye" 'P' .</i> nil) <tt>shouldBe</tt>
--       False .<i> Tagged @"Hi" (6 :: Int) .</i> Tagged @Foo False .<i> Tagged @Bar 'X' .</i> Tagged @"Bye" 'P' ./ <a>nil</a>
--   </pre>
amendL' :: forall ls smaller larger. (Amend' smaller larger, smaller ~ KindsAtLabels ls larger, IsDistinct ls, UniqueLabels ls larger) => Many larger -> Many smaller -> Many larger

-- | A friendlier type constraint synomyn for <a>amendN</a>
type AmendN ns smaller smaller' larger = (AFoldable (CollectorAnyN (CaseAmendN ns larger) 0 (Zip smaller smaller')) (Int, WrappedAny), smaller ~ KindsAtIndices ns larger, IsDistinct ns)

-- | A polymorphic variation of <a>amendN'</a>
amendN :: forall ns smaller smaller' larger larger'. (AmendN ns smaller smaller' larger, larger' ~ ReplacesIndex ns smaller' larger) => Many larger -> Many smaller' -> Many larger'

-- | A friendlier type constraint synomyn for <a>amendN'</a>
type AmendN' ns smaller larger = (AFoldable (CollectorAnyN (CaseAmendN' ns larger) 0 smaller) (Int, WrappedAny), smaller ~ KindsAtIndices ns larger, IsDistinct ns)

-- | A variation of <a>amend'</a> which uses a Nat list <tt>n</tt> to
--   specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx@
--   </pre>
--   
--   This variation allows <tt>smaller</tt> or <tt>larger</tt> to contain
--   indistinct since the mapping is specified by <tt>indicies</tt>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--   <a>amendN'</a> @'[5, 4, 0] x (Just 'B' <a>./</a> (8 :: Int) <a>./</a> (4 ::Int) <a>./</a> <a>nil</a>) `shouldBe`
--       (4 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (8 :: Int) <a>./</a> Just 'B' <a>./</a> <a>nil</a>
--   </pre>
amendN' :: forall ns smaller larger. (AmendN' ns smaller larger) => Many larger -> Many smaller -> Many larger

-- | A friendlier type constraint synomyn for <a>collect</a> and
--   <a>forMany</a>
type Collect c r (xs :: [Type]) = (AFoldable (Collector c xs) r, Case (c r) xs)

-- | Collects the output from <a>case'</a>ing each field in a <a>Many</a>.
--   Uses <a>Reiterate</a> to prepare the <a>Case</a> to accept the next
--   type in the <tt>xs</tt> typelist.
--   
--   Internally, this holds the left-over [(k, v)] from the original
--   <a>Many</a> for the remaining typelist <tt>xs</tt>.
--   
--   That is, the first v in the (k, v) is of type <tt>x</tt>, and the
--   length of the list is equal to the length of <tt>xs</tt>.
data Collector c (xs :: [Type]) r

-- | Folds any <a>Many</a>, even with indistinct types. Given
--   <b>distinct</b> handlers for the fields in <a>Many</a>, create
--   <a>AFoldable</a> of the results of running the handlers over the
--   fields in <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Bool <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>forMany</a> (<a>cases</a> y) x) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
forMany :: Collect c r xs => c r xs -> Many xs -> Collector c xs r

-- | This is <tt>flip <a>forMany</a></tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Bool <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>collect</a> x (<a>cases</a> y)) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
collect :: (Collect c r xs) => Many xs -> c r xs -> Collector c xs r

-- | A friendlier type constraint synomyn for <a>collect</a> and
--   <a>forMany</a>
type CollectN c r (n :: Nat) (xs :: [Type]) = (AFoldable (CollectorN c n xs) r, Case (c r n) xs)

-- | A variation of <a>Collector</a> which uses <a>ReiterateN</a> instead
--   of <a>Reiterate</a>
data CollectorN c (n :: Nat) (xs :: [Type]) r

-- | Folds any <a>Many</a>, even with indistinct types. Given <b>index</b>
--   handlers for the fields in <a>Many</a>, create <a>AFoldable</a> of the
--   results of running the handlers over the fields in <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Bool <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Int <a>./</a> show @(Maybe Char) <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>forManyN</a> (<a>casesN</a> y) x) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
forManyN :: CollectN c r n xs => c r n xs -> Many xs -> CollectorN c n xs r

-- | This is <tt>flip <a>forManyN</a></tt>
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <a>nil</a>
--       y = show @Int <a>./</a> show @Bool <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Int <a>./</a> show @(Maybe Char) <a>./</a> <a>nil</a>
--   <a>afoldr</a> (:) [] (<a>collectN</a> x (<a>casesN</a> y)) `shouldBe`
--       ["5", "False", "'X'", "Just 'O'", "6", "Just 'A'"]
--   </pre>
collectN :: CollectN c r n xs => Many xs -> c r n xs -> CollectorN c n xs r

module Data.Diverse.Cases

-- | Contains a <a>Many</a> of handlers/continuations for all the types in
--   the <tt>xs</tt> typelist. This uses <b><a>fetch</a></b> to get the
--   unique handler for the type at the <a>Head</a> of <tt>xs</tt>.
--   
--   Use <a>cases</a> to construct this with <a>SameLength</a> constraint
--   to reduce programming confusion.
data Cases (fs :: [Type]) r (xs :: [Type])

-- | Create an instance of <a>Case</a> for either handling <a>switch</a>ing
--   a <tt>Which</tt>.
--   
--   <pre>
--   let y = <a>pick</a> (5 :: Int) :: <a>Which</a> '[Int, Bool]
--   <a>switch</a> y (
--       <a>cases</a> (show @Bool
--           <a>./</a> show @Int
--           <a>./</a> <tt>nul</tt>)) `shouldBe` "5"
--   </pre>
--   
--   Or for handling <a>collect</a> from a <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <tt>nul</tt>
--       y = show @Int <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Bool <a>./</a> <tt>nul</tt>
--   <a>afoldr</a> (:) [] (<a>collect</a> x (<a>cases</a> y)) `shouldBe`
--       ["5", "False", "<tt>X</tt>", "Just 'O'", "6", "Just 'A'"]
--   </pre>
--   
--   This function imposes additional <tt>SameLength</tt> constraints than
--   when using the <a>Cases</a> constructor directly. It is better
--   practice to use <a>cases</a> to prevent programming confusion with
--   dead code. However, the <a>Cases</a> constructor is still exported to
--   allow creating a master-of-all-<a>Case</a>.
cases :: forall r xs fs. (AllConstrained ((~) r) (CaseResults (Cases fs r) fs), SameLength fs (Nub xs)) => Many fs -> Cases fs r xs

-- | A variation of <a>cases</a> without the <tt>SameLength</tt> constraint
--   to allow creating a master-of-all-<a>Case</a>.
cases' :: forall r xs fs. (AllConstrained ((~) r) (CaseResults (Cases fs r) fs)) => Many fs -> Cases fs r xs

-- | A variation of <a>Cases</a> which uses <b><a>fetchN</a></b> to get the
--   handler by index. There may be different handlers for the same type,
--   but the handlers must be in the same order as the input <tt>xs</tt>
--   typelist. Use <a>casesN</a> to construct this safely ensuring
--   <tt>n</tt> starts at 0.
data CasesN (fs :: [Type]) r (n :: Nat) (xs :: [Type])

-- | Safe Constructor for <a>CasesN</a> ensuring that the <tt>n</tt> Nat
--   starts at 0. It is an instance of <tt>CaseN</tt> for either handling
--   <a>switchN</a>ing a <tt>Which</tt> in index order.
--   
--   <pre>
--   let y = <a>pickN</a> @0 Proxy (5 :: Int) :: Which '[Int, Bool, Bool, Int]
--   <a>switchN</a> y (
--       <a>casesN</a> (show @Int
--           <a>./</a> show @Bool
--           <a>./</a> show @Bool
--           <a>./</a> show @Int
--           <a>./</a> <tt>nul</tt>)) `shouldBe` "5"
--   </pre>
--   
--   Or for handling <a>collectN</a> from a <a>Many</a>.
--   
--   <pre>
--   let x = (5 :: Int) <a>./</a> False <a>./</a> 'X' <a>./</a> Just 'O' <a>./</a> (6 :: Int) <a>./</a> Just 'A' <a>./</a> <tt>nul</tt>
--       y = show @Int <a>./</a> show @Bool <a>./</a> show @Char <a>./</a> show @(Maybe Char) <a>./</a> show @Int <a>./</a> show @(Maybe Char) <a>./</a> <tt>nul</tt>
--   <a>afoldr</a> (:) [] (<a>collectN</a> x (<a>casesN</a> y)) `shouldBe`
--       ["5", "False", "<tt>X</tt>", "Just 'O'", "6", "Just 'A'"]
--   </pre>
casesN :: forall r xs fs. (AllConstrained ((~) r) (CaseResults (CasesN fs r 0) fs), SameLength fs xs) => Many fs -> CasesN fs r 0 xs

-- | A variation of <a>casesN</a> without the <tt>SameLength</tt>
--   constraint to allow creating a master-of-all-<a>Case</a>.
casesN' :: forall r xs fs. (AllConstrained ((~) r) (CaseResults (CasesN fs r 0) fs)) => Many fs -> CasesN fs r 0 xs
instance Data.Diverse.Reiterate.ReiterateN (Data.Diverse.Cases.CasesN fs r) n xs
instance Data.Diverse.TypeLevel.MemberAt n (Data.Diverse.TypeLevel.Head xs -> r) fs => Data.Diverse.Case.Case (Data.Diverse.Cases.CasesN fs r n) xs
instance Data.Diverse.Reiterate.Reiterate (Data.Diverse.Cases.Cases fs r) xs
instance Data.Diverse.TypeLevel.UniqueMember (Data.Diverse.TypeLevel.Head xs -> r) fs => Data.Diverse.Case.Case (Data.Diverse.Cases.Cases fs r) xs

module Data.Diverse.Which.Internal

-- | A <a>Which</a> is an anonymous sum type (also known as a polymorphic
--   variant, or co-record) which can only contain one of the types in the
--   typelist. This is essentially a typed version of <a>Dynamic</a>.
--   
--   The following functions are available can be used to manipulate unique
--   types in the typelist
--   
--   <ul>
--   <li>constructor: <a>pick</a></li>
--   <li>destructor: <a>trial</a></li>
--   <li>injection: <a>diversify</a> and <a>reinterpret</a></li>
--   <li>catamorphism: <a>which</a> or <a>switch</a></li>
--   </ul>
--   
--   These functions are type specified. This means labels are not required
--   because the types themselves can be used to access the <a>Which</a>.
--   It is a compile error to use those functions for duplicate fields.
--   
--   For duplicate types in the list of possible types, Nat-indexed version
--   of the functions are available:
--   
--   <ul>
--   <li>constructor: <a>pickN</a></li>
--   <li>destructor: <a>trialN</a></li>
--   <li>inejction: <a>diversifyN</a> and <tt>reinterpretN</tt></li>
--   <li>catamorphism: <a>whichN</a> or <a>switchN</a></li>
--   </ul>
--   
--   Encoding: The variant contains a value whose type is at the given
--   position in the type list. This is the same encoding as
--   <a>Haskus.Util.Variant</a> and <a>Data.Hlist.Variant</a>.
--   
--   The constructor is only exported in the
--   <a>Data.Diverse.Which.Internal</a> module
data Which (xs :: [Type])
Which :: {-# UNPACK #-} !Int -> Any -> Which

-- | Analogous to <a>absurd</a>. Renamed <a>impossible</a> to avoid
--   conflicts.
--   
--   Since 'Which '[]' values logically don't exist, this witnesses the
--   logical reasoning tool of "ex falso quodlibet", ie "from falsehood,
--   anything follows".
--   
--   A 'Which '[]' is a <a>Which</a> with no alternatives, which may occur
--   as a <a>Left</a>-over from <a>trial</a>ing a <tt>Which '[x]</tt> with
--   one type. It is an uninhabited type, just like <a>Void</a>
impossible :: Which '[] -> a

-- | Lift a value into a <a>Which</a> of possibly other types <tt>xs</tt>.
--   <tt>xs</tt> can be inferred or specified with TypeApplications. NB.
--   forall is used to specify <tt>xs</tt> first, so TypeApplications can
--   be used to specify <tt>xs</tt> first
--   
--   <pre>
--   <a>pick</a> 'A' @_ @'[Int, Bool, Char, Maybe String] :: Which '[Int, Bool, Char, Maybe String]
--   </pre>
pick :: forall x xs. UniqueMember x xs => x -> Which xs

-- | A variation of <a>pick</a> into a <a>Which</a> where <tt>x</tt> is the
--   first type.
--   
--   <pre>
--   <a>pick0</a> 'A' :: Which '[Char, Int, Bool]
--   </pre>
pick0 :: x -> Which (x : xs)

-- | A variation of <a>pick</a> into a <a>Which</a> of a single type.
--   
--   <pre>
--   <a>pickOnly</a> 'A' :: Which '[Char]
--   </pre>
pickOnly :: x -> Which '[x]

-- | A variation of <a>pick</a> where <tt>x</tt> is specified via a label
--   
--   <pre>
--   let y = <a>pickL</a> @Foo (Tagged (5 :: Int)) :: Which '[Bool, Tagged Foo Int, Tagged Bar Char]
--       x = <a>trialL</a> @Foo y
--   x <tt>shouldBe</tt> (Right (Tagged 5))
--   </pre>
pickL :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => x -> Which xs

-- | Variation of <a>pickL</a> specialized to <a>Tagged</a> that
--   automatically tags the value.
pickTag :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => x -> Which xs

-- | Lift a value into a <a>Which</a> of possibly other (possibley
--   indistinct) types, where the value is the <tt>n</tt>-th type.
--   
--   <pre>
--   <a>pickN</a> @4 (5 :: Int) :: Which '[Bool, Int, Char, Bool, Int, Char]
--   </pre>
pickN :: forall n x xs. MemberAt n x xs => x -> Which xs

-- | It is <a>obvious</a> what value is inside a <a>Which</a> of one type.
--   
--   <pre>
--   let x = <tt>pick'</tt> 'A' :: Which '[Char]
--   <a>obvious</a> x `shouldBe` 'A'
--   </pre>
obvious :: Which '[a] -> a

-- | <a>trial</a> a type in a <a>Which</a> and <a>Either</a> get the
--   <a>Right</a> value or the <a>Left</a>-over possibilities.
--   
--   <pre>
--   let x = <a>pick</a> 'A' @'[Int, Bool, Char, Maybe String] :: <a>Which</a> '[Int, Bool, Char, Maybe String]
--   <a>trial</a> @Char x `shouldBe` Right 'A'
--   <a>trial</a> @Int x `shouldBe` Left (<a>pick</a> 'A') :: <a>Which</a> '[Bool, Char, Maybe String]
--   </pre>
trial :: forall x xs. (UniqueMember x xs) => Which xs -> Either (Which (Remove x xs)) x

-- | Variation of <a>trial</a> which returns a Maybe
trial' :: forall x xs. (UniqueMember x xs) => Which xs -> Maybe x

-- | A variation of a <a>Which</a> <a>trial</a> which <a>trial</a>s the
--   first type in the type list.
--   
--   <pre>
--   let x = <a>pick</a> 'A' @'[Int, Bool, Char, Maybe String] :: <a>Which</a> '[Int, Bool, Char, Maybe String]
--   <a>trial0</a> x `shouldBe` Left (<a>pick</a> 'A') :: <a>Which</a> '[Bool, Char, Maybe String]
--   </pre>
trial0 :: forall x xs. Which (x : xs) -> Either (Which xs) x

-- | Variation of <a>trial0</a> which returns a Maybe
trial0' :: forall x xs. Which (x : xs) -> Maybe x

-- | A variation of <a>trial</a> where x is specified via a label
--   
--   <pre>
--   let y = <a>pickL</a> @Foo (Tagged (5 :: Int)) :: Which '[Bool, Tagged Foo Int, Tagged Bar Char]
--       x = <a>trialL</a> @Foo Proxy y
--   x <tt>shouldBe</tt> (Right (Tagged 5))
--   </pre>
trialL :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Which xs -> Either (Which (Remove x xs)) x

-- | Variation of <a>trialL</a> which returns a Maybe
trialL' :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Which xs -> Maybe x

-- | Variation of <a>trialL</a> specialized to <a>Tagged</a> which untags
--   the field.
trialTag :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Which xs -> Either (Which (Remove (Tagged l x) xs)) x

-- | Variation of <a>trialL'</a> specialized to <a>Tagged</a> which untags
--   the field.
trialTag' :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Which xs -> Maybe x

-- | <a>trialN</a> the n-th type of a <a>Which</a>, and get <a>Either</a>
--   the <a>Right</a> value or the <a>Left</a>-over possibilities.
--   
--   <pre>
--   let x = <a>pick</a> 'A' @_ @'[Int, Bool, Char, Maybe String] :: <a>Which</a> '[Int, Bool, Char, Maybe String]
--   <a>trialN</a> @1 x `shouldBe` Left (<a>pick</a> 'A') :: <a>Which</a> '[Int, Char, Maybe String]
--   </pre>
trialN :: forall n x xs. (MemberAt n x xs) => Which xs -> Either (Which (RemoveIndex n xs)) x

-- | Variation of <a>trialN</a> which returns a Maybe
trialN' :: forall n x xs. (MemberAt n x xs) => Which xs -> Maybe x

-- | A friendlier constraint synonym for <a>diversify</a>.
type Diversify (branch :: [Type]) (tree :: [Type]) = Switch (CaseDiversify branch tree) (Which tree) branch

-- | Convert a <a>Which</a> to another <a>Which</a> that may include other
--   possibilities. That is, <tt>branch</tt> is equal or is a subset of
--   <tt>tree</tt>.
--   
--   This can also be used to rearrange the order of the types in the
--   <a>Which</a>.
--   
--   It is a compile error if <tt>tree</tt> has duplicate types with
--   <tt>branch</tt>.
--   
--   NB. Use TypeApplications with <tt>_ to specify </tt>tree@.
--   
--   <pre>
--   let a = <tt>pick'</tt> (5 :: Int) :: <a>Which</a> '[Int]
--       b = <a>diversify</a> @_ @[Int, Bool] a :: <a>Which</a> '[Int, Bool]
--       c = <a>diversify</a> @_ @[Bool, Int] b :: <a>Which</a> '[Bool, Int]
--   </pre>
diversify :: forall branch tree. Diversify branch tree => Which branch -> Which tree

-- | A restricted version of <a>diversify</a> which only rearranges the
--   types
diversify' :: forall branch tree. (Diversify branch tree, SameLength branch tree) => Which branch -> Which tree

-- | A simple version of <a>diversify</a> which add another type to the
--   front of the typelist.
diversify0 :: forall x xs. Which xs -> Which (x : xs)

-- | A friendlier constraint synonym for <a>diversifyL</a>.
type DiversifyL (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Diversify branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | A variation of <a>diversify</a> where <tt>branch</tt>is additionally
--   specified by a labels list.
--   
--   <pre>
--   let y = <a>pickOnly</a> (5 :: Tagged Bar Int)
--       y' = <a>diversifyL</a> @'[Bar] y :: <a>Which</a> '[Tagged Bar Int, Tagged Foo Bool]
--       y'' = <a>diversifyL</a> @'[Bar, Foo] y' :: <a>Which</a> '[Tagged Foo Bool, Tagged Bar Int]
--   <a>switch</a> y'' (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` "Tagged * Bar Int"
--   </pre>
diversifyL :: forall ls branch tree. (DiversifyL ls branch tree) => Which branch -> Which tree

-- | A friendlier constraint synonym for <a>diversifyN</a>.
type DiversifyN (ns :: [Nat]) (branch :: [Type]) (tree :: [Type]) = (SwitchN Which (CaseDiversifyN ns) (Which tree) 0 branch, KindsAtIndices ns tree ~ branch)

-- | A variation of <a>diversify</a> which uses a Nat list <tt>indices</tt>
--   to specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx
--   </pre>
--   
--   This variation allows <tt>tree</tt> to contain duplicate types with
--   <tt>branch</tt> since the mapping is specified by <tt>indicies</tt>.
--   
--   <pre>
--   let y = <a>pickOnly</a> (5 :: Int)
--       y' = <a>diversifyN</a> @'[0] @_ @[Int, Bool] y
--       y'' = <a>diversifyN</a> @[1,0] @_ @[Bool, Int] y'
--   <a>switch</a> y'' (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` "Int"
--   </pre>
diversifyN :: forall ns branch tree. (DiversifyN ns branch tree) => Which branch -> Which tree

-- | A friendlier constraint synonym for <a>reinterpret</a>.
type Reinterpret (branch :: [Type]) (tree :: [Type]) = Switch (CaseReinterpret branch tree) (Either (Which (Complement tree branch)) (Which branch)) tree

-- | A variation of <a>Reinterpret</a> that exposes <tt>branchlessTree ~
--   Complement tree branch</tt>
type Reinterpreted branch tree branchlessTree = (Reinterpret branch tree, branchlessTree ~ Complement tree branch)

-- | Convert a <a>Which</a> into possibly another <a>Which</a> with a
--   totally different typelist. Returns either a <a>Which</a> with the
--   <a>Right</a> value, or a <a>Which</a> with the <a>Left</a>over
--   <tt>compliment</tt> types.
--   
--   It is a compile error if <tt>branch</tt> or <tt>compliment</tt> has
--   duplicate types with <tt>tree</tt>.
--   
--   NB. forall used to specify <tt>branch</tt> first, so TypeApplications
--   can be used to specify <tt>branch</tt> first.
--   
--   <pre>
--   let a = <a>pick</a> @[Int, Char, Bool] (5 :: Int) :: <a>Which</a> '[Int, Char, Bool]
--   let  b = <a>reinterpret</a> <tt>[String, Char] y
--   b `shouldBe` Left (<a>pick</a> (5 :: Int)) :: <a>Which</a> '[Int, Bool]
--   let c = <a>reinterpret</a> </tt>[String, Int] a
--   c `shouldBe` Right (<a>pick</a> (5 :: Int)) :: <a>Which</a> '[String, Int]
--   </pre>
reinterpret :: forall branch tree. (Reinterpret branch tree) => Which tree -> Either (Which (Complement tree branch)) (Which branch)

-- | A friendlier constraint synonym for <a>reinterpret'</a>.
type Reinterpret' (branch :: [Type]) (tree :: [Type]) = Switch (CaseReinterpret' branch tree) (Maybe (Which branch)) tree

-- | Variation of <a>reinterpret</a> which returns a Maybe.
reinterpret' :: forall branch tree. (Reinterpret' branch tree) => Which tree -> Maybe (Which branch)

-- | A friendlier constraint synonym for <a>reinterpretL</a>.
type ReinterpretL (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Reinterpret branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | A variation of <a>ReinterpretL</a> that exposes <tt>branchlessTree ~
--   Complement tree branch</tt>
type ReinterpretedL ls branch tree branchlessTree = (ReinterpretL ls branch tree, branchlessTree ~ Complement tree branch)

-- | A variation of <a>reinterpret</a> where the <tt>branch</tt> is
--   additionally specified with a labels list.
--   
--   <pre>
--   let y = <a>pick</a> @[Tagged Bar Int, Tagged Foo Bool, Tagged Hi Char, Tagged Bye Bool] (5 :: Tagged Bar Int)
--       y' = <a>reinterpretL</a> @[Foo, Bar] y
--       x = <a>pick</a> @[Tagged Foo Bool, Tagged Bar Int] (5 :: Tagged Bar Int)
--   y' `shouldBe` Right x
--   </pre>
reinterpretL :: forall ls branch tree. (ReinterpretL ls branch tree) => Which tree -> Either (Which (Complement tree branch)) (Which branch)

-- | A friendlier constraint synonym for <a>reinterpretL</a>.
type ReinterpretL' (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Reinterpret' branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | Variation of <a>reinterpretL</a> which returns a Maybe.
reinterpretL' :: forall ls branch tree. (ReinterpretL' ls branch tree) => Which tree -> Maybe (Which branch)

-- | A friendlier constraint synonym for <tt>reinterpretN</tt>.
type ReinterpretN' (ns :: [Nat]) (branch :: [Type]) (tree :: [Type]) = (SwitchN Which (CaseReinterpretN' ns) (Maybe (Which branch)) 0 tree, KindsAtIndices ns tree ~ branch)

-- | A limited variation of <a>reinterpret'</a> which uses a Nat list
--   <tt>n</tt> to specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx
--   </pre>
--   
--   This variation allows <tt>tree</tt> to contain duplicate types with
--   <tt>branch</tt> since the mapping is specified by <tt>indicies</tt>.
--   
--   However, unlike <tt>reinterpert</tt>, in this variation,
--   <tt>branch</tt> must be a subset of <tt>tree</tt> instead of any
--   arbitrary Which. Also it returns a Maybe instead of Either.
--   
--   This is so that the same <tt>indices</tt> can be used in
--   <tt>narrowN</tt>.
reinterpretN' :: forall ns branch tree. (ReinterpretN' ns branch tree) => Which tree -> Maybe (Which branch)

-- | A friendlier constraint synonym for <tt>reinterpretN</tt>.
type Switch c r xs = Reduce (Which xs) (Switcher c r xs)

-- | A switch/case statement for <a>Which</a>. This is equivalent to
--   <tt>flip <a>which</a></tt>
--   
--   Use <a>Case</a> instances like <a>Cases</a> to apply a <a>Which</a> of
--   functions to a variant of values.
--   
--   <pre>
--   let y = <a>pick</a> (5 :: Int) :: <a>Which</a> '[Int, Bool]
--   <a>switch</a> y (
--       <a>cases</a> (show @Bool
--           <a>./</a> show @Int
--           <a>./</a> <a>nil</a>)) `shouldBe` "5"
--   </pre>
--   
--   Or <a>CaseFunc</a> @<a>Typeable</a> to apply a polymorphic function
--   that work on all <tt>Typeable</tt>s.
--   
--   <pre>
--   let y = <a>pick</a> (5 :: Int) :: <a>Which</a> '[Int, Bool]
--   <a>switch</a> y (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` <a>Int</a>
--   </pre>
--   
--   Or you may use your own custom instance of <a>Case</a>.
switch :: Switch c r xs => Which xs -> c r xs -> r

-- | Catamorphism for <a>Which</a>. This is <tt>flip <a>switch</a></tt>.
which :: Switch c r xs => c r xs -> Which xs -> r

-- | <a>Switcher</a> is an instance of <a>Reduce</a> for which
--   <b><a>reiterate</a></b>s through the possibilities in a <a>Which</a>,
--   delegating handling to <a>Case</a>, ensuring termination when
--   <a>Which</a> only contains one type.
newtype Switcher c r (xs :: [Type])
Switcher :: (c r xs) -> Switcher c r

-- | A switch/case statement for <a>Which</a>. This is equivalent to
--   <tt>flip <a>whichN</a></tt>
--   
--   Use <a>Case</a> instances like <a>CasesN</a> to apply a <a>Which</a>
--   of functions to a variant of values in index order.
--   
--   <pre>
--   let y = <a>pickN</a> @0 (5 :: Int) :: <a>Which</a> '[Int, Bool, Bool, Int]
--   <a>switchN</a> y (
--       <a>casesN</a> (show @Int
--           <a>./</a> show @Bool
--           <a>./</a> show @Bool
--           <a>./</a> show @Int
--           <a>./</a> <a>nil</a>)) `shouldBe` "5"
--   </pre>
--   
--   Or you may use your own custom instance of <a>Case</a>.
class SwitchN w c r (n :: Nat) xs
switchN :: SwitchN w c r n xs => w xs -> c r n xs -> r
switchN :: SwitchN w c r n xs => w xs -> c r n xs -> r

-- | Catamorphism for <a>Which</a>. This is equivalent to <tt>flip
--   <a>switchN</a></tt>.
whichN :: SwitchN w c r n xs => c r n xs -> w xs -> r

-- | <a>SwitcherN</a> is a variation of <a>Switcher</a> which
--   <b><a>reiterateN</a></b>s through the possibilities in a <a>Which</a>,
--   delegating work to <tt>CaseN</tt>, ensuring termination when
--   <a>Which</a> only contains one type.
newtype SwitcherN c r (n :: Nat) (xs :: [Type])
SwitcherN :: (c r n xs) -> SwitcherN c r
instance GHC.Read.Read x => Data.Diverse.Which.Internal.WhichRead (Data.Diverse.Which.Internal.Which_ '[x])
instance (GHC.Read.Read x, Data.Diverse.Which.Internal.WhichRead (Data.Diverse.Which.Internal.Which_ (x' : xs))) => Data.Diverse.Which.Internal.WhichRead (Data.Diverse.Which.Internal.Which_ (x : x' : xs))
instance Data.Diverse.Which.Internal.WhichRead (Data.Diverse.Which.Internal.Which_ (x : xs)) => GHC.Read.Read (Data.Diverse.Which.Internal.Which (x : xs))
instance Data.Diverse.Which.Internal.Switch Data.Diverse.Which.Internal.CaseShowWhich GHC.Show.ShowS (x : xs) => GHC.Show.Show (Data.Diverse.Which.Internal.Which (x : xs))
instance forall k (r :: k) x (xs :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Which.Internal.CaseShowWhich r) (x : xs)
instance GHC.Show.Show x => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseShowWhich GHC.Show.ShowS) (x : xs)
instance (Data.Diverse.Which.Internal.Switch Data.Diverse.Which.Internal.CaseEqWhich GHC.Types.Bool (x : xs), Data.Diverse.Which.Internal.Switch Data.Diverse.Which.Internal.CaseOrdWhich GHC.Types.Ordering (x : xs)) => GHC.Classes.Ord (Data.Diverse.Which.Internal.Which (x : xs))
instance forall k (r :: k) x (xs :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Which.Internal.CaseOrdWhich r) (x : xs)
instance GHC.Classes.Ord x => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseOrdWhich GHC.Types.Ordering) (x : xs)
instance Data.Diverse.Which.Internal.Switch Data.Diverse.Which.Internal.CaseEqWhich GHC.Types.Bool (x : xs) => GHC.Classes.Eq (Data.Diverse.Which.Internal.Which (x : xs))
instance forall k (r :: k) x (xs :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Which.Internal.CaseEqWhich r) (x : xs)
instance GHC.Classes.Eq x => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseEqWhich GHC.Types.Bool) (x : xs)
instance Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which xs) (Data.Diverse.Which.Internal.SwitcherN c r n xs) => Data.Diverse.Which.Internal.SwitchN Data.Diverse.Which.Internal.Which c r n xs
instance (Data.Diverse.Case.Case (c r n) (x : x' : xs), Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which (x' : xs)) (Data.Diverse.Which.Internal.SwitcherN c r (n GHC.TypeNats.+ 1) (x' : xs)), Data.Diverse.Reiterate.ReiterateN (c r) n (x : x' : xs), r ~ Data.Diverse.TypeLevel.CaseResult (c r n) x) => Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which (x : x' : xs)) (Data.Diverse.Which.Internal.SwitcherN c r n (x : x' : xs))
instance (Data.Diverse.Case.Case (c r n) '[x], r ~ Data.Diverse.TypeLevel.CaseResult (c r n) x) => Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which '[x]) (Data.Diverse.Which.Internal.SwitcherN c r n '[x])
instance (Data.Diverse.Case.Case (c r) (x : x' : xs), Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which (x' : xs)) (Data.Diverse.Which.Internal.Switcher c r (x' : xs)), Data.Diverse.Reiterate.Reiterate (c r) (x : x' : xs), r ~ Data.Diverse.TypeLevel.CaseResult (c r) x) => Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which (x : x' : xs)) (Data.Diverse.Which.Internal.Switcher c r (x : x' : xs))
instance (Data.Diverse.Case.Case (c r) '[x], r ~ Data.Diverse.TypeLevel.CaseResult (c r) x) => Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which '[x]) (Data.Diverse.Which.Internal.Switcher c r '[x])
instance forall k (c :: k -> [*] -> *) (r :: k). Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which '[]) (Data.Diverse.Which.Internal.Switcher c r '[])
instance Data.Diverse.Reduce.Reduce (Data.Diverse.Which.Internal.Which (x : xs)) (Data.Diverse.Which.Internal.Switcher (Data.Diverse.CaseFunc.CaseFunc Control.DeepSeq.NFData) () (x : xs)) => Control.DeepSeq.NFData (Data.Diverse.Which.Internal.Which (x : xs))
instance forall k (indices :: [GHC.Types.Nat]) (r :: k) (n :: GHC.Types.Nat) (tree' :: [*]). Data.Diverse.Reiterate.ReiterateN (Data.Diverse.Which.Internal.CaseReinterpretN' indices r) n tree'
instance (Data.Diverse.TypeLevel.MaybeMemberAt n' x branch, n' ~ Data.Diverse.TypeLevel.PositionOf n indices) => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseReinterpretN' indices (GHC.Base.Maybe (Data.Diverse.Which.Internal.Which branch)) n) (x : tree)
instance forall k (branch :: [*]) (tree :: [*]) (r :: k) (tree' :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Which.Internal.CaseReinterpret' branch tree r) tree'
instance (Data.Diverse.TypeLevel.MaybeUniqueMember x branch, comp ~ Data.Diverse.TypeLevel.Complement tree branch, Data.Diverse.TypeLevel.Unique x tree) => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseReinterpret' branch tree (GHC.Base.Maybe (Data.Diverse.Which.Internal.Which branch))) (x : tree')
instance forall k (branch :: [*]) (tree :: [*]) (r :: k) (tree' :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Which.Internal.CaseReinterpret branch tree r) tree'
instance (Data.Diverse.TypeLevel.MaybeUniqueMember x branch, comp ~ Data.Diverse.TypeLevel.Complement tree branch, Data.Diverse.TypeLevel.MaybeUniqueMember x comp, Data.Diverse.TypeLevel.Unique x tree) => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseReinterpret branch tree (Data.Either.Either (Data.Diverse.Which.Internal.Which comp) (Data.Diverse.Which.Internal.Which branch))) (x : tree')
instance forall k (ns :: [GHC.Types.Nat]) (r :: k) (n :: GHC.Types.Nat) (branch' :: [*]). Data.Diverse.Reiterate.ReiterateN (Data.Diverse.Which.Internal.CaseDiversifyN ns r) n branch'
instance Data.Diverse.TypeLevel.MemberAt (Data.Diverse.TypeLevel.KindAtIndex n ns) x tree => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseDiversifyN ns (Data.Diverse.Which.Internal.Which tree) n) (x : branch')
instance forall k (r :: [*]) (branch :: [*]) (tree :: k) (branch' :: [*]). Data.Diverse.Reiterate.Reiterate (Data.Diverse.Which.Internal.CaseDiversify r branch tree) branch'
instance (Data.Diverse.TypeLevel.UniqueMember x tree, Data.Diverse.TypeLevel.Unique x branch) => Data.Diverse.Case.Case (Data.Diverse.Which.Internal.CaseDiversify branch tree (Data.Diverse.Which.Internal.Which tree)) (x : branch')
instance GHC.Generics.Generic (Data.Diverse.Which.Internal.Which '[])
instance GHC.Generics.Generic (Data.Diverse.Which.Internal.Which '[x])
instance GHC.Generics.Generic (Data.Diverse.Which.Internal.Which (x : x' : xs))
instance Data.Semigroup.Semigroup (Data.Diverse.Which.Internal.Which '[])
instance GHC.Classes.Eq (Data.Diverse.Which.Internal.Which '[])
instance GHC.Classes.Ord (Data.Diverse.Which.Internal.Which '[])
instance GHC.Show.Show (Data.Diverse.Which.Internal.Which '[])
instance GHC.Read.Read (Data.Diverse.Which.Internal.Which '[])
instance Control.DeepSeq.NFData (Data.Diverse.Which.Internal.Which '[])


-- | Re-export Which without the constructor
module Data.Diverse.Which

-- | A <a>Which</a> is an anonymous sum type (also known as a polymorphic
--   variant, or co-record) which can only contain one of the types in the
--   typelist. This is essentially a typed version of <a>Dynamic</a>.
--   
--   The following functions are available can be used to manipulate unique
--   types in the typelist
--   
--   <ul>
--   <li>constructor: <a>pick</a></li>
--   <li>destructor: <a>trial</a></li>
--   <li>injection: <a>diversify</a> and <a>reinterpret</a></li>
--   <li>catamorphism: <a>which</a> or <a>switch</a></li>
--   </ul>
--   
--   These functions are type specified. This means labels are not required
--   because the types themselves can be used to access the <a>Which</a>.
--   It is a compile error to use those functions for duplicate fields.
--   
--   For duplicate types in the list of possible types, Nat-indexed version
--   of the functions are available:
--   
--   <ul>
--   <li>constructor: <a>pickN</a></li>
--   <li>destructor: <a>trialN</a></li>
--   <li>inejction: <a>diversifyN</a> and <tt>reinterpretN</tt></li>
--   <li>catamorphism: <a>whichN</a> or <a>switchN</a></li>
--   </ul>
--   
--   Encoding: The variant contains a value whose type is at the given
--   position in the type list. This is the same encoding as
--   <a>Haskus.Util.Variant</a> and <a>Data.Hlist.Variant</a>.
--   
--   The constructor is only exported in the
--   <a>Data.Diverse.Which.Internal</a> module
data Which (xs :: [Type])

-- | Analogous to <a>absurd</a>. Renamed <a>impossible</a> to avoid
--   conflicts.
--   
--   Since 'Which '[]' values logically don't exist, this witnesses the
--   logical reasoning tool of "ex falso quodlibet", ie "from falsehood,
--   anything follows".
--   
--   A 'Which '[]' is a <a>Which</a> with no alternatives, which may occur
--   as a <a>Left</a>-over from <a>trial</a>ing a <tt>Which '[x]</tt> with
--   one type. It is an uninhabited type, just like <a>Void</a>
impossible :: Which '[] -> a

-- | Lift a value into a <a>Which</a> of possibly other types <tt>xs</tt>.
--   <tt>xs</tt> can be inferred or specified with TypeApplications. NB.
--   forall is used to specify <tt>xs</tt> first, so TypeApplications can
--   be used to specify <tt>xs</tt> first
--   
--   <pre>
--   <a>pick</a> 'A' @_ @'[Int, Bool, Char, Maybe String] :: Which '[Int, Bool, Char, Maybe String]
--   </pre>
pick :: forall x xs. UniqueMember x xs => x -> Which xs

-- | A variation of <a>pick</a> into a <a>Which</a> where <tt>x</tt> is the
--   first type.
--   
--   <pre>
--   <a>pick0</a> 'A' :: Which '[Char, Int, Bool]
--   </pre>
pick0 :: x -> Which (x : xs)

-- | A variation of <a>pick</a> into a <a>Which</a> of a single type.
--   
--   <pre>
--   <a>pickOnly</a> 'A' :: Which '[Char]
--   </pre>
pickOnly :: x -> Which '[x]

-- | A variation of <a>pick</a> where <tt>x</tt> is specified via a label
--   
--   <pre>
--   let y = <a>pickL</a> @Foo (Tagged (5 :: Int)) :: Which '[Bool, Tagged Foo Int, Tagged Bar Char]
--       x = <a>trialL</a> @Foo y
--   x <tt>shouldBe</tt> (Right (Tagged 5))
--   </pre>
pickL :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => x -> Which xs

-- | Variation of <a>pickL</a> specialized to <a>Tagged</a> that
--   automatically tags the value.
pickTag :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => x -> Which xs

-- | Lift a value into a <a>Which</a> of possibly other (possibley
--   indistinct) types, where the value is the <tt>n</tt>-th type.
--   
--   <pre>
--   <a>pickN</a> @4 (5 :: Int) :: Which '[Bool, Int, Char, Bool, Int, Char]
--   </pre>
pickN :: forall n x xs. MemberAt n x xs => x -> Which xs

-- | It is <a>obvious</a> what value is inside a <a>Which</a> of one type.
--   
--   <pre>
--   let x = <tt>pick'</tt> 'A' :: Which '[Char]
--   <a>obvious</a> x `shouldBe` 'A'
--   </pre>
obvious :: Which '[a] -> a

-- | <a>trial</a> a type in a <a>Which</a> and <a>Either</a> get the
--   <a>Right</a> value or the <a>Left</a>-over possibilities.
--   
--   <pre>
--   let x = <a>pick</a> 'A' @'[Int, Bool, Char, Maybe String] :: <a>Which</a> '[Int, Bool, Char, Maybe String]
--   <a>trial</a> @Char x `shouldBe` Right 'A'
--   <a>trial</a> @Int x `shouldBe` Left (<a>pick</a> 'A') :: <a>Which</a> '[Bool, Char, Maybe String]
--   </pre>
trial :: forall x xs. (UniqueMember x xs) => Which xs -> Either (Which (Remove x xs)) x

-- | Variation of <a>trial</a> which returns a Maybe
trial' :: forall x xs. (UniqueMember x xs) => Which xs -> Maybe x

-- | A variation of a <a>Which</a> <a>trial</a> which <a>trial</a>s the
--   first type in the type list.
--   
--   <pre>
--   let x = <a>pick</a> 'A' @'[Int, Bool, Char, Maybe String] :: <a>Which</a> '[Int, Bool, Char, Maybe String]
--   <a>trial0</a> x `shouldBe` Left (<a>pick</a> 'A') :: <a>Which</a> '[Bool, Char, Maybe String]
--   </pre>
trial0 :: forall x xs. Which (x : xs) -> Either (Which xs) x

-- | Variation of <a>trial0</a> which returns a Maybe
trial0' :: forall x xs. Which (x : xs) -> Maybe x

-- | A variation of <a>trial</a> where x is specified via a label
--   
--   <pre>
--   let y = <a>pickL</a> @Foo (Tagged (5 :: Int)) :: Which '[Bool, Tagged Foo Int, Tagged Bar Char]
--       x = <a>trialL</a> @Foo Proxy y
--   x <tt>shouldBe</tt> (Right (Tagged 5))
--   </pre>
trialL :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Which xs -> Either (Which (Remove x xs)) x

-- | Variation of <a>trialL</a> which returns a Maybe
trialL' :: forall l x xs. (UniqueLabelMember l xs, x ~ KindAtLabel l xs) => Which xs -> Maybe x

-- | Variation of <a>trialL</a> specialized to <a>Tagged</a> which untags
--   the field.
trialTag :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Which xs -> Either (Which (Remove (Tagged l x) xs)) x

-- | Variation of <a>trialL'</a> specialized to <a>Tagged</a> which untags
--   the field.
trialTag' :: forall l x xs. (UniqueLabelMember l xs, Tagged l x ~ KindAtLabel l xs) => Which xs -> Maybe x

-- | <a>trialN</a> the n-th type of a <a>Which</a>, and get <a>Either</a>
--   the <a>Right</a> value or the <a>Left</a>-over possibilities.
--   
--   <pre>
--   let x = <a>pick</a> 'A' @_ @'[Int, Bool, Char, Maybe String] :: <a>Which</a> '[Int, Bool, Char, Maybe String]
--   <a>trialN</a> @1 x `shouldBe` Left (<a>pick</a> 'A') :: <a>Which</a> '[Int, Char, Maybe String]
--   </pre>
trialN :: forall n x xs. (MemberAt n x xs) => Which xs -> Either (Which (RemoveIndex n xs)) x

-- | Variation of <a>trialN</a> which returns a Maybe
trialN' :: forall n x xs. (MemberAt n x xs) => Which xs -> Maybe x

-- | A friendlier constraint synonym for <a>diversify</a>.
type Diversify (branch :: [Type]) (tree :: [Type]) = Switch (CaseDiversify branch tree) (Which tree) branch

-- | Convert a <a>Which</a> to another <a>Which</a> that may include other
--   possibilities. That is, <tt>branch</tt> is equal or is a subset of
--   <tt>tree</tt>.
--   
--   This can also be used to rearrange the order of the types in the
--   <a>Which</a>.
--   
--   It is a compile error if <tt>tree</tt> has duplicate types with
--   <tt>branch</tt>.
--   
--   NB. Use TypeApplications with <tt>_ to specify </tt>tree@.
--   
--   <pre>
--   let a = <tt>pick'</tt> (5 :: Int) :: <a>Which</a> '[Int]
--       b = <a>diversify</a> @_ @[Int, Bool] a :: <a>Which</a> '[Int, Bool]
--       c = <a>diversify</a> @_ @[Bool, Int] b :: <a>Which</a> '[Bool, Int]
--   </pre>
diversify :: forall branch tree. Diversify branch tree => Which branch -> Which tree

-- | A restricted version of <a>diversify</a> which only rearranges the
--   types
diversify' :: forall branch tree. (Diversify branch tree, SameLength branch tree) => Which branch -> Which tree

-- | A simple version of <a>diversify</a> which add another type to the
--   front of the typelist.
diversify0 :: forall x xs. Which xs -> Which (x : xs)

-- | A friendlier constraint synonym for <a>diversifyL</a>.
type DiversifyL (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Diversify branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | A variation of <a>diversify</a> where <tt>branch</tt>is additionally
--   specified by a labels list.
--   
--   <pre>
--   let y = <a>pickOnly</a> (5 :: Tagged Bar Int)
--       y' = <a>diversifyL</a> @'[Bar] y :: <a>Which</a> '[Tagged Bar Int, Tagged Foo Bool]
--       y'' = <a>diversifyL</a> @'[Bar, Foo] y' :: <a>Which</a> '[Tagged Foo Bool, Tagged Bar Int]
--   <a>switch</a> y'' (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` "Tagged * Bar Int"
--   </pre>
diversifyL :: forall ls branch tree. (DiversifyL ls branch tree) => Which branch -> Which tree

-- | A friendlier constraint synonym for <a>diversifyN</a>.
type DiversifyN (ns :: [Nat]) (branch :: [Type]) (tree :: [Type]) = (SwitchN Which (CaseDiversifyN ns) (Which tree) 0 branch, KindsAtIndices ns tree ~ branch)

-- | A variation of <a>diversify</a> which uses a Nat list <tt>indices</tt>
--   to specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx
--   </pre>
--   
--   This variation allows <tt>tree</tt> to contain duplicate types with
--   <tt>branch</tt> since the mapping is specified by <tt>indicies</tt>.
--   
--   <pre>
--   let y = <a>pickOnly</a> (5 :: Int)
--       y' = <a>diversifyN</a> @'[0] @_ @[Int, Bool] y
--       y'' = <a>diversifyN</a> @[1,0] @_ @[Bool, Int] y'
--   <a>switch</a> y'' (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` "Int"
--   </pre>
diversifyN :: forall ns branch tree. (DiversifyN ns branch tree) => Which branch -> Which tree

-- | A friendlier constraint synonym for <a>reinterpret</a>.
type Reinterpret (branch :: [Type]) (tree :: [Type]) = Switch (CaseReinterpret branch tree) (Either (Which (Complement tree branch)) (Which branch)) tree

-- | A variation of <a>Reinterpret</a> that exposes <tt>branchlessTree ~
--   Complement tree branch</tt>
type Reinterpreted branch tree branchlessTree = (Reinterpret branch tree, branchlessTree ~ Complement tree branch)

-- | Convert a <a>Which</a> into possibly another <a>Which</a> with a
--   totally different typelist. Returns either a <a>Which</a> with the
--   <a>Right</a> value, or a <a>Which</a> with the <a>Left</a>over
--   <tt>compliment</tt> types.
--   
--   It is a compile error if <tt>branch</tt> or <tt>compliment</tt> has
--   duplicate types with <tt>tree</tt>.
--   
--   NB. forall used to specify <tt>branch</tt> first, so TypeApplications
--   can be used to specify <tt>branch</tt> first.
--   
--   <pre>
--   let a = <a>pick</a> @[Int, Char, Bool] (5 :: Int) :: <a>Which</a> '[Int, Char, Bool]
--   let  b = <a>reinterpret</a> <tt>[String, Char] y
--   b `shouldBe` Left (<a>pick</a> (5 :: Int)) :: <a>Which</a> '[Int, Bool]
--   let c = <a>reinterpret</a> </tt>[String, Int] a
--   c `shouldBe` Right (<a>pick</a> (5 :: Int)) :: <a>Which</a> '[String, Int]
--   </pre>
reinterpret :: forall branch tree. (Reinterpret branch tree) => Which tree -> Either (Which (Complement tree branch)) (Which branch)

-- | A friendlier constraint synonym for <a>reinterpret'</a>.
type Reinterpret' (branch :: [Type]) (tree :: [Type]) = Switch (CaseReinterpret' branch tree) (Maybe (Which branch)) tree

-- | Variation of <a>reinterpret</a> which returns a Maybe.
reinterpret' :: forall branch tree. (Reinterpret' branch tree) => Which tree -> Maybe (Which branch)

-- | A friendlier constraint synonym for <a>reinterpretL</a>.
type ReinterpretL (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Reinterpret branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | A variation of <a>ReinterpretL</a> that exposes <tt>branchlessTree ~
--   Complement tree branch</tt>
type ReinterpretedL ls branch tree branchlessTree = (ReinterpretL ls branch tree, branchlessTree ~ Complement tree branch)

-- | A variation of <a>reinterpret</a> where the <tt>branch</tt> is
--   additionally specified with a labels list.
--   
--   <pre>
--   let y = <a>pick</a> @[Tagged Bar Int, Tagged Foo Bool, Tagged Hi Char, Tagged Bye Bool] (5 :: Tagged Bar Int)
--       y' = <a>reinterpretL</a> @[Foo, Bar] y
--       x = <a>pick</a> @[Tagged Foo Bool, Tagged Bar Int] (5 :: Tagged Bar Int)
--   y' `shouldBe` Right x
--   </pre>
reinterpretL :: forall ls branch tree. (ReinterpretL ls branch tree) => Which tree -> Either (Which (Complement tree branch)) (Which branch)

-- | A friendlier constraint synonym for <a>reinterpretL</a>.
type ReinterpretL' (ls :: [k]) (branch :: [Type]) (tree :: [Type]) = (Reinterpret' branch tree, branch ~ KindsAtLabels ls tree, UniqueLabels ls tree, IsDistinct ls)

-- | Variation of <a>reinterpretL</a> which returns a Maybe.
reinterpretL' :: forall ls branch tree. (ReinterpretL' ls branch tree) => Which tree -> Maybe (Which branch)

-- | A friendlier constraint synonym for <tt>reinterpretN</tt>.
type ReinterpretN' (ns :: [Nat]) (branch :: [Type]) (tree :: [Type]) = (SwitchN Which (CaseReinterpretN' ns) (Maybe (Which branch)) 0 tree, KindsAtIndices ns tree ~ branch)

-- | A limited variation of <a>reinterpret'</a> which uses a Nat list
--   <tt>n</tt> to specify how to reorder the fields, where
--   
--   <pre>
--   indices[branch_idx] = tree_idx
--   </pre>
--   
--   This variation allows <tt>tree</tt> to contain duplicate types with
--   <tt>branch</tt> since the mapping is specified by <tt>indicies</tt>.
--   
--   However, unlike <tt>reinterpert</tt>, in this variation,
--   <tt>branch</tt> must be a subset of <tt>tree</tt> instead of any
--   arbitrary Which. Also it returns a Maybe instead of Either.
--   
--   This is so that the same <tt>indices</tt> can be used in
--   <tt>narrowN</tt>.
reinterpretN' :: forall ns branch tree. (ReinterpretN' ns branch tree) => Which tree -> Maybe (Which branch)

-- | A friendlier constraint synonym for <tt>reinterpretN</tt>.
type Switch c r xs = Reduce (Which xs) (Switcher c r xs)

-- | A switch/case statement for <a>Which</a>. This is equivalent to
--   <tt>flip <a>which</a></tt>
--   
--   Use <a>Case</a> instances like <a>Cases</a> to apply a <a>Which</a> of
--   functions to a variant of values.
--   
--   <pre>
--   let y = <a>pick</a> (5 :: Int) :: <a>Which</a> '[Int, Bool]
--   <a>switch</a> y (
--       <a>cases</a> (show @Bool
--           <a>./</a> show @Int
--           <a>./</a> <a>nil</a>)) `shouldBe` "5"
--   </pre>
--   
--   Or <a>CaseFunc</a> @<a>Typeable</a> to apply a polymorphic function
--   that work on all <tt>Typeable</tt>s.
--   
--   <pre>
--   let y = <a>pick</a> (5 :: Int) :: <a>Which</a> '[Int, Bool]
--   <a>switch</a> y (<a>CaseFunc</a> @<a>Typeable</a> (show . typeRep . (pure @Proxy))) `shouldBe` <a>Int</a>
--   </pre>
--   
--   Or you may use your own custom instance of <a>Case</a>.
switch :: Switch c r xs => Which xs -> c r xs -> r

-- | Catamorphism for <a>Which</a>. This is <tt>flip <a>switch</a></tt>.
which :: Switch c r xs => c r xs -> Which xs -> r

-- | <a>Switcher</a> is an instance of <a>Reduce</a> for which
--   <b><a>reiterate</a></b>s through the possibilities in a <a>Which</a>,
--   delegating handling to <a>Case</a>, ensuring termination when
--   <a>Which</a> only contains one type.
newtype Switcher c r (xs :: [Type])
Switcher :: (c r xs) -> Switcher c r

-- | A switch/case statement for <a>Which</a>. This is equivalent to
--   <tt>flip <a>whichN</a></tt>
--   
--   Use <a>Case</a> instances like <a>CasesN</a> to apply a <a>Which</a>
--   of functions to a variant of values in index order.
--   
--   <pre>
--   let y = <a>pickN</a> @0 (5 :: Int) :: <a>Which</a> '[Int, Bool, Bool, Int]
--   <a>switchN</a> y (
--       <a>casesN</a> (show @Int
--           <a>./</a> show @Bool
--           <a>./</a> show @Bool
--           <a>./</a> show @Int
--           <a>./</a> <a>nil</a>)) `shouldBe` "5"
--   </pre>
--   
--   Or you may use your own custom instance of <a>Case</a>.
class SwitchN w c r (n :: Nat) xs
switchN :: SwitchN w c r n xs => w xs -> c r n xs -> r
switchN :: SwitchN w c r n xs => w xs -> c r n xs -> r

-- | Catamorphism for <a>Which</a>. This is equivalent to <tt>flip
--   <a>switchN</a></tt>.
whichN :: SwitchN w c r n xs => c r n xs -> w xs -> r

-- | <a>SwitcherN</a> is a variation of <a>Switcher</a> which
--   <b><a>reiterateN</a></b>s through the possibilities in a <a>Which</a>,
--   delegating work to <tt>CaseN</tt>, ensuring termination when
--   <a>Which</a> only contains one type.
newtype SwitcherN c r (n :: Nat) (xs :: [Type])
SwitcherN :: (c r n xs) -> SwitcherN c r

module Data.Diverse
