    -- |
    -- Module: Optics.IxAffineTraversal
    -- Description: An indexed version of an 'Optics.AffineTraversal.AffineTraversal'.
    --
    -- An 'IxAffineTraversal' is an indexed version of an
    -- 'Optics.AffineTraversal.AffineTraversal'.  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.IxAffineTraversal
      (
      -- * Formation
        IxAffineTraversal
      , IxAffineTraversal'

      -- * Introduction
      , iatraversal

      -- * Elimination
      -- | An 'IxAffineTraversal' is in particular an
      -- 'Optics.IxAffineFold.IxAffineFold' and an 'Optics.IxSetter.IxSetter',
      -- therefore you can specialise types to obtain:
      --
      -- @
      -- 'Optics.IxAffineFold.ipreview' :: 'IxAffineTraversal' i s t a b -> s -> Maybe (i, a)
      -- @
      --
      -- @
      -- 'Optics.IxSetter.iover'    :: 'IxAffineTraversal' i s t a b -> (i -> a -> b) -> s -> t
      -- 'Optics.IxSetter.iset'     :: 'IxAffineTraversal' i s t a b -> (i      -> b) -> s -> t
      -- @

      -- * Combinators
      , unsafeFilteredBy

      -- * Additional introduction forms
      , ignored

      -- * Subtyping
      , An_AffineTraversal

      -- * van Laarhoven encoding
      , IxAffineTraversalVL
      , IxAffineTraversalVL'
      , iatraversalVL
      , iatraverseOf
      ) where

    import Data.Profunctor.Indexed

    import Optics.AffineFold
    import Optics.Internal.Indexed
    import Optics.Internal.Optic
    import Optics.Internal.Utils

    -- | Type synonym for a type-modifying indexed affine traversal.
    type IxAffineTraversal i s t a b = Optic An_AffineTraversal (WithIx i) s t a b

    -- | Type synonym for a type-preserving indexed affine traversal.
    type IxAffineTraversal' i s a = Optic' An_AffineTraversal (WithIx i) s a

    -- | Type synonym for a type-modifying van Laarhoven indexed affine traversal.
    --
    -- Note: this isn't exactly van Laarhoven representation as there is no
    -- @Pointed@ class (which would be a superclass of 'Applicative' that contains
    -- 'pure' but not '<*>'). You can interpret the first argument as a dictionary
    -- of @Pointed@ that supplies the @point@ function (i.e. the implementation of
    -- 'pure').
    --
    type IxAffineTraversalVL i s t a b =
      forall f. Functor f => (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t

    -- | Type synonym for a type-preserving van Laarhoven indexed affine traversal.
    type IxAffineTraversalVL' i s a = IxAffineTraversalVL i s s a a

    -- | Build an indexed affine traversal from a matcher and an updater.
    --
    -- If you want to build an 'IxAffineTraversal' from the van Laarhoven
    -- representation, use 'iatraversalVL'.
    iatraversal :: (s -> Either t (i, a)) -> (s -> b -> t) -> IxAffineTraversal i s t a b
    iatraversal :: forall s t i a b.
    (s -> Either t (i, a))
    -> (s -> b -> t) -> IxAffineTraversal i s t a b
    iatraversal s -> Either t (i, a)
    match s -> b -> t
    update = IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    forall i s t a b.
    IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    iatraversalVL (IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b)
    -> IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    forall a b. (a -> b) -> a -> b
    $ \forall r. r -> f r
    point i -> a -> f b
    f s
    s ->
      (t -> f t) -> ((i, a) -> f t) -> Either t (i, a) -> f t
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either t -> f t
    forall r. r -> f r
    point (\(i, a)
    a -> s -> b -> t
    update s
    s (b -> t) -> f b -> f t
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (i -> a -> f b) -> (i, a) -> f b
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry' i -> a -> f b
    f (i, a)
    a) (s -> Either t (i, a)
    match s
    s)
    {-# INLINE iatraversal #-}

    -- | Build an indexed affine traversal from the van Laarhoven representation.
    iatraversalVL :: IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    iatraversalVL :: forall i s t a b.
    IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    iatraversalVL IxAffineTraversalVL i s t a b
    f = (forall (p :: * -> * -> * -> *) i.
     Profunctor p =>
     Optic_ An_AffineTraversal p i (Curry (WithIx i) i) s t a b)
    -> Optic An_AffineTraversal (WithIx i) s t a b
    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 (IxAffineTraversalVL i s t a b -> p i a b -> p (i -> i) s t
    forall i a b s t j.
    (forall (f :: * -> *).
     Functor f =>
     (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t)
    -> p j a b -> p (i -> j) s t
    forall (p :: * -> * -> * -> *) i a b s t j.
    Visiting p =>
    (forall (f :: * -> *).
     Functor f =>
     (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t)
    -> p j a b -> p (i -> j) s t
    ivisit (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t
    IxAffineTraversalVL i s t a b
    f)
    {-# INLINE iatraversalVL #-}

    -- | Traverse over the target of an 'IxAffineTraversal' and compute a
    -- 'Functor'-based answer.
    --
    -- @since 0.3
    iatraverseOf
      :: (Is k An_AffineTraversal, Functor f, is `HasSingleIndex` i)
      => Optic k is s t a b
      -> (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t
    iatraverseOf :: forall k (f :: * -> *) (is :: IxList) i s t a b.
    (Is k An_AffineTraversal, Functor f, HasSingleIndex is i) =>
    Optic k is s t a b
    -> (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t
    iatraverseOf Optic k is s t a b
    o forall r. r -> f r
    point = \i -> a -> f b
    f ->
      IxStarA f (i -> i) s t -> (i -> i) -> s -> f t
    forall (f :: * -> *) i a b. IxStarA f i a b -> i -> a -> f b
    runIxStarA (Optic An_AffineTraversal is s t a b
    -> Optic_ An_AffineTraversal (IxStarA f) i (Curry is i) s t a b
    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 @An_AffineTraversal Optic k is s t a b
    o) ((forall r. r -> f r) -> (i -> a -> f b) -> IxStarA f i a b
    forall (f :: * -> *) i a b.
    (forall r. r -> f r) -> (i -> a -> f b) -> IxStarA f i a b
    IxStarA r -> f r
    forall r. r -> f r
    point i -> a -> f b
    f)) i -> i
    forall a. a -> a
    id
    {-# INLINE iatraverseOf #-}

    -- | Obtain a potentially empty 'IxAffineTraversal' by taking the element from
    -- another 'AffineFold' and using it as an index.
    --
    -- -- /Note:/ This is /not/ a legal 'Optics.IxTraversal.IxTraversal', unless you
    -- are very careful not to invalidate the predicate on the target (see
    -- 'Optics.AffineTraversal.unsafeFiltered' for more details).
    --
    -- @since 0.3
    unsafeFilteredBy
      :: Is k An_AffineFold
      => Optic' k is a i
      -> IxAffineTraversal' i a a
    unsafeFilteredBy :: forall k (is :: IxList) a i.
    Is k An_AffineFold =>
    Optic' k is a i -> IxAffineTraversal' i a a
    unsafeFilteredBy Optic' k is a i
    p = IxAffineTraversalVL i a a a a -> IxAffineTraversal i a a a a
    forall i s t a b.
    IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    iatraversalVL (IxAffineTraversalVL i a a a a -> IxAffineTraversal i a a a a)
    -> IxAffineTraversalVL i a a a a -> IxAffineTraversal i a a a a
    forall a b. (a -> b) -> a -> b
    $ \forall r. r -> f r
    point i -> a -> f a
    f a
    s -> case Optic' k is a i -> a -> Maybe i
    forall k (is :: IxList) s a.
    Is k An_AffineFold =>
    Optic' k is s a -> s -> Maybe a
    preview Optic' k is a i
    p a
    s of
      Just i
    i  -> i -> a -> f a
    f i
    i a
    s
      Maybe i
    Nothing -> a -> f a
    forall r. r -> f r
    point a
    s
    {-# INLINE unsafeFilteredBy #-}

    -- | This is the trivial empty 'IxAffineTraversal', i.e. the optic that targets
    -- no substructures.
    --
    -- This is the identity element when a 'Optics.Fold.Fold',
    -- 'Optics.AffineFold.AffineFold', 'Optics.IxFold.IxFold',
    -- 'Optics.IxAffineFold.IxAffineFold', 'Optics.Traversal.Traversal' or
    -- 'Optics.IxTraversal.IxTraversal' is viewed as a monoid.
    --
    -- >>> 6 & ignored %~ absurd
    -- 6
    ignored :: IxAffineTraversal i s s a b
    ignored :: forall i s a b. IxAffineTraversal i s s a b
    ignored = IxAffineTraversalVL i s s a b -> IxAffineTraversal i s s a b
    forall i s t a b.
    IxAffineTraversalVL i s t a b -> IxAffineTraversal i s t a b
    iatraversalVL (IxAffineTraversalVL i s s a b -> IxAffineTraversal i s s a b)
    -> IxAffineTraversalVL i s s a b -> IxAffineTraversal i s s a b
    forall a b. (a -> b) -> a -> b
    $ \forall r. r -> f r
    point i -> a -> f b
    _ -> s -> f s
    forall r. r -> f r
    point
    {-# INLINE ignored #-}

    -- $setup
    -- >>> import Optics.Core
    -- >>> import Data.Void (absurd)