{-# 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 (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)
-> IxFold i s 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__ 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 :: 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__ (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 (Optic' k is s a -> Optic A_Fold is s s a a
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 :: 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' :: 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 :: 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_ :: 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_ :: 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 :: 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)
-> IxFold i (f 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) (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 :: (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)
-> IxFold i s 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)
 -> IxFold i s a)
-> (forall (p :: * -> * -> * -> *) i.
    Profunctor p =>
    Optic_ A_Fold p i (Curry (WithIx i) i) s s a a)
-> IxFold i s a
forall a b. (a -> b) -> a -> b
$ (s -> f a) -> p (i -> i) (f a) s -> p (i -> i) s s
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 (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)
-> IxFold i s 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__ 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 :: 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 :: (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 (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_ :: Optic' k is s a -> IxFold i s a
ibackwards_ Optic' k is s a
o = Optic A_Fold NoIx s s a a -> IxFold i s a -> IxFold i s a
forall (is :: IxList) i k s t a b.
HasSingleIndex is i =>
Optic k NoIx 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 NoIx 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) (IxFold i s a -> IxFold i s a) -> IxFold i s a -> IxFold i s a
forall a b. (a -> b) -> a -> b
$ (forall (f :: * -> *).
 Applicative f =>
 (i -> a -> f Any) -> 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 Any) -> s -> f ())
 -> IxFold i s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (i -> a -> f Any) -> s -> f ())
-> IxFold i s a
forall a b. (a -> b) -> a -> b
$ \i -> a -> f Any
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 Any) -> 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 Any -> Backwards f Any
forall k (f :: k -> *) (a :: k). f a -> Backwards f a
Backwards (f Any -> Backwards f Any) -> (a -> f Any) -> a -> Backwards f Any
forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
#. i -> a -> f Any
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 :: 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 NoIx s s a a -> IxFold i s a -> IxFold i s a
forall (is :: IxList) i k s t a b.
HasSingleIndex is i =>
Optic k NoIx 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 NoIx 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) (IxFold i s a -> IxFold i s a) -> IxFold i s a -> IxFold i s a
forall a b. (a -> b) -> a -> b
$ (forall (f :: * -> *).
 Applicative f =>
 (i -> a -> f Any) -> 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 Any) -> s -> f ())
 -> IxFold i s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (i -> a -> f Any) -> s -> f ())
-> IxFold i s a
forall a b. (a -> b) -> a -> b
$ \i -> a -> f Any
f s
s ->
  Optic' k is1 s a -> (i -> a -> f Any) -> 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 Any
f s
s f () -> f () -> f ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Optic' l is2 s a -> (i -> a -> f Any) -> 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 Any
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 :: 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 NoIx s s a a -> IxFold i s a -> IxFold i s a
forall (is :: IxList) i k s t a b.
HasSingleIndex is i =>
Optic k NoIx 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 NoIx 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) (IxFold i s a -> IxFold i s a) -> IxFold i s a -> IxFold i s a
forall a b. (a -> b) -> a -> b
$ (forall (f :: * -> *).
 Applicative f =>
 (i -> a -> f Any) -> 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 Any) -> s -> f ())
 -> IxFold i s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (i -> a -> f Any) -> s -> f ())
-> IxFold i s a
forall a b. (a -> b) -> a -> b
$ \i -> a -> f Any
f s
s ->
  let OrT Bool
visited f ()
fu = Optic' k is1 s a -> (i -> a -> OrT f Any) -> 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 Any -> OrT f Any
forall (f :: * -> *) a. f a -> OrT f a
wrapOrT (f Any -> OrT f Any) -> (a -> f Any) -> a -> OrT f Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. i -> a -> f Any
f i
i) s
s
  in if Bool
visited
     then f ()
fu
     else Optic' l is2 s a -> (i -> a -> f Any) -> 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 Any
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 :: 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 :: 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 :: 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 :: 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 :: 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 :: 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 :: 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 (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 (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 (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (i, a)
forall a. Maybe a
Nothing)
{-# INLINE ifindMOf #-}

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