-- |
-- Module: Optics.Fold
-- Description: Extracts elements from a container.
--
-- A @'Fold' S A@ has the ability to extract some number of elements of type @A@
-- from a container of type @S@.  For example, 'toListOf' can be used to obtain
-- the contained elements as a list. Unlike a 'Optics.Traversal.Traversal',
-- there is no way to set or update elements.
--
-- This can be seen as a generalisation of 'traverse_', where the type @S@ does
-- not need to be a type constructor with @A@ as the last parameter.
--
-- A close relative is the 'Optics.AffineFold.AffineFold', which is a 'Fold'
-- that contains at most one element.
--
module Optics.Fold
  (
  -- * Formation
    Fold

  -- * Introduction
  , foldVL

  -- * Elimination
  , foldOf
  , foldMapOf
  , foldrOf
  , foldlOf'
  , toListOf
  , sequenceOf_
  , traverseOf_
  , forOf_

  -- * Computation
  --
  -- |
  --
  -- @
  -- 'traverseOf_' ('foldVL' f) ≡ f
  -- @

  -- * Additional introduction forms
  , folded
  , folding
  , foldring
  , unfolded

  -- * Additional elimination forms
  -- | See also 'Data.Set.Optics.setOf', which constructs a 'Data.Set.Set' from a 'Fold'.
  , has
  , hasn't
  , headOf
  , lastOf
  , andOf
  , orOf
  , allOf
  , anyOf
  , noneOf
  , productOf
  , sumOf
  , asumOf
  , msumOf
  , elemOf
  , notElemOf
  , lengthOf
  , maximumOf
  , minimumOf
  , maximumByOf
  , minimumByOf
  , findOf
  , findMOf
  , lookupOf
  , universeOf
  , cosmosOf
  , paraOf

  -- * Combinators
  , pre
  , backwards_

  -- * Monoid structures #monoids#
  -- | 'Fold' admits (at least) two monoid structures:
  --
  -- * 'summing' concatenates results from both folds.
  --
  -- * 'failing' 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 'Fold', because there is
  -- not a unique choice of monoid to use, and the ('<>') operator could not be
  -- used to combine optics of different kinds.  When porting code from @lens@
  -- that uses '<>' to combine folds, use 'summing' instead.
  , summing
  , failing

  -- * Subtyping
  , A_Fold
  -- | <<diagrams/Fold.png Fold in the optics hierarchy>>
  )
  where

import Control.Applicative
import Control.Applicative.Backwards
import Control.Monad
import Data.Foldable
import Data.Function
import Data.Monoid

import Data.Profunctor.Indexed

import Optics.AffineFold
import Optics.Internal.Bi
import Optics.Internal.Fold
import Optics.Internal.Optic
import Optics.Internal.Utils

-- | Type synonym for a fold.
type Fold s a = Optic' A_Fold NoIx s a

-- | Obtain a 'Fold' by lifting 'traverse_' like function.
--
-- @
-- 'foldVL' '.' 'traverseOf_' ≡ 'id'
-- 'traverseOf_' '.' 'foldVL' ≡ 'id'
-- @
foldVL
  :: (forall f. Applicative f => (a -> f u) -> s -> f v)
  -> Fold s a
foldVL :: (forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Fold s a
foldVL forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v
f = (forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ A_Fold p i (Curry NoIx i) s s a a)
-> Fold 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 => (a -> f u) -> s -> f v)
-> Optic__ p i i s s a a
forall (p :: * -> * -> * -> *) a u s v i t b.
(Bicontravariant p, Traversing p) =>
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Optic__ p i i s t a b
foldVL__ forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v
f)
{-# INLINE foldVL #-}

-- | Combine the results of a fold using a monoid.
foldOf :: (Is k A_Fold, Monoid a) => Optic' k is s a -> s -> a
foldOf :: Optic' k is s a -> s -> a
foldOf Optic' k is s a
o = Optic' k is s a -> (a -> a) -> s -> a
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o a -> a
forall a. a -> a
id
{-# INLINE foldOf #-}

-- | Fold via embedding into a monoid.
foldMapOf :: (Is k A_Fold, Monoid m) => Optic' k is s a -> (a -> m) -> s -> m
foldMapOf :: Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o = Forget m (Curry is Any) s s -> s -> m
forall r i a b. Forget r i a b -> a -> r
runForget (Forget m (Curry is Any) s s -> s -> m)
-> (Forget m Any a a -> Forget m (Curry is Any) s s)
-> Forget m Any a a
-> s
-> m
forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
#. Optic A_Fold is s s a a
-> Optic_ A_Fold (Forget m) Any (Curry is Any) 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) (Forget m Any a a -> s -> m)
-> ((a -> m) -> Forget m Any a a) -> (a -> m) -> s -> m
forall a b c. Coercible a b => (b -> c) -> (a -> b) -> a -> c
.# (a -> m) -> Forget m Any a a
forall r i a b. (a -> r) -> Forget r i a b
Forget
{-# INLINE foldMapOf #-}

-- | Fold right-associatively.
foldrOf :: Is k A_Fold => Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf :: Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s a
o = \a -> r -> r
arr r
r s
s -> (\Endo r
e -> Endo r -> r -> r
forall a. Endo a -> a -> a
appEndo Endo r
e r
r) (Endo r -> r) -> Endo r -> r
forall a b. (a -> b) -> a -> b
$ Optic' k is s a -> (a -> Endo r) -> s -> Endo r
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o ((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
#. a -> r -> r
arr) s
s
{-# INLINE foldrOf #-}

-- | Fold left-associatively, and strictly.
foldlOf' :: Is k A_Fold => Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' :: Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o = \r -> a -> r
rar r
r0 s
s -> Optic' k is s a
-> (a -> (r -> r) -> r -> r) -> (r -> r) -> s -> r -> r
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s a
o (\a
a r -> r
rr r
r -> r -> r
rr (r -> r) -> r -> r
forall a b. (a -> b) -> a -> b
$! r -> a -> r
rar r
r a
a) r -> r
forall a. a -> a
id s
s r
r0
{-# INLINE foldlOf' #-}

-- | Fold to a list.
--
-- >>> toListOf (_1 % folded % _Right) ([Right 'h', Left 5, Right 'i'], "bye")
-- "hi"
toListOf :: Is k A_Fold => Optic' k is s a -> s -> [a]
toListOf :: Optic' k is s a -> s -> [a]
toListOf Optic' k is s a
o = Optic' k is s a -> (a -> [a] -> [a]) -> [a] -> s -> [a]
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s a
o (:) []
{-# INLINE toListOf #-}

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

-- | Traverse over all of the targets of a 'Fold', computing an
-- 'Applicative'-based answer, but unlike 'Optics.Traversal.traverseOf' do not
-- construct a new structure. 'traverseOf_' generalizes
-- 'Data.Foldable.traverse_' to work over any 'Fold'.
--
-- >>> traverseOf_ each putStrLn ("hello","world")
-- hello
-- world
--
-- @
-- 'Data.Foldable.traverse_' ≡ 'traverseOf_' 'folded'
-- @
traverseOf_
  :: (Is k A_Fold, Applicative f)
  => Optic' k is s a
  -> (a -> f r) -> s -> f ()
traverseOf_ :: Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' k is s a
o = \a -> f r
f -> 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 -> (a -> Traversed f r) -> s -> Traversed f r
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o (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
#. a -> f r
f)
{-# INLINE traverseOf_ #-}

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

-- | Evaluate each action in a structure observed by a 'Fold' from left to
-- right, ignoring the results.
--
-- @
-- 'sequenceA_' ≡ 'sequenceOf_' 'folded'
-- @
--
-- >>> sequenceOf_ each (putStrLn "hello",putStrLn "world")
-- hello
-- world
sequenceOf_
  :: (Is k A_Fold, Applicative f)
  => Optic' k is s (f a)
  -> s -> f ()
sequenceOf_ :: Optic' k is s (f a) -> s -> f ()
sequenceOf_ Optic' k is s (f a)
o = Traversed f a -> f ()
forall (f :: * -> *) a. Functor f => Traversed f a -> f ()
runTraversed (Traversed f a -> f ()) -> (s -> Traversed f a) -> s -> f ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is s (f a) -> (f a -> Traversed f a) -> s -> Traversed f a
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s (f a)
o f a -> Traversed f a
forall (f :: * -> *) a. f a -> Traversed f a
Traversed
{-# INLINE sequenceOf_ #-}

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

-- | Fold via the 'Foldable' class.
folded :: Foldable f => Fold (f a) a
folded :: Fold (f a) a
folded = (forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ A_Fold p i (Curry NoIx i) (f a) (f a) a a)
-> Fold (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 NoIx i) (f a) (f a) a a
forall (p :: * -> * -> * -> *) (f :: * -> *) i a b.
(Bicontravariant p, Traversing p, Foldable f) =>
Optic__ p i i (f a) (f b) a b
folded__
{-# INLINE folded #-}

-- | Obtain a 'Fold' by lifting an operation that returns a 'Foldable' result.
--
-- This can be useful to lift operations from @Data.List@ and elsewhere into a
-- 'Fold'.
--
-- >>> toListOf (folding tail) [1,2,3,4]
-- [2,3,4]
folding :: Foldable f => (s -> f a) -> Fold s a
folding :: (s -> f a) -> Fold s a
folding s -> f a
f = (forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ A_Fold p i (Curry NoIx i) s s a a)
-> Fold 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 ((s -> f a) -> p i (f a) s -> p 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 (f a) s -> p i s s)
-> (p i a a -> p i (f a) s) -> p i a a -> p i s s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (f :: * -> *).
 Applicative f =>
 (a -> f Any) -> f a -> f ())
-> p i a a -> p i (f a) s
forall (p :: * -> * -> * -> *) a u s v i t b.
(Bicontravariant p, Traversing p) =>
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Optic__ p i i s t a b
foldVL__ forall (f :: * -> *). Applicative f => (a -> f Any) -> f a -> f ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_)
{-# INLINE folding #-}

-- | Obtain a 'Fold' by lifting 'foldr' like function.
--
-- >>> toListOf (foldring foldr) [1,2,3,4]
-- [1,2,3,4]
foldring
  :: (forall f. Applicative f => (a -> f u -> f u) -> f v -> s -> f w)
  -> Fold s a
foldring :: (forall (f :: * -> *).
 Applicative f =>
 (a -> f u -> f u) -> f v -> s -> f w)
-> Fold s a
foldring forall (f :: * -> *).
Applicative f =>
(a -> f u -> f u) -> f v -> s -> f w
fr = (forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ A_Fold p i (Curry NoIx i) s s a a)
-> Fold 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 =>
 (a -> f u -> f u) -> f v -> s -> f w)
-> Optic__ p i i s s a a
forall (p :: * -> * -> * -> *) a u v s w i t b.
(Bicontravariant p, Traversing p) =>
(forall (f :: * -> *).
 Applicative f =>
 (a -> f u -> f u) -> f v -> s -> f w)
-> Optic__ p i i s t a b
foldring__ forall (f :: * -> *).
Applicative f =>
(a -> f u -> f u) -> f v -> s -> f w
fr)
{-# INLINE foldring #-}

-- | Build a 'Fold' that unfolds its values from a seed.
--
-- @
-- 'Prelude.unfoldr' ≡ 'toListOf' '.' 'unfolded'
-- @
--
-- >>> toListOf (unfolded $ \b -> if b == 0 then Nothing else Just (b, b - 1)) 10
-- [10,9,8,7,6,5,4,3,2,1]
unfolded :: (s -> Maybe (a, s)) -> Fold s a
unfolded :: (s -> Maybe (a, s)) -> Fold s a
unfolded s -> Maybe (a, s)
step = (forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
-> Fold s a
forall a u s v.
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Fold s a
foldVL ((forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
 -> Fold s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (a -> f Any) -> s -> f ())
-> Fold s a
forall a b. (a -> b) -> a -> b
$ \a -> f Any
f -> ((s -> f ()) -> s -> f ()) -> s -> f ()
forall a. (a -> a) -> a
fix (((s -> f ()) -> s -> f ()) -> s -> f ())
-> ((s -> f ()) -> s -> f ()) -> s -> f ()
forall a b. (a -> b) -> a -> b
$ \s -> f ()
loop s
b ->
  case s -> Maybe (a, s)
step s
b of
    Just (a
a, s
b') -> a -> f Any
f a
a f Any -> f () -> f ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> s -> f ()
loop s
b'
    Maybe (a, s)
Nothing      -> () -> f ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
{-# INLINE unfolded #-}

-- | Convert a fold to an 'AffineFold' that visits the first element of the
-- original fold.
--
-- For the traversal version see 'Optics.Traversal.singular'.
pre :: Is k A_Fold => Optic' k is s a -> AffineFold s a
pre :: Optic' k is s a -> AffineFold s a
pre = (s -> Maybe a) -> AffineFold s a
forall s a. (s -> Maybe a) -> AffineFold s a
afolding ((s -> Maybe a) -> AffineFold s a)
-> (Optic' k is s a -> s -> Maybe a)
-> Optic' k is s a
-> AffineFold s a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is s a -> s -> Maybe a
forall k (is :: IxList) s a.
Is k A_Fold =>
Optic' k is s a -> s -> Maybe a
headOf
{-# INLINE pre #-}

-- | This allows you to traverse the elements of a 'Fold' in the opposite order.
backwards_
  :: Is k A_Fold
  => Optic' k is s a
  -> Fold s a
backwards_ :: Optic' k is s a -> Fold s a
backwards_ Optic' k is s a
o = (forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
-> Fold s a
forall a u s v.
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Fold s a
foldVL ((forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
 -> Fold s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (a -> f Any) -> s -> f ())
-> Fold s a
forall a b. (a -> b) -> a -> b
$ \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 -> (a -> Backwards f Any) -> s -> Backwards f ()
forall k (f :: * -> *) (is :: IxList) s a r.
(Is k A_Fold, Applicative f) =>
Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' k is s a
o (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
#. a -> f Any
f)
{-# INLINE backwards_ #-}

-- | Return entries of the first 'Fold', then the second one.
--
-- >>> toListOf (_1 % ix 0 `summing` _2 % ix 1) ([1,2], [4,7,1])
-- [1,7]
--
-- For the traversal version see 'Optics.Traversal.adjoin'.
summing
  :: (Is k A_Fold, Is l A_Fold)
  => Optic' k is s a
  -> Optic' l js s a
  -> Fold s a
summing :: Optic' k is s a -> Optic' l js s a -> Fold s a
summing Optic' k is s a
a Optic' l js s a
b = (forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
-> Fold s a
forall a u s v.
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Fold s a
foldVL ((forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
 -> Fold s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (a -> f Any) -> s -> f ())
-> Fold s a
forall a b. (a -> b) -> a -> b
$ \a -> f Any
f s
s -> Optic' k is s a -> (a -> f Any) -> s -> f ()
forall k (f :: * -> *) (is :: IxList) s a r.
(Is k A_Fold, Applicative f) =>
Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' k is s a
a a -> f Any
f s
s f () -> f () -> f ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Optic' l js s a -> (a -> f Any) -> s -> f ()
forall k (f :: * -> *) (is :: IxList) s a r.
(Is k A_Fold, Applicative f) =>
Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' l js s a
b a -> f Any
f s
s
infixr 6 `summing` -- Same as (<>)
{-# INLINE summing #-}

-- | Try the first 'Fold'. If it returns no entries, try the second one.
--
-- >>> toListOf (ix 1 `failing` ix 0) [4,7]
-- [7]
-- >>> toListOf (ix 1 `failing` ix 0) [4]
-- [4]
--
failing
  :: (Is k A_Fold, Is l A_Fold)
  => Optic' k is s a
  -> Optic' l js s a
  -> Fold s a
failing :: Optic' k is s a -> Optic' l js s a -> Fold s a
failing Optic' k is s a
a Optic' l js s a
b = (forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
-> Fold s a
forall a u s v.
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Fold s a
foldVL ((forall (f :: * -> *). Applicative f => (a -> f Any) -> s -> f ())
 -> Fold s a)
-> (forall (f :: * -> *).
    Applicative f =>
    (a -> f Any) -> s -> f ())
-> Fold s a
forall a b. (a -> b) -> a -> b
$ \a -> f Any
f s
s ->
  let OrT Bool
visited f ()
fu = Optic' k is s a -> (a -> OrT f Any) -> s -> OrT f ()
forall k (f :: * -> *) (is :: IxList) s a r.
(Is k A_Fold, Applicative f) =>
Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' k is s a
a (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
. a -> f Any
f) s
s
  in if Bool
visited
     then f ()
fu
     else Optic' l js s a -> (a -> f Any) -> s -> f ()
forall k (f :: * -> *) (is :: IxList) s a r.
(Is k A_Fold, Applicative f) =>
Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' l js s a
b a -> f Any
f s
s
infixl 3 `failing` -- Same as (<|>)
{-# INLINE failing #-}

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

-- | Check to see if this optic matches 1 or more entries.
--
-- >>> has _Left (Left 12)
-- True
--
-- >>> has _Right (Left 12)
-- False
--
-- This will always return 'True' for a 'Optics.Lens.Lens' or
-- 'Optics.Getter.Getter'.
--
-- >>> has _1 ("hello","world")
-- True
has :: Is k A_Fold => Optic' k is s a -> s -> Bool
has :: Optic' k is s a -> s -> Bool
has Optic' k is s a
o = 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 -> (a -> Any) -> s -> Any
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o (\a
_ -> Bool -> Any
Any Bool
True)
{-# INLINE has #-}

-- | Check to see if this 'Fold' or 'Optics.Traversal.Traversal' has
-- no matches.
--
-- >>> hasn't _Left (Right 12)
-- True
--
-- >>> hasn't _Left (Left 12)
-- False
hasn't :: Is k A_Fold => Optic' k is s a -> s -> Bool
hasn't :: Optic' k is s a -> s -> Bool
hasn't Optic' k is s a
o = 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 -> (a -> All) -> s -> All
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o (\a
_ -> Bool -> All
All Bool
False)
{-# INLINE hasn't #-}

-- | Retrieve the first entry of a 'Fold'.
--
-- >>> headOf folded [1..10]
-- Just 1
--
-- >>> headOf each (1,2)
-- Just 1
headOf :: Is k A_Fold => Optic' k is s a -> s -> Maybe a
headOf :: Optic' k is s a -> s -> Maybe a
headOf Optic' k is s a
o = Leftmost a -> Maybe a
forall a. Leftmost a -> Maybe a
getLeftmost (Leftmost a -> Maybe a) -> (s -> Leftmost a) -> s -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is s a -> (a -> Leftmost a) -> s -> Leftmost a
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o a -> Leftmost a
forall a. a -> Leftmost a
LLeaf
{-# INLINE headOf #-}

-- | Retrieve the last entry of a 'Fold'.
--
-- >>> lastOf folded [1..10]
-- Just 10
--
-- >>> lastOf each (1,2)
-- Just 2
lastOf :: Is k A_Fold => Optic' k is s a -> s -> Maybe a
lastOf :: Optic' k is s a -> s -> Maybe a
lastOf Optic' k is s a
o = Rightmost a -> Maybe a
forall a. Rightmost a -> Maybe a
getRightmost (Rightmost a -> Maybe a) -> (s -> Rightmost a) -> s -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is s a -> (a -> Rightmost a) -> s -> Rightmost a
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o a -> Rightmost a
forall a. a -> Rightmost a
RLeaf
{-# INLINE lastOf #-}

-- | Returns 'True' if every target of a 'Fold' is 'True'.
--
-- >>> andOf each (True, False)
-- False
-- >>> andOf each (True, True)
-- True
--
-- @
-- 'Data.Foldable.and' ≡ 'andOf' 'folded'
-- @
andOf :: Is k A_Fold => Optic' k is s Bool -> s -> Bool
andOf :: Optic' k is s Bool -> s -> Bool
andOf Optic' k is s Bool
o = 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 Bool -> (Bool -> All) -> s -> All
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s Bool
o Bool -> All
All
{-# INLINE andOf #-}

-- | Returns 'True' if any target of a 'Fold' is 'True'.
--
-- >>> orOf each (True, False)
-- True
-- >>> orOf each (False, False)
-- False
--
-- @
-- 'Data.Foldable.or' ≡ 'orOf' 'folded'
-- @
orOf :: Is k A_Fold => Optic' k is s Bool -> s -> Bool
orOf :: Optic' k is s Bool -> s -> Bool
orOf Optic' k is s Bool
o = 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 Bool -> (Bool -> Any) -> s -> Any
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s Bool
o Bool -> Any
Any
{-# INLINE orOf #-}

-- | Returns 'True' if any target of a 'Fold' satisfies a predicate.
--
-- >>> anyOf each (=='x') ('x','y')
-- True
anyOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool
anyOf :: Optic' k is s a -> (a -> Bool) -> s -> Bool
anyOf Optic' k is s a
o = \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 -> (a -> Any) -> s -> Any
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o (Bool -> Any
Any (Bool -> Any) -> (a -> Bool) -> a -> Any
forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
#. a -> Bool
f)
{-# INLINE anyOf #-}

-- | Returns 'True' if every target of a 'Fold' satisfies a predicate.
--
-- >>> allOf each (>=3) (4,5)
-- True
-- >>> allOf folded (>=2) [1..10]
-- False
--
-- @
-- 'Data.Foldable.all' ≡ 'allOf' 'folded'
-- @
allOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool
allOf :: Optic' k is s a -> (a -> Bool) -> s -> Bool
allOf Optic' k is s a
o = \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 -> (a -> All) -> s -> All
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is s a
o (Bool -> All
All (Bool -> All) -> (a -> Bool) -> a -> All
forall b c a. Coercible b c => (b -> c) -> (a -> b) -> a -> c
#. a -> Bool
f)
{-# INLINE allOf #-}

-- | Returns 'True' only if no targets of a 'Fold' satisfy a predicate.
--
-- >>> noneOf each (not . isn't _Nothing) (Just 3, Just 4, Just 5)
-- True
-- >>> noneOf (folded % folded) (<10) [[13,99,20],[3,71,42]]
-- False
noneOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool
noneOf :: Optic' k is s a -> (a -> Bool) -> s -> Bool
noneOf Optic' k is s a
o = \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 -> (a -> Bool) -> s -> Bool
forall k (is :: IxList) s a.
Is k A_Fold =>
Optic' k is s a -> (a -> Bool) -> s -> Bool
anyOf Optic' k is s a
o a -> Bool
f
{-# INLINE noneOf #-}

-- | Calculate the 'Product' of every number targeted by a 'Fold'.
--
-- >>> productOf each (4,5)
-- 20
-- >>> productOf folded [1,2,3,4,5]
-- 120
--
-- @
-- 'Data.Foldable.product' ≡ 'productOf' 'folded'
-- @
--
-- This operation may be more strict than you would expect. If you want a lazier
-- version use @\\o -> 'getProduct' '.' 'foldMapOf' o 'Product'@.
productOf :: (Is k A_Fold, Num a) => Optic' k is s a -> s -> a
productOf :: Optic' k is s a -> s -> a
productOf Optic' k is s a
o = Optic' k is s a -> (a -> a -> a) -> a -> s -> a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o a -> a -> a
forall a. Num a => a -> a -> a
(*) a
1
{-# INLINE productOf #-}

-- | Calculate the 'Sum' of every number targeted by a 'Fold'.
--
-- >>> sumOf each (5,6)
-- 11
-- >>> sumOf folded [1,2,3,4]
-- 10
-- >>> sumOf (folded % each) [(1,2),(3,4)]
-- 10
--
-- @
-- 'Data.Foldable.sum' ≡ 'sumOf' 'folded'
-- @
--
-- This operation may be more strict than you would expect. If you want a lazier
-- version use @\\o -> 'getSum' '.' 'foldMapOf' o 'Sum'@
sumOf :: (Is k A_Fold, Num a) => Optic' k is s a -> s -> a
sumOf :: Optic' k is s a -> s -> a
sumOf Optic' k is s a
o = Optic' k is s a -> (a -> a -> a) -> a -> s -> a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o a -> a -> a
forall a. Num a => a -> a -> a
(+) a
0
{-# INLINE sumOf #-}

-- | The sum of a collection of actions.
--
-- >>> asumOf each ("hello","world")
-- "helloworld"
--
-- >>> asumOf each (Nothing, Just "hello", Nothing)
-- Just "hello"
--
-- @
-- 'asum' ≡ 'asumOf' 'folded'
-- @
asumOf :: (Is k A_Fold, Alternative f) => Optic' k is s (f a) -> s -> f a
asumOf :: Optic' k is s (f a) -> s -> f a
asumOf Optic' k is s (f a)
o = Optic' k is s (f a) -> (f a -> f a -> f a) -> f a -> s -> f a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s (f a)
o f a -> f a -> f a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>) f a
forall (f :: * -> *) a. Alternative f => f a
empty
{-# INLINE asumOf #-}

-- | The sum of a collection of actions.
--
-- >>> msumOf each ("hello","world")
-- "helloworld"
--
-- >>> msumOf each (Nothing, Just "hello", Nothing)
-- Just "hello"
--
-- @
-- 'msum' ≡ 'msumOf' 'folded'
-- @
msumOf :: (Is k A_Fold, MonadPlus m) => Optic' k is s (m a) -> s -> m a
msumOf :: Optic' k is s (m a) -> s -> m a
msumOf Optic' k is s (m a)
o = Optic' k is s (m a) -> (m a -> m a -> m a) -> m a -> s -> m a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s (m a)
o m a -> m a -> m a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
{-# INLINE msumOf #-}

-- | Does the element occur anywhere within a given 'Fold' of the structure?
--
-- >>> elemOf each "hello" ("hello","world")
-- True
--
-- @
-- 'elem' ≡ 'elemOf' 'folded'
-- @
elemOf :: (Is k A_Fold, Eq a) => Optic' k is s a -> a -> s -> Bool
elemOf :: Optic' k is s a -> a -> s -> Bool
elemOf Optic' k is s a
o = Optic' k is s a -> (a -> Bool) -> s -> Bool
forall k (is :: IxList) s a.
Is k A_Fold =>
Optic' k is s a -> (a -> Bool) -> s -> Bool
anyOf Optic' k is s a
o ((a -> Bool) -> s -> Bool) -> (a -> a -> Bool) -> a -> s -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)
{-# INLINE elemOf #-}

-- | Does the element not occur anywhere within a given 'Fold' of the structure?
--
-- >>> notElemOf each 'd' ('a','b','c')
-- True
--
-- >>> notElemOf each 'a' ('a','b','c')
-- False
--
-- @
-- 'notElem' ≡ 'notElemOf' 'folded'
-- @
notElemOf :: (Is k A_Fold, Eq a) => Optic' k is s a -> a -> s -> Bool
notElemOf :: Optic' k is s a -> a -> s -> Bool
notElemOf Optic' k is s a
o = Optic' k is s a -> (a -> Bool) -> s -> Bool
forall k (is :: IxList) s a.
Is k A_Fold =>
Optic' k is s a -> (a -> Bool) -> s -> Bool
allOf Optic' k is s a
o ((a -> Bool) -> s -> Bool) -> (a -> a -> Bool) -> a -> s -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(/=)
{-# INLINE notElemOf #-}

-- | Calculate the number of targets there are for a 'Fold' in a given
-- container.
--
-- /Note:/ This can be rather inefficient for large containers and just like
-- 'length', this will not terminate for infinite folds.
--
-- @
-- 'length' ≡ 'lengthOf' 'folded'
-- @
--
-- >>> lengthOf _1 ("hello",())
-- 1
--
-- >>> lengthOf folded [1..10]
-- 10
--
-- >>> lengthOf (folded % folded) [[1,2],[3,4],[5,6]]
-- 6
lengthOf :: Is k A_Fold => Optic' k is s a -> s -> Int
lengthOf :: Optic' k is s a -> s -> Int
lengthOf Optic' k is s a
o = Optic' k is s a -> (Int -> a -> Int) -> Int -> s -> Int
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o (\ Int
n a
_ -> Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n) Int
0
{-# INLINE lengthOf #-}

-- | Obtain the maximum element (if any) targeted by a 'Fold' safely.
--
-- Note: 'maximumOf' on a valid 'Optics.Iso.Iso', 'Optics.Lens.Lens'
-- or 'Optics.Getter.Getter' will always return 'Just' a value.
--
-- >>> maximumOf folded [1..10]
-- Just 10
--
-- >>> maximumOf folded []
-- Nothing
--
-- >>> maximumOf (folded % filtered even) [1,4,3,6,7,9,2]
-- Just 6
--
-- @
-- 'maximum' ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'maximumOf' 'folded'
-- @
--
-- In the interest of efficiency, This operation has semantics more strict than
-- strictly necessary.  @\\o -> 'Data.Semigroup.getMax' . 'foldMapOf' o 'Data.Semigroup.Max'@ has lazier
-- semantics but could leak memory.
maximumOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Maybe a
maximumOf :: Optic' k is s a -> s -> Maybe a
maximumOf Optic' k is s a
o = Optic' k is s a
-> (Maybe a -> a -> Maybe a) -> Maybe a -> s -> Maybe a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o Maybe a -> a -> Maybe a
forall a. Ord a => Maybe a -> a -> Maybe a
mf Maybe a
forall a. Maybe a
Nothing where
  mf :: Maybe a -> a -> Maybe a
mf Maybe a
Nothing a
y  = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! a
y
  mf (Just a
x) a
y = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! a -> a -> a
forall a. Ord a => a -> a -> a
max a
x a
y
{-# INLINE maximumOf #-}

-- | Obtain the minimum element (if any) targeted by a 'Fold' safely.
--
-- Note: 'minimumOf' on a valid 'Optics.Iso.Iso', 'Optics.Lens.Lens'
-- or 'Optics.Getter.Getter' will always return 'Just' a value.
--
-- >>> minimumOf folded [1..10]
-- Just 1
--
-- >>> minimumOf folded []
-- Nothing
--
-- >>> minimumOf (folded % filtered even) [1,4,3,6,7,9,2]
-- Just 2
--
-- @
-- 'minimum' ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'minimumOf' 'folded'
-- @
--
-- In the interest of efficiency, This operation has semantics more strict than
-- strictly necessary.  @\\o -> 'Data.Semigroup.getMin' . 'foldMapOf' o 'Data.Semigroup.Min'@ has lazier
-- semantics but could leak memory.
minimumOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Maybe a
minimumOf :: Optic' k is s a -> s -> Maybe a
minimumOf Optic' k is s a
o = Optic' k is s a
-> (Maybe a -> a -> Maybe a) -> Maybe a -> s -> Maybe a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o Maybe a -> a -> Maybe a
forall a. Ord a => Maybe a -> a -> Maybe a
mf Maybe a
forall a. Maybe a
Nothing where
  mf :: Maybe a -> a -> Maybe a
mf Maybe a
Nothing a
y = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! a
y
  mf (Just a
x) a
y = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! a -> a -> a
forall a. Ord a => a -> a -> a
min a
x a
y
{-# INLINE minimumOf #-}

-- | Obtain the maximum element (if any) targeted by a 'Fold' according to a
-- user supplied 'Ordering'.
--
-- >>> maximumByOf folded (compare `on` length) ["mustard","relish","ham"]
-- Just "mustard"
--
-- In the interest of efficiency, This operation has semantics more strict than
-- strictly necessary.
--
-- @
-- 'Data.Foldable.maximumBy' cmp ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'maximumByOf' 'folded' cmp
-- @
maximumByOf :: Is k A_Fold => Optic' k is s a -> (a -> a -> Ordering) -> s -> Maybe a
maximumByOf :: Optic' k is s a -> (a -> a -> Ordering) -> s -> Maybe a
maximumByOf Optic' k is s a
o = \a -> a -> Ordering
cmp ->
  let mf :: Maybe a -> a -> Maybe a
mf Maybe a
Nothing a
y  = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! a
y
      mf (Just a
x) a
y = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! if a -> a -> Ordering
cmp a
x a
y Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
GT then a
x else a
y
  in Optic' k is s a
-> (Maybe a -> a -> Maybe a) -> Maybe a -> s -> Maybe a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o Maybe a -> a -> Maybe a
mf Maybe a
forall a. Maybe a
Nothing
{-# INLINE maximumByOf #-}

-- | Obtain the minimum element (if any) targeted by a 'Fold' according to a
-- user supplied 'Ordering'.
--
-- In the interest of efficiency, This operation has semantics more strict than
-- strictly necessary.
--
-- >>> minimumByOf folded (compare `on` length) ["mustard","relish","ham"]
-- Just "ham"
--
-- @
-- 'minimumBy' cmp ≡ 'Data.Maybe.fromMaybe' ('error' \"empty\") '.' 'minimumByOf' 'folded' cmp
-- @
minimumByOf :: Is k A_Fold => Optic' k is s a -> (a -> a -> Ordering) -> s -> Maybe a
minimumByOf :: Optic' k is s a -> (a -> a -> Ordering) -> s -> Maybe a
minimumByOf Optic' k is s a
o = \a -> a -> Ordering
cmp ->
  let mf :: Maybe a -> a -> Maybe a
mf Maybe a
Nothing a
y  = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! a
y
      mf (Just a
x) a
y = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$! if a -> a -> Ordering
cmp a
x a
y Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
GT then a
y else a
x
  in Optic' k is s a
-> (Maybe a -> a -> Maybe a) -> Maybe a -> s -> Maybe a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (r -> a -> r) -> r -> s -> r
foldlOf' Optic' k is s a
o Maybe a -> a -> Maybe a
mf Maybe a
forall a. Maybe a
Nothing
{-# INLINE minimumByOf #-}

-- | The 'findOf' function takes a 'Fold', a predicate and a structure and
-- returns the leftmost element of the structure matching the predicate, or
-- 'Nothing' if there is no such element.
--
-- >>> findOf each even (1,3,4,6)
-- Just 4
--
-- >>> findOf folded even [1,3,5,7]
-- Nothing
--
-- @
-- 'Data.Foldable.find' ≡ 'findOf' 'folded'
-- @
findOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Maybe a
findOf :: Optic' k is s a -> (a -> Bool) -> s -> Maybe a
findOf Optic' k is s a
o = \a -> Bool
f -> Optic' k is s a
-> (a -> Maybe a -> Maybe a) -> Maybe a -> s -> Maybe a
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s a
o (\a
a Maybe a
y -> if a -> Bool
f a
a then a -> Maybe a
forall a. a -> Maybe a
Just a
a else Maybe a
y) Maybe a
forall a. Maybe a
Nothing
{-# INLINE findOf #-}

-- | The 'findMOf' function takes a 'Fold', a monadic predicate and a structure
-- and returns in the monad the leftmost element of the structure matching the
-- predicate, or 'Nothing' if there is no such element.
--
-- >>> findMOf each (\x -> print ("Checking " ++ show x) >> return (even x)) (1,3,4,6)
-- "Checking 1"
-- "Checking 3"
-- "Checking 4"
-- Just 4
--
-- >>> findMOf each (\x -> print ("Checking " ++ show x) >> return (even x)) (1,3,5,7)
-- "Checking 1"
-- "Checking 3"
-- "Checking 5"
-- "Checking 7"
-- Nothing
--
-- @
-- 'findMOf' 'folded' :: (Monad m, Foldable f) => (a -> m Bool) -> f a -> m (Maybe a)
-- @
findMOf :: (Is k A_Fold, Monad m) => Optic' k is s a -> (a -> m Bool) -> s -> m (Maybe a)
findMOf :: Optic' k is s a -> (a -> m Bool) -> s -> m (Maybe a)
findMOf Optic' k is s a
o = \a -> m Bool
f -> Optic' k is s a
-> (a -> m (Maybe a) -> m (Maybe a))
-> m (Maybe a)
-> s
-> m (Maybe a)
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s a
o
  (\a
a m (Maybe a)
y -> a -> m Bool
f a
a m Bool -> (Bool -> m (Maybe a)) -> m (Maybe a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
r -> if Bool
r then Maybe a -> m (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> Maybe a
forall a. a -> Maybe a
Just a
a) else m (Maybe a)
y)
  (Maybe a -> m (Maybe a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe a
forall a. Maybe a
Nothing)
{-# INLINE findMOf #-}

-- | The 'lookupOf' function takes a 'Fold', a key, and a structure containing
-- key/value pairs.  It returns the first value corresponding to the given
-- key. This function generalizes 'lookup' to work on an arbitrary 'Fold'
-- instead of lists.
--
-- >>> lookupOf folded 4 [(2, 'a'), (4, 'b'), (4, 'c')]
-- Just 'b'
--
-- >>> lookupOf folded 2 [(2, 'a'), (4, 'b'), (4, 'c')]
-- Just 'a'
lookupOf :: (Is k A_Fold, Eq a) => Optic' k is s (a, v) -> a -> s -> Maybe v
lookupOf :: Optic' k is s (a, v) -> a -> s -> Maybe v
lookupOf Optic' k is s (a, v)
o a
a = Optic' k is s (a, v)
-> ((a, v) -> Maybe v -> Maybe v) -> Maybe v -> s -> Maybe v
forall k (is :: IxList) s a r.
Is k A_Fold =>
Optic' k is s a -> (a -> r -> r) -> r -> s -> r
foldrOf Optic' k is s (a, v)
o (\(a
a', v
v) Maybe v
next -> if a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a' then v -> Maybe v
forall a. a -> Maybe a
Just v
v else Maybe v
next) Maybe v
forall a. Maybe a
Nothing
{-# INLINE lookupOf #-}

-- | Given a 'Fold' that knows how to locate immediate children, retrieve all of
-- the transitive descendants of a node, including itself.
--
-- @since 0.4.1
universeOf :: Is k A_Fold => Optic' k is a a -> a -> [a]
universeOf :: Optic' k is a a -> a -> [a]
universeOf Optic' k is a a
o = (Endo [a] -> [a] -> [a]
forall a. Endo a -> a -> a
`appEndo` []) (Endo [a] -> [a]) -> (a -> Endo [a]) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Endo [a]
go
  where
    go :: a -> Endo [a]
go a
a = ([a] -> [a]) -> Endo [a]
forall a. (a -> a) -> Endo a
Endo (a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
:) Endo [a] -> Endo [a] -> Endo [a]
forall a. Semigroup a => a -> a -> a
<> Optic' k is a a -> (a -> Endo [a]) -> a -> Endo [a]
forall k m (is :: IxList) s a.
(Is k A_Fold, Monoid m) =>
Optic' k is s a -> (a -> m) -> s -> m
foldMapOf Optic' k is a a
o a -> Endo [a]
go a
a
{-# INLINE universeOf #-}

-- | Given a 'Fold' that knows how to locate immediate children, fold all of the
-- transitive descendants of a node, including itself.
--
-- @since 0.4.1
cosmosOf :: forall k is a. Is k A_Fold => Optic' k is a a -> Fold a a
cosmosOf :: Optic' k is a a -> Fold a a
cosmosOf Optic' k is a a
o = (forall (f :: * -> *). Applicative f => (a -> f ()) -> a -> f ())
-> Fold a a
forall a u s v.
(forall (f :: * -> *). Applicative f => (a -> f u) -> s -> f v)
-> Fold s a
foldVL forall (f :: * -> *). Applicative f => (a -> f ()) -> a -> f ()
go
  where
    go :: Applicative f => (a -> f ()) -> a -> f ()
    go :: (a -> f ()) -> a -> f ()
go a -> f ()
f a
a = a -> f ()
f a
a f () -> f () -> f ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Optic' k is a a -> (a -> f ()) -> a -> f ()
forall k (f :: * -> *) (is :: IxList) s a r.
(Is k A_Fold, Applicative f) =>
Optic' k is s a -> (a -> f r) -> s -> f ()
traverseOf_ Optic' k is a a
o ((a -> f ()) -> a -> f ()
forall (f :: * -> *). Applicative f => (a -> f ()) -> a -> f ()
go a -> f ()
f) a
a
{-# INLINE cosmosOf #-}

-- | Perform a fold-like computation on each value, technically a paramorphism.
--
-- @since 0.4.1
paraOf :: Is k A_Fold => Optic' k is a a -> (a -> [r] -> r) -> a -> r
paraOf :: Optic' k is a a -> (a -> [r] -> r) -> a -> r
paraOf Optic' k is a a
o a -> [r] -> r
f = a -> r
go
  where
    go :: a -> r
go a
a = a -> [r] -> r
f a
a (a -> r
go (a -> r) -> [a] -> [r]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Optic' k is a a -> a -> [a]
forall k (is :: IxList) s a.
Is k A_Fold =>
Optic' k is s a -> s -> [a]
toListOf Optic' k is a a
o a
a)
{-# INLINE paraOf #-}

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