    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DataKinds #-}
    -- |
    -- Module: Optics.IxFold
    -- Description: An indexed version of a 'Optics.Fold.Fold'.
    --
    -- An 'IxFold' is an indexed version of a 'Optics.Fold.Fold'. See the "Indexed
    -- optics" section of the overview documentation in the @Optics@ module of the
    -- main @optics@ package for more details on indexed optics.
    --
    module Optics.IxFold
      (
      -- * Formation
        IxFold

      -- * Introduction
      , ifoldVL

      -- * Elimination
      , ifoldMapOf
      , ifoldrOf
      , ifoldlOf'
      , itoListOf
      , itraverseOf_
      , iforOf_

      -- * Additional introduction forms
      , ifolded
      , ifolding
      , ifoldring

      -- * Additional elimination forms
      -- | See also 'Data.Map.Optics.toMapOf', which constructs a 'Data.Map.Map' from an 'IxFold'.
      , iheadOf
      , ilastOf
      , ianyOf
      , iallOf
      , inoneOf
      , ifindOf
      , ifindMOf

      -- * Combinators
      , ipre
      , ifiltered
      , ibackwards_

      -- * Monoid structures #monoids#
      -- | 'IxFold' admits (at least) two monoid structures:
      --
      -- * 'isumming' concatenates results from both folds.
      --
      -- * 'ifailing' returns results from the second fold only if the first returns
      --   no results.
      --
      -- In both cases, the identity element of the monoid is
      -- `Optics.IxAffineTraversal.ignored`, which returns no results.
      --
      -- There is no 'Semigroup' or 'Monoid' instance for 'IxFold', because there is
      -- not a unique choice of monoid to use, and the ('<>') operator could not be
      -- used to combine optics of different kinds.
      , isumming
      , ifailing

      -- * Subtyping
      , A_Fold

      -- * Re-exports
      , FoldableWithIndex(..)
      ) where

    import Control.Applicative.Backwards
    import Data.Monoid

    import Data.Profunctor.Indexed

    import Optics.Internal.Bi
    import Optics.Internal.Indexed
    import Optics.Internal.Indexed.Classes
    import Optics.Internal.Fold
    import Optics.Internal.IxFold
    import Optics.Internal.Optic
    import Optics.Internal.Utils
    import Optics.IxAffineFold
    import Optics.Fold

    -- | Type synonym for an indexed fold.
    type IxFold i s a = Optic' A_Fold (WithIx i) s a

    -- | Obtain an indexed fold by lifting 'itraverse_' like function.
    --
    -- @
    -- 'ifoldVL' '.' 'itraverseOf_' ≡ 'id'
    -- 'itraverseOf_' '.' 'ifoldVL' ≡ 'id'
    -- @
    ifoldVL
      :: (forall f. Applicative f => (i -> a -> f u) -> s -> f v)
      -> IxFold i s a
    ifoldVL :: forall i a u s v.
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> IxFold i s a
    ifoldVL forall (f :: * -> *). Applicative f => (i -> a -> f u) -> s -> f v
    f = (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ A_Fold p i (Curry (WithIx i) i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    forall k (is :: IxList) s t a b.
    (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ k p i (Curry is i) s t a b)
    -> Optic k is s t a b
    Optic ((forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> Optic__ p i (i -> i) s s a a
    forall (p :: * -> * -> * -> *) i a u s v j t b.
    (Bicontravariant p, Traversing p) =>
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> Optic__ p j (i -> j) s t a b
    ifoldVL__ (i -> a -> f u) -> s -> f v
    forall (f :: * -> *). Applicative f => (i -> a -> f u) -> s -> f v
    f)
    {-# INLINE ifoldVL #-}

    -- | Fold with index via embedding into a monoid.
    ifoldMapOf
      :: (Is k A_Fold, Monoid m, is `HasSingleIndex` i)
      => Optic' k is s a
      -> (i -> a -> m) -> s -> m
    ifoldMapOf :: forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o = \i -> a -> m
    f -> IxForget m (i -> i) s s -> (i -> i) -> s -> m
    forall r i a b. IxForget r i a b -> i -> a -> r
    runIxForget (Optic A_Fold is s s a a
    -> Optic_ A_Fold (IxForget m) i (Curry is i) s s a a
    forall (p :: * -> * -> * -> *) k (is :: IxList) s t a b i.
    Profunctor p =>
    Optic k is s t a b -> Optic_ k p i (Curry is i) s t a b
    getOptic (forall destKind srcKind (is :: IxList) s t a b.
    Is srcKind destKind =>
    Optic srcKind is s t a b -> Optic destKind is s t a b
    castOptic @A_Fold Optic' k is s a
    o) ((i -> a -> m) -> IxForget m i a a
    forall r i a b. (i -> a -> r) -> IxForget r i a b
    IxForget i -> a -> m
    f)) i -> i
    forall a. a -> a
    id
    {-# INLINE ifoldMapOf #-}

    -- | Fold with index right-associatively.
    ifoldrOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a
      -> (i -> a -> r -> r) -> r -> s -> r
    ifoldrOf :: forall k (is :: IxList) i s a r.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> r -> r) -> r -> s -> r
    ifoldrOf Optic' k is s a
    o = \i -> a -> r -> r
    iarr r
    r0 s
    s -> (\Endo r
    e -> Endo r -> r -> r
    forall a. Endo a -> a -> a
    appEndo Endo r
    e r
    r0) (Endo r -> r) -> Endo r -> r
    forall a b. (a -> b) -> a -> b
    $ Optic' k is s a -> (i -> a -> Endo r) -> s -> Endo r
    forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o (\i
    i -> (r -> r) -> Endo r
    forall a. (a -> a) -> Endo a
    Endo ((r -> r) -> Endo r) -> (a -> r -> r) -> a -> Endo r
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. i -> a -> r -> r
    iarr i
    i) s
    s
    {-# INLINE ifoldrOf #-}

    -- | Fold with index left-associatively, and strictly.
    ifoldlOf'
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a
      -> (i -> r -> a -> r) -> r -> s -> r
    ifoldlOf' :: forall k (is :: IxList) i s a r.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> r -> a -> r) -> r -> s -> r
    ifoldlOf' Optic' k is s a
    o = \i -> r -> a -> r
    irar r
    r0 s
    s -> Optic' k is s a
    -> (i -> a -> (r -> r) -> r -> r) -> (r -> r) -> s -> r -> r
    forall k (is :: IxList) i s a r.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> r -> r) -> r -> s -> r
    ifoldrOf Optic' k is s a
    o (\i
    i a
    a r -> r
    rr r
    r -> r -> r
    rr (r -> r) -> r -> r
    forall a b. (a -> b) -> a -> b
    $! i -> r -> a -> r
    irar i
    i r
    r a
    a) r -> r
    forall a. a -> a
    id s
    s r
    r0
    {-# INLINE ifoldlOf' #-}

    -- | Fold with index to a list.
    --
    -- >>> itoListOf (folded % ifolded) ["abc", "def"]
    -- [(0,'a'),(1,'b'),(2,'c'),(0,'d'),(1,'e'),(2,'f')]
    --
    -- /Note:/ currently indexed optics can be used as non-indexed.
    --
    -- >>> toListOf (folded % ifolded) ["abc", "def"]
    -- "abcdef"
    --
    itoListOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a
      -> s -> [(i, a)]
    itoListOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> s -> [(i, a)]
    itoListOf Optic' k is s a
    o = Optic' k is s a
    -> (i -> a -> [(i, a)] -> [(i, a)]) -> [(i, a)] -> s -> [(i, a)]
    forall k (is :: IxList) i s a r.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> r -> r) -> r -> s -> r
    ifoldrOf Optic' k is s a
    o (\i
    i -> (:) ((i, a) -> [(i, a)] -> [(i, a)])
    -> (a -> (i, a)) -> a -> [(i, a)] -> [(i, a)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (i
    i, )) []
    {-# INLINE itoListOf #-}

    ----------------------------------------

    -- | Traverse over all of the targets of an 'IxFold', computing an
    -- 'Applicative'-based answer, but unlike 'Optics.IxTraversal.itraverseOf' do
    -- not construct a new structure.
    --
    -- >>> itraverseOf_ each (curry print) ("hello","world")
    -- (0,"hello")
    -- (1,"world")
    --
    itraverseOf_
      :: (Is k A_Fold, Applicative f, is `HasSingleIndex` i)
      => Optic' k is s a
      -> (i -> a -> f r) -> s -> f ()
    #if __GLASGOW_HASKELL__ == 802
    -- GHC 8.2.2 needs this to optimize away profunctors when f is not supplied.
    itraverseOf_ o = \f ->
    #else
    itraverseOf_ :: forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' k is s a
    o i -> a -> f r
    f =
    #endif
      Traversed f r -> f ()
    forall (f :: * -> *) a. Functor f => Traversed f a -> f ()
    runTraversed (Traversed f r -> f ()) -> (s -> Traversed f r) -> s -> f ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Optic' k is s a -> (i -> a -> Traversed f r) -> s -> Traversed f r
    forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o (\i
    i -> f r -> Traversed f r
    forall (f :: * -> *) a. f a -> Traversed f a
    Traversed (f r -> Traversed f r) -> (a -> f r) -> a -> Traversed f r
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. i -> a -> f r
    f i
    i)
    {-# INLINE itraverseOf_ #-}

    -- | A version of 'itraverseOf_' with the arguments flipped.
    iforOf_
      :: (Is k A_Fold, Applicative f, is `HasSingleIndex` i)
      => Optic' k is s a
      -> s -> (i -> a -> f r) -> f ()
    iforOf_ :: forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> s -> (i -> a -> f r) -> f ()
    iforOf_ = ((i -> a -> f r) -> s -> f ()) -> s -> (i -> a -> f r) -> f ()
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (((i -> a -> f r) -> s -> f ()) -> s -> (i -> a -> f r) -> f ())
    -> (Optic' k is s a -> (i -> a -> f r) -> s -> f ())
    -> Optic' k is s a
    -> s
    -> (i -> a -> f r)
    -> f ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_
    {-# INLINE iforOf_ #-}

    ----------------------------------------

    -- | Indexed fold via 'FoldableWithIndex' class.
    ifolded :: FoldableWithIndex i f => IxFold i (f a) a
    ifolded :: forall i (f :: * -> *) a. FoldableWithIndex i f => IxFold i (f a) a
    ifolded = (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ A_Fold p i (Curry (WithIx i) i) (f a) (f a) a a)
    -> Optic A_Fold (WithIx i) (f a) (f a) a a
    forall k (is :: IxList) s t a b.
    (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ k p i (Curry is i) s t a b)
    -> Optic k is s t a b
    Optic p i a a -> p (Curry (WithIx i) i) (f a) (f a)
    Optic__ p i (i -> i) (f a) (f a) a a
    forall (p :: * -> * -> * -> *) i.
    Profunctor p =>
    Optic_ A_Fold p i (Curry (WithIx i) i) (f a) (f a) a a
    forall (p :: * -> * -> * -> *) i (f :: * -> *) j a t b.
    (Bicontravariant p, Traversing p, FoldableWithIndex i f) =>
    Optic__ p j (i -> j) (f a) t a b
    ifolded__
    {-# INLINE ifolded #-}

    -- | Obtain an 'IxFold' by lifting an operation that returns a
    -- 'FoldableWithIndex' result.
    --
    -- This can be useful to lift operations from @Data.List@ and elsewhere into an
    -- 'IxFold'.
    --
    -- >>> itoListOf (ifolding words) "how are you"
    -- [(0,"how"),(1,"are"),(2,"you")]
    ifolding :: FoldableWithIndex i f => (s -> f a) -> IxFold i s a
    ifolding :: forall i (f :: * -> *) s a.
    FoldableWithIndex i f =>
    (s -> f a) -> IxFold i s a
    ifolding s -> f a
    f = (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ A_Fold p i (Curry (WithIx i) i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    forall k (is :: IxList) s t a b.
    (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ k p i (Curry is i) s t a b)
    -> Optic k is s t a b
    Optic ((forall (p :: * -> * -> * -> *) i.
      Profunctor p =>
      Optic_ A_Fold p i (Curry (WithIx i) i) s s a a)
     -> Optic A_Fold (WithIx i) s s a a)
    -> (forall (p :: * -> * -> * -> *) i.
        Profunctor p =>
        Optic_ A_Fold p i (Curry (WithIx i) i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ (s -> f a) -> p (i -> i) (f a) s -> p (i -> i) s s
    forall b a i c. (b -> a) -> p i a c -> p i b c
    forall (p :: * -> * -> * -> *) b a i c.
    Bicontravariant p =>
    (b -> a) -> p i a c -> p i b c
    contrafirst s -> f a
    f (p (i -> i) (f a) s -> p (i -> i) s s)
    -> (p i a a -> p (i -> i) (f a) s) -> p i a a -> p (i -> i) s s
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . p i a a -> p (i -> i) (f a) s
    forall (p :: * -> * -> * -> *) i (f :: * -> *) j a t b.
    (Bicontravariant p, Traversing p, FoldableWithIndex i f) =>
    Optic__ p j (i -> j) (f a) t a b
    ifolded__
    {-# INLINE ifolding #-}

    -- | Obtain an 'IxFold' by lifting 'ifoldr' like function.
    --
    -- >>> itoListOf (ifoldring ifoldr) "hello"
    -- [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
    ifoldring
      :: (forall f. Applicative f => (i -> a -> f u -> f u) -> f v -> s -> f w)
      -> IxFold i s a
    ifoldring :: forall i a u v s w.
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u -> f u) -> f v -> s -> f w)
    -> IxFold i s a
    ifoldring forall (f :: * -> *).
    Applicative f =>
    (i -> a -> f u -> f u) -> f v -> s -> f w
    fr = (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ A_Fold p i (Curry (WithIx i) i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    forall k (is :: IxList) s t a b.
    (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ k p i (Curry is i) s t a b)
    -> Optic k is s t a b
    Optic ((forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u -> f u) -> f v -> s -> f w)
    -> Optic__ p i (i -> i) s s a a
    forall (p :: * -> * -> * -> *) i a u v s w j t b.
    (Bicontravariant p, Traversing p) =>
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u -> f u) -> f v -> s -> f w)
    -> Optic__ p j (i -> j) s t a b
    ifoldring__ (i -> a -> f u -> f u) -> f v -> s -> f w
    forall (f :: * -> *).
    Applicative f =>
    (i -> a -> f u -> f u) -> f v -> s -> f w
    fr)
    {-# INLINE ifoldring #-}

    -- | Convert an indexed fold to an 'IxAffineFold' that visits the first element
    -- of the original fold.
    --
    -- For the traversal version see 'Optics.IxTraversal.isingular'.
    ipre
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a
      -> IxAffineFold i s a
    ipre :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> IxAffineFold i s a
    ipre = (s -> Maybe (i, a)) -> IxAffineFold i s a
    forall s i a. (s -> Maybe (i, a)) -> IxAffineFold i s a
    iafolding ((s -> Maybe (i, a)) -> IxAffineFold i s a)
    -> (Optic' k is s a -> s -> Maybe (i, a))
    -> Optic' k is s a
    -> IxAffineFold i s a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Optic' k is s a -> s -> Maybe (i, a)
    forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> s -> Maybe (i, a)
    iheadOf
    {-# INLINE ipre #-}

    -- | Filter results of an 'IxFold' that don't satisfy a predicate.
    --
    -- >>> toListOf (ifolded %& ifiltered (>)) [3,2,1,0]
    -- [1,0]
    --
    ifiltered
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => (i -> a -> Bool)
      -> Optic' k is s a
      -> IxFold i s a
    ifiltered :: forall k (is :: IxList) i a s.
    (Is k A_Fold, HasSingleIndex is i) =>
    (i -> a -> Bool) -> Optic' k is s a -> IxFold i s a
    ifiltered i -> a -> Bool
    p Optic' k is s a
    o = (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f ()) -> s -> f ())
    -> IxFold i s a
    forall i a u s v.
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> IxFold i s a
    ifoldVL ((forall (f :: * -> *).
      Applicative f =>
      (i -> a -> f ()) -> s -> f ())
     -> IxFold i s a)
    -> (forall (f :: * -> *).
        Applicative f =>
        (i -> a -> f ()) -> s -> f ())
    -> IxFold i s a
    forall a b. (a -> b) -> a -> b
    $ \i -> a -> f ()
    f ->
      Optic' k is s a -> (i -> a -> f ()) -> s -> f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' k is s a
    o (\i
    i a
    a -> if i -> a -> Bool
    p i
    i a
    a then i -> a -> f ()
    f i
    i a
    a else () -> f ()
    forall a. a -> f a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ())
    {-# INLINE ifiltered #-}
    -- Note: technically this should be defined per optic kind:
    --
    -- ifiltered :: _ -> IxFold i s a       -> IxFold i s a
    -- ifiltered :: _ -> IxGetter i s a     -> IxAffineFold i s a
    -- ifiltered :: _ -> IxAffineFold i s a -> IxAffineFold i s a
    --
    -- and similarly for (non-existent) unsafeIFiltered.

    -- | This allows you to traverse the elements of an 'IxFold' in the opposite
    -- order.
    ibackwards_
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a
      -> IxFold i s a
    ibackwards_ :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> IxFold i s a
    ibackwards_ Optic' k is s a
    o = Optic A_Fold '[] s s a a
    -> Optic A_Fold (WithIx i) s s a a
    -> Optic A_Fold (WithIx i) s s a a
    forall (is :: IxList) i k s t a b.
    HasSingleIndex is i =>
    Optic k '[] s t a b -> Optic k is s t a b -> Optic k is s t a b
    conjoined (Optic' k is s a -> Optic A_Fold '[] s s a a
    forall k (is :: IxList) s a.
    Is k A_Fold =>
    Optic' k is s a -> Fold s a
    backwards_ Optic' k is s a
    o) (Optic A_Fold (WithIx i) s s a a
     -> Optic A_Fold (WithIx i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f (ZonkAny 0)) -> s -> f ())
    -> Optic A_Fold (WithIx i) s s a a
    forall i a u s v.
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> IxFold i s a
    ifoldVL ((forall (f :: * -> *).
      Applicative f =>
      (i -> a -> f (ZonkAny 0)) -> s -> f ())
     -> Optic A_Fold (WithIx i) s s a a)
    -> (forall (f :: * -> *).
        Applicative f =>
        (i -> a -> f (ZonkAny 0)) -> s -> f ())
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ \i -> a -> f (ZonkAny 0)
    f ->
      Backwards f () -> f ()
    forall {k} (f :: k -> *) (a :: k). Backwards f a -> f a
    forwards (Backwards f () -> f ()) -> (s -> Backwards f ()) -> s -> f ()
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. Optic' k is s a
    -> (i -> a -> Backwards f (ZonkAny 0)) -> s -> Backwards f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' k is s a
    o (\i
    i -> f (ZonkAny 0) -> Backwards f (ZonkAny 0)
    forall {k} (f :: k -> *) (a :: k). f a -> Backwards f a
    Backwards (f (ZonkAny 0) -> Backwards f (ZonkAny 0))
    -> (a -> f (ZonkAny 0)) -> a -> Backwards f (ZonkAny 0)
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. i -> a -> f (ZonkAny 0)
    f i
    i)
    {-# INLINE ibackwards_ #-}

    -- | Return entries of the first 'IxFold', then the second one.
    --
    -- >>> itoListOf (ifolded `isumming` ibackwards_ ifolded) ["a","b"]
    -- [(0,"a"),(1,"b"),(1,"b"),(0,"a")]
    --
    -- For the traversal version see 'Optics.IxTraversal.iadjoin'.
    isumming
      :: (Is k A_Fold, Is l A_Fold,
          is1 `HasSingleIndex` i, is2 `HasSingleIndex` i)
      => Optic' k is1 s a
      -> Optic' l is2 s a
      -> IxFold i s a
    isumming :: forall k l (is1 :: IxList) i (is2 :: IxList) s a.
    (Is k A_Fold, Is l A_Fold, HasSingleIndex is1 i,
     HasSingleIndex is2 i) =>
    Optic' k is1 s a -> Optic' l is2 s a -> IxFold i s a
    isumming Optic' k is1 s a
    a Optic' l is2 s a
    b = Optic A_Fold '[] s s a a
    -> Optic A_Fold (WithIx i) s s a a
    -> Optic A_Fold (WithIx i) s s a a
    forall (is :: IxList) i k s t a b.
    HasSingleIndex is i =>
    Optic k '[] s t a b -> Optic k is s t a b -> Optic k is s t a b
    conjoined (Optic' k is1 s a -> Optic' l is2 s a -> Optic A_Fold '[] s s a a
    forall k l (is :: IxList) s a (js :: IxList).
    (Is k A_Fold, Is l A_Fold) =>
    Optic' k is s a -> Optic' l js s a -> Fold s a
    summing Optic' k is1 s a
    a Optic' l is2 s a
    b) (Optic A_Fold (WithIx i) s s a a
     -> Optic A_Fold (WithIx i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f (ZonkAny 1)) -> s -> f ())
    -> Optic A_Fold (WithIx i) s s a a
    forall i a u s v.
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> IxFold i s a
    ifoldVL ((forall (f :: * -> *).
      Applicative f =>
      (i -> a -> f (ZonkAny 1)) -> s -> f ())
     -> Optic A_Fold (WithIx i) s s a a)
    -> (forall (f :: * -> *).
        Applicative f =>
        (i -> a -> f (ZonkAny 1)) -> s -> f ())
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ \i -> a -> f (ZonkAny 1)
    f s
    s ->
      Optic' k is1 s a -> (i -> a -> f (ZonkAny 1)) -> s -> f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' k is1 s a
    a i -> a -> f (ZonkAny 1)
    f s
    s f () -> f () -> f ()
    forall a b. f a -> f b -> f b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Optic' l is2 s a -> (i -> a -> f (ZonkAny 1)) -> s -> f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' l is2 s a
    b i -> a -> f (ZonkAny 1)
    f s
    s
    infixr 6 `isumming` -- Same as (<>)
    {-# INLINE isumming #-}

    -- | Try the first 'IxFold'. If it returns no entries, try the second one.
    --
    -- >>> itoListOf (_1 % ifolded `ifailing` _2 % ifolded) (["a"], ["b","c"])
    -- [(0,"a")]
    -- >>> itoListOf (_1 % ifolded `ifailing` _2 % ifolded) ([], ["b","c"])
    -- [(0,"b"),(1,"c")]
    --
    ifailing
      :: (Is k A_Fold, Is l A_Fold, is1 `HasSingleIndex` i, is2 `HasSingleIndex` i)
      => Optic' k is1 s a
      -> Optic' l is2 s a
      -> IxFold i s a
    ifailing :: forall k l (is1 :: IxList) i (is2 :: IxList) s a.
    (Is k A_Fold, Is l A_Fold, HasSingleIndex is1 i,
     HasSingleIndex is2 i) =>
    Optic' k is1 s a -> Optic' l is2 s a -> IxFold i s a
    ifailing Optic' k is1 s a
    a Optic' l is2 s a
    b = Optic A_Fold '[] s s a a
    -> Optic A_Fold (WithIx i) s s a a
    -> Optic A_Fold (WithIx i) s s a a
    forall (is :: IxList) i k s t a b.
    HasSingleIndex is i =>
    Optic k '[] s t a b -> Optic k is s t a b -> Optic k is s t a b
    conjoined (Optic' k is1 s a -> Optic' l is2 s a -> Optic A_Fold '[] s s a a
    forall k l (is :: IxList) s a (js :: IxList).
    (Is k A_Fold, Is l A_Fold) =>
    Optic' k is s a -> Optic' l js s a -> Fold s a
    failing Optic' k is1 s a
    a Optic' l is2 s a
    b) (Optic A_Fold (WithIx i) s s a a
     -> Optic A_Fold (WithIx i) s s a a)
    -> Optic A_Fold (WithIx i) s s a a
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f (ZonkAny 2)) -> s -> f ())
    -> Optic A_Fold (WithIx i) s s a a
    forall i a u s v.
    (forall (f :: * -> *).
     Applicative f =>
     (i -> a -> f u) -> s -> f v)
    -> IxFold i s a
    ifoldVL ((forall (f :: * -> *).
      Applicative f =>
      (i -> a -> f (ZonkAny 2)) -> s -> f ())
     -> Optic A_Fold (WithIx i) s s a a)
    -> (forall (f :: * -> *).
        Applicative f =>
        (i -> a -> f (ZonkAny 2)) -> s -> f ())
    -> Optic A_Fold (WithIx i) s s a a
    forall a b. (a -> b) -> a -> b
    $ \i -> a -> f (ZonkAny 2)
    f s
    s ->
      let OrT Bool
    visited f ()
    fu = Optic' k is1 s a -> (i -> a -> OrT f (ZonkAny 2)) -> s -> OrT f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' k is1 s a
    a (\i
    i -> f (ZonkAny 2) -> OrT f (ZonkAny 2)
    forall (f :: * -> *) a. f a -> OrT f a
    wrapOrT (f (ZonkAny 2) -> OrT f (ZonkAny 2))
    -> (a -> f (ZonkAny 2)) -> a -> OrT f (ZonkAny 2)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . i -> a -> f (ZonkAny 2)
    f i
    i) s
    s
      in if Bool
    visited
         then f ()
    fu
         else Optic' l is2 s a -> (i -> a -> f (ZonkAny 2)) -> s -> f ()
    forall k (f :: * -> *) (is :: IxList) i s a r.
    (Is k A_Fold, Applicative f, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> f r) -> s -> f ()
    itraverseOf_ Optic' l is2 s a
    b i -> a -> f (ZonkAny 2)
    f s
    s
    infixl 3 `ifailing` -- Same as (<|>)
    {-# INLINE ifailing #-}

    ----------------------------------------
    -- Special folds

    -- | Retrieve the first entry of an 'IxFold' along with its index.
    --
    -- >>> iheadOf ifolded [1..10]
    -- Just (0,1)
    iheadOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a -> s -> Maybe (i, a)
    iheadOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> s -> Maybe (i, a)
    iheadOf Optic' k is s a
    o = Leftmost (i, a) -> Maybe (i, a)
    forall a. Leftmost a -> Maybe a
    getLeftmost (Leftmost (i, a) -> Maybe (i, a))
    -> (s -> Leftmost (i, a)) -> s -> Maybe (i, a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Optic' k is s a
    -> (i -> a -> Leftmost (i, a)) -> s -> Leftmost (i, a)
    forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o (\i
    i -> (i, a) -> Leftmost (i, a)
    forall a. a -> Leftmost a
    LLeaf ((i, a) -> Leftmost (i, a))
    -> (a -> (i, a)) -> a -> Leftmost (i, a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (i
    i, ))
    {-# INLINE iheadOf #-}

    -- | Retrieve the last entry of an 'IxFold' along with its index.
    --
    -- >>> ilastOf ifolded [1..10]
    -- Just (9,10)
    ilastOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a -> s -> Maybe (i, a)
    ilastOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> s -> Maybe (i, a)
    ilastOf Optic' k is s a
    o = Rightmost (i, a) -> Maybe (i, a)
    forall a. Rightmost a -> Maybe a
    getRightmost (Rightmost (i, a) -> Maybe (i, a))
    -> (s -> Rightmost (i, a)) -> s -> Maybe (i, a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Optic' k is s a
    -> (i -> a -> Rightmost (i, a)) -> s -> Rightmost (i, a)
    forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o (\i
    i -> (i, a) -> Rightmost (i, a)
    forall a. a -> Rightmost a
    RLeaf ((i, a) -> Rightmost (i, a))
    -> (a -> (i, a)) -> a -> Rightmost (i, a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (i
    i, ))
    {-# INLINE ilastOf #-}

    -- | Return whether or not any element viewed through an 'IxFold' satisfies a
    -- predicate, with access to the @i@.
    --
    -- When you don't need access to the index then 'anyOf' is more flexible in what
    -- it accepts.
    --
    -- @
    -- 'anyOf' o ≡ 'ianyOf' o '.' 'const'
    -- @
    ianyOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    ianyOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    ianyOf Optic' k is s a
    o = \i -> a -> Bool
    f -> Any -> Bool
    getAny (Any -> Bool) -> (s -> Any) -> s -> Bool
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. Optic' k is s a -> (i -> a -> Any) -> s -> Any
    forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o (\i
    i -> Bool -> Any
    Any (Bool -> Any) -> (a -> Bool) -> a -> Any
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. i -> a -> Bool
    f i
    i)
    {-# INLINE ianyOf #-}

    -- | Return whether or not all elements viewed through an 'IxFold' satisfy a
    -- predicate, with access to the @i@.
    --
    -- When you don't need access to the index then 'allOf' is more flexible in what
    -- it accepts.
    --
    -- @
    -- 'allOf' o ≡ 'iallOf' o '.' 'const'
    -- @
    iallOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    iallOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    iallOf Optic' k is s a
    o = \i -> a -> Bool
    f -> All -> Bool
    getAll (All -> Bool) -> (s -> All) -> s -> Bool
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. Optic' k is s a -> (i -> a -> All) -> s -> All
    forall k m (is :: IxList) i s a.
    (Is k A_Fold, Monoid m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m) -> s -> m
    ifoldMapOf Optic' k is s a
    o (\i
    i -> Bool -> All
    All (Bool -> All) -> (a -> Bool) -> a -> All
    forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
    #. i -> a -> Bool
    f i
    i)
    {-# INLINE iallOf #-}

    -- | Return whether or not none of the elements viewed through an 'IxFold'
    -- satisfy a predicate, with access to the @i@.
    --
    -- When you don't need access to the index then 'noneOf' is more flexible in
    -- what it accepts.
    --
    -- @
    -- 'noneOf' o ≡ 'inoneOf' o '.' 'const'
    -- @
    inoneOf
      :: (Is k A_Fold, is `HasSingleIndex` i)
      => Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    inoneOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    inoneOf Optic' k is s a
    o = \i -> a -> Bool
    f -> Bool -> Bool
    not (Bool -> Bool) -> (s -> Bool) -> s -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> Bool) -> s -> Bool
    ianyOf Optic' k is s a
    o i -> a -> Bool
    f
    {-# INLINE inoneOf #-}

    -- | The 'ifindOf' function takes an 'IxFold', a predicate that is also supplied
    -- the index, a structure and returns the left-most element of the structure
    -- along with its index matching the predicate, or 'Nothing' if there is no such
    -- element.
    --
    -- When you don't need access to the index then 'findOf' is more flexible in
    -- what it accepts.
    ifindOf
     :: (Is k A_Fold, is `HasSingleIndex` i)
     => Optic' k is s a -> (i -> a -> Bool) -> s -> Maybe (i, a)
    ifindOf :: forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> Bool) -> s -> Maybe (i, a)
    ifindOf Optic' k is s a
    o = \i -> a -> Bool
    p -> Optic' A_Fold (WithIx i) s a -> s -> Maybe (i, a)
    forall k (is :: IxList) i s a.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> s -> Maybe (i, a)
    iheadOf ((i -> a -> Bool) -> Optic' k is s a -> Optic' A_Fold (WithIx i) s a
    forall k (is :: IxList) i a s.
    (Is k A_Fold, HasSingleIndex is i) =>
    (i -> a -> Bool) -> Optic' k is s a -> IxFold i s a
    ifiltered i -> a -> Bool
    p Optic' k is s a
    o)
    {-# INLINE ifindOf #-}

    -- | The 'ifindMOf' function takes an 'IxFold', a monadic predicate that is also
    -- supplied the index, a structure and returns in the monad the left-most
    -- element of the structure matching the predicate, or 'Nothing' if there is no
    -- such element.
    --
    -- When you don't need access to the index then 'findMOf' is more flexible in
    -- what it accepts.
    ifindMOf
      :: (Is k A_Fold, Monad m, is `HasSingleIndex` i)
      => Optic' k is s a -> (i -> a -> m Bool) -> s -> m (Maybe (i, a))
    ifindMOf :: forall k (m :: * -> *) (is :: IxList) i s a.
    (Is k A_Fold, Monad m, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> m Bool) -> s -> m (Maybe (i, a))
    ifindMOf Optic' k is s a
    o = \i -> a -> m Bool
    f -> Optic' k is s a
    -> (i -> a -> m (Maybe (i, a)) -> m (Maybe (i, a)))
    -> m (Maybe (i, a))
    -> s
    -> m (Maybe (i, a))
    forall k (is :: IxList) i s a r.
    (Is k A_Fold, HasSingleIndex is i) =>
    Optic' k is s a -> (i -> a -> r -> r) -> r -> s -> r
    ifoldrOf Optic' k is s a
    o
      (\i
    i a
    a m (Maybe (i, a))
    y -> i -> a -> m Bool
    f i
    i a
    a m Bool -> (Bool -> m (Maybe (i, a))) -> m (Maybe (i, a))
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Bool
    r -> if Bool
    r then Maybe (i, a) -> m (Maybe (i, a))
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ((i, a) -> Maybe (i, a)
    forall a. a -> Maybe a
    Just (i
    i, a
    a)) else m (Maybe (i, a))
    y)
      (Maybe (i, a) -> m (Maybe (i, a))
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe (i, a)
    forall a. Maybe a
    Nothing)
    {-# INLINE ifindMOf #-}

    -- $setup
    -- >>> import Optics.Core