#ifdef TRUSTWORTHY
#endif
#ifndef MIN_VERSION_containers
#define MIN_VERSION_containers(x,y,z) 1
#endif
module Control.Lens.Indexed
(
Indexable(..)
, Conjoined(..)
, Indexed(..)
, (<.), (<.>), (.>)
, selfIndex
, reindexed
, icompose
, indexing
, indexing64
, FunctorWithIndex(..)
, FoldableWithIndex(..)
, iany
, iall
, inone, none
, itraverse_
, ifor_
, imapM_
, iforM_
, iconcatMap
, ifind
, ifoldrM
, ifoldlM
, itoList
, withIndex
, asIndex
, indices
, index
, TraversableWithIndex(..)
, ifor
, imapM
, iforM
, imapAccumR
, imapAccumL
, ifoldMapBy
, ifoldMapByOf
) where
import Control.Applicative
import Control.Applicative.Backwards
import Control.Comonad.Cofree
import Control.Comonad.Trans.Traced
import Control.Monad (void, liftM)
import Control.Monad.Trans.Identity
import Control.Monad.Trans.Reader
import Control.Monad.Trans.State.Lazy as Lazy
import Control.Monad.Free
import Control.Lens.Fold
import Control.Lens.Getter
import Control.Lens.Internal.Fold
import Control.Lens.Internal.Indexed
import Control.Lens.Internal.Level
import Control.Lens.Internal.Magma
import Control.Lens.Setter
import Control.Lens.Traversal
import Control.Lens.Type
import Data.Array (Array)
import qualified Data.Array as Array
import Data.Foldable
import Data.Functor.Compose
import Data.Functor.Product
import Data.Functor.Reverse
import Data.Hashable
import Data.HashMap.Lazy as HashMap
import Data.IntMap as IntMap
import Data.Ix (Ix)
import Data.List.NonEmpty as NonEmpty
import Data.Map as Map
import Data.Monoid hiding (Product)
import Data.Profunctor.Unsafe
import Data.Sequence hiding ((:<), index)
import Data.Traversable
import Data.Tree
import Data.Tuple (swap)
import Data.Vector (Vector)
import qualified Data.Vector as V
import Prelude
infixr 9 <.>, <., .>
(<.) :: Indexable i p => (Indexed i s t -> r) -> ((a -> b) -> s -> t) -> p a b -> r
(<.) f g h = f . Indexed $ g . indexed h
(.>) :: (st -> r) -> (kab -> st) -> kab -> r
(.>) = (.)
selfIndex :: Indexable a p => p a fb -> a -> fb
selfIndex f a = indexed f a a
reindexed :: Indexable j p => (i -> j) -> (Indexed i a b -> r) -> p a b -> r
reindexed ij f g = f . Indexed $ indexed g . ij
(<.>) :: Indexable (i, j) p => (Indexed i s t -> r) -> (Indexed j a b -> s -> t) -> p a b -> r
f <.> g = icompose (,) f g
icompose :: Indexable p c => (i -> j -> p) -> (Indexed i s t -> r) -> (Indexed j a b -> s -> t) -> c a b -> r
icompose ijk istr jabst cab = istr . Indexed $ \i -> jabst . Indexed $ \j -> indexed cab $ ijk i j
withIndex :: (Indexable i p, Functor f) => Optical p (Indexed i) f s t (i, s) (j, t)
withIndex f = Indexed $ \i a -> snd <$> indexed f i (i, a)
asIndex :: (Indexable i p, Contravariant f, Functor f) => Optical' p (Indexed i) f s i
asIndex f = Indexed $ \i _ -> coerce (indexed f i i)
indices :: (Indexable i p, Applicative f) => (i -> Bool) -> Optical' p (Indexed i) f a a
indices p f = Indexed $ \i a -> if p i then indexed f i a else pure a
index :: (Indexable i p, Eq i, Applicative f) => i -> Optical' p (Indexed i) f a a
index j f = Indexed $ \i a -> if j == i then indexed f i a else pure a
class Functor f => FunctorWithIndex i f | f -> i where
imap :: (i -> a -> b) -> f a -> f b
#ifndef HLINT
default imap :: TraversableWithIndex i f => (i -> a -> b) -> f a -> f b
imap = iover itraversed
#endif
imapped :: IndexedSetter i (f a) (f b) a b
imapped = conjoined mapped (isets imap)
class Foldable f => FoldableWithIndex i f | f -> i where
ifoldMap :: Monoid m => (i -> a -> m) -> f a -> m
#ifndef HLINT
default ifoldMap :: (TraversableWithIndex i f, Monoid m) => (i -> a -> m) -> f a -> m
ifoldMap = ifoldMapOf itraversed
#endif
ifolded :: IndexedFold i (f a) a
ifolded = conjoined folded $ \f -> coerce . getFolding . ifoldMap (\i -> Folding #. indexed f i)
ifoldr :: (i -> a -> b -> b) -> b -> f a -> b
ifoldr f z t = appEndo (ifoldMap (\i -> Endo #. f i) t) z
ifoldl :: (i -> b -> a -> b) -> b -> f a -> b
ifoldl f z t = appEndo (getDual (ifoldMap (\i -> Dual #. Endo #. flip (f i)) t)) z
ifoldr' :: (i -> a -> b -> b) -> b -> f a -> b
ifoldr' f z0 xs = ifoldl f' id xs z0
where f' i k x z = k $! f i x z
ifoldl' :: (i -> b -> a -> b) -> b -> f a -> b
ifoldl' f z0 xs = ifoldr f' id xs z0
where f' i x k z = k $! f i z x
iany :: FoldableWithIndex i f => (i -> a -> Bool) -> f a -> Bool
iany f = getAny #. ifoldMap (\i -> Any #. f i)
iall :: FoldableWithIndex i f => (i -> a -> Bool) -> f a -> Bool
iall f = getAll #. ifoldMap (\i -> All #. f i)
inone :: FoldableWithIndex i f => (i -> a -> Bool) -> f a -> Bool
inone f = not . iany f
none :: Foldable f => (a -> Bool) -> f a -> Bool
none f = not . Data.Foldable.any f
itraverse_ :: (FoldableWithIndex i t, Applicative f) => (i -> a -> f b) -> t a -> f ()
itraverse_ f = getTraversed #. ifoldMap (\i -> Traversed #. void . f i)
ifor_ :: (FoldableWithIndex i t, Applicative f) => t a -> (i -> a -> f b) -> f ()
ifor_ = flip itraverse_
imapM_ :: (FoldableWithIndex i t, Monad m) => (i -> a -> m b) -> t a -> m ()
imapM_ f = getSequenced #. ifoldMap (\i -> Sequenced #. liftM skip . f i)
iforM_ :: (FoldableWithIndex i t, Monad m) => t a -> (i -> a -> m b) -> m ()
iforM_ = flip imapM_
iconcatMap :: FoldableWithIndex i f => (i -> a -> [b]) -> f a -> [b]
iconcatMap = ifoldMap
ifind :: FoldableWithIndex i f => (i -> a -> Bool) -> f a -> Maybe (i, a)
ifind p = ifoldr (\i a y -> if p i a then Just (i, a) else y) Nothing
ifoldrM :: (FoldableWithIndex i f, Monad m) => (i -> a -> b -> m b) -> b -> f a -> m b
ifoldrM f z0 xs = ifoldl f' return xs z0
where f' i k x z = f i x z >>= k
ifoldlM :: (FoldableWithIndex i f, Monad m) => (i -> b -> a -> m b) -> b -> f a -> m b
ifoldlM f z0 xs = ifoldr f' return xs z0
where f' i x k z = f i z x >>= k
itoList :: FoldableWithIndex i f => f a -> [(i,a)]
itoList = ifoldr (\i c -> ((i,c):)) []
class (FunctorWithIndex i t, FoldableWithIndex i t, Traversable t) => TraversableWithIndex i t | t -> i where
itraverse :: Applicative f => (i -> a -> f b) -> t a -> f (t b)
#ifndef HLINT
default itraverse :: Applicative f => (Int -> a -> f b) -> t a -> f (t b)
itraverse = traversed .# Indexed
#endif
itraversed :: IndexedTraversal i (t a) (t b) a b
itraversed = conjoined traverse (itraverse . indexed)
ifor :: (TraversableWithIndex i t, Applicative f) => t a -> (i -> a -> f b) -> f (t b)
ifor = flip itraverse
imapM :: (TraversableWithIndex i t, Monad m) => (i -> a -> m b) -> t a -> m (t b)
imapM f = unwrapMonad #. itraverse (\i -> WrapMonad #. f i)
iforM :: (TraversableWithIndex i t, Monad m) => t a -> (i -> a -> m b) -> m (t b)
iforM = flip imapM
imapAccumR :: TraversableWithIndex i t => (i -> s -> a -> (s, b)) -> s -> t a -> (s, t b)
imapAccumR f s0 a = swap (Lazy.runState (forwards (itraverse (\i c -> Backwards (Lazy.state (\s -> swap (f i s c)))) a)) s0)
imapAccumL :: TraversableWithIndex i t => (i -> s -> a -> (s, b)) -> s -> t a -> (s, t b)
imapAccumL f s0 a = swap (Lazy.runState (itraverse (\i c -> Lazy.state (\s -> swap (f i s c))) a) s0)
instance FunctorWithIndex i f => FunctorWithIndex i (Backwards f) where
imap f = Backwards . imap f . forwards
instance FoldableWithIndex i f => FoldableWithIndex i (Backwards f) where
ifoldMap f = ifoldMap f . forwards
instance TraversableWithIndex i f => TraversableWithIndex i (Backwards f) where
itraverse f = fmap Backwards . itraverse f . forwards
instance FunctorWithIndex i f => FunctorWithIndex i (Reverse f) where
imap f = Reverse . imap f . getReverse
instance FoldableWithIndex i f => FoldableWithIndex i (Reverse f) where
ifoldMap f = getDual . ifoldMap (\i -> Dual #. f i) . getReverse
instance TraversableWithIndex i f => TraversableWithIndex i (Reverse f) where
itraverse f = fmap Reverse . forwards . itraverse (\i -> Backwards . f i) . getReverse
instance FunctorWithIndex () Identity where
imap f (Identity a) = Identity (f () a)
instance FoldableWithIndex () Identity where
ifoldMap f (Identity a) = f () a
instance TraversableWithIndex () Identity where
itraverse f (Identity a) = Identity <$> f () a
instance FunctorWithIndex k ((,) k) where
imap f (k,a) = (k, f k a)
instance FoldableWithIndex k ((,) k) where
ifoldMap = uncurry
instance TraversableWithIndex k ((,) k) where
itraverse f (k, a) = (,) k <$> f k a
instance FunctorWithIndex Int []
instance FoldableWithIndex Int []
instance TraversableWithIndex Int [] where
itraverse = itraverseOf traversed
instance FunctorWithIndex Int NonEmpty
instance FoldableWithIndex Int NonEmpty
instance TraversableWithIndex Int NonEmpty where
itraverse = itraverseOf traversed
instance FunctorWithIndex () Maybe where
imap f = fmap (f ())
instance FoldableWithIndex () Maybe where
ifoldMap f = foldMap (f ())
instance TraversableWithIndex () Maybe where
itraverse f = traverse (f ())
instance FunctorWithIndex Int Seq
instance FoldableWithIndex Int Seq
instance TraversableWithIndex Int Seq where
itraverse = itraverseOf traversed
instance FunctorWithIndex Int Vector where
imap = V.imap
instance FoldableWithIndex Int Vector where
ifoldr = V.ifoldr
ifoldl = V.ifoldl . flip
ifoldr' = V.ifoldr'
ifoldl' = V.ifoldl' . flip
instance TraversableWithIndex Int Vector where
itraverse f = sequenceA . V.imap f
instance FunctorWithIndex Int IntMap
instance FoldableWithIndex Int IntMap
instance TraversableWithIndex Int IntMap where
#if MIN_VERSION_containers(0,5,0)
itraverse = IntMap.traverseWithKey
#else
itraverse f = sequenceA . IntMap.mapWithKey f
#endif
instance FunctorWithIndex k (Map k)
instance FoldableWithIndex k (Map k)
instance TraversableWithIndex k (Map k) where
#if MIN_VERSION_containers(0,5,0)
itraverse = Map.traverseWithKey
#else
itraverse f = sequenceA . Map.mapWithKey f
#endif
instance (Eq k, Hashable k) => FunctorWithIndex k (HashMap k)
instance (Eq k, Hashable k) => FoldableWithIndex k (HashMap k)
instance (Eq k, Hashable k) => TraversableWithIndex k (HashMap k) where
itraverse = HashMap.traverseWithKey
instance FunctorWithIndex r ((->) r) where
imap f g x = f x (g x)
instance FunctorWithIndex i (Level i) where
imap f = go where
go (Two n l r) = Two n (go l) (go r)
go (One i a) = One i (f i a)
go Zero = Zero
instance FoldableWithIndex i (Level i) where
ifoldMap f = go where
go (Two _ l r) = go l `mappend` go r
go (One i a) = f i a
go Zero = mempty
instance TraversableWithIndex i (Level i) where
itraverse f = go where
go (Two n l r) = Two n <$> go l <*> go r
go (One i a) = One i <$> f i a
go Zero = pure Zero
instance FunctorWithIndex i (Magma i t b) where
imap f (MagmaAp x y) = MagmaAp (imap f x) (imap f y)
imap _ (MagmaPure x) = MagmaPure x
imap f (MagmaFmap xy x) = MagmaFmap xy (imap f x)
imap f (Magma i a) = Magma i (f i a)
instance FoldableWithIndex i (Magma i t b) where
ifoldMap f (MagmaAp x y) = ifoldMap f x `mappend` ifoldMap f y
ifoldMap _ MagmaPure{} = mempty
ifoldMap f (MagmaFmap _ x) = ifoldMap f x
ifoldMap f (Magma i a) = f i a
instance TraversableWithIndex i (Magma i t b) where
itraverse f (MagmaAp x y) = MagmaAp <$> itraverse f x <*> itraverse f y
itraverse _ (MagmaPure x) = pure (MagmaPure x)
itraverse f (MagmaFmap xy x) = MagmaFmap xy <$> itraverse f x
itraverse f (Magma i a) = Magma i <$> f i a
instance FunctorWithIndex i f => FunctorWithIndex [i] (Free f) where
imap f (Pure a) = Pure $ f [] a
imap f (Free s) = Free $ imap (\i -> imap (f . (:) i)) s
instance FoldableWithIndex i f => FoldableWithIndex [i] (Free f) where
ifoldMap f (Pure a) = f [] a
ifoldMap f (Free s) = ifoldMap (\i -> ifoldMap (f . (:) i)) s
instance TraversableWithIndex i f => TraversableWithIndex [i] (Free f) where
itraverse f (Pure a) = Pure <$> f [] a
itraverse f (Free s) = Free <$> itraverse (\i -> itraverse (f . (:) i)) s
instance Ix i => FunctorWithIndex i (Array i) where
imap f arr = Array.listArray (Array.bounds arr) . fmap (uncurry f) $ Array.assocs arr
instance Ix i => FoldableWithIndex i (Array i) where
ifoldMap f = foldMap (uncurry f) . Array.assocs
instance Ix i => TraversableWithIndex i (Array i) where
itraverse f arr = Array.listArray (Array.bounds arr) <$> traverse (uncurry f) (Array.assocs arr)
instance FunctorWithIndex i f => FunctorWithIndex [i] (Cofree f) where
imap f (a :< as) = f [] a :< imap (\i -> imap (f . (:) i)) as
instance FoldableWithIndex i f => FoldableWithIndex [i] (Cofree f) where
ifoldMap f (a :< as) = f [] a `mappend` ifoldMap (\i -> ifoldMap (f . (:) i)) as
instance TraversableWithIndex i f => TraversableWithIndex [i] (Cofree f) where
itraverse f (a :< as) = (:<) <$> f [] a <*> itraverse (\i -> itraverse (f . (:) i)) as
instance (FunctorWithIndex i f, FunctorWithIndex j g) => FunctorWithIndex (i, j) (Compose f g) where
imap f (Compose fg) = Compose $ imap (\k -> imap (f . (,) k)) fg
instance (FoldableWithIndex i f, FoldableWithIndex j g) => FoldableWithIndex (i, j) (Compose f g) where
ifoldMap f (Compose fg) = ifoldMap (\k -> ifoldMap (f . (,) k)) fg
instance (TraversableWithIndex i f, TraversableWithIndex j g) => TraversableWithIndex (i, j) (Compose f g) where
itraverse f (Compose fg) = Compose <$> itraverse (\k -> itraverse (f . (,) k)) fg
instance FunctorWithIndex i m => FunctorWithIndex i (IdentityT m) where
imap f (IdentityT m) = IdentityT $ imap f m
instance FoldableWithIndex i m => FoldableWithIndex i (IdentityT m) where
ifoldMap f (IdentityT m) = ifoldMap f m
instance TraversableWithIndex i m => TraversableWithIndex i (IdentityT m) where
itraverse f (IdentityT m) = IdentityT <$> itraverse f m
instance (FunctorWithIndex i f, FunctorWithIndex j g) => FunctorWithIndex (Either i j) (Product f g) where
imap f (Pair a b) = Pair (imap (f . Left) a) (imap (f . Right) b)
instance (FoldableWithIndex i f, FoldableWithIndex j g) => FoldableWithIndex (Either i j) (Product f g) where
ifoldMap f (Pair a b) = ifoldMap (f . Left) a `mappend` ifoldMap (f . Right) b
instance (TraversableWithIndex i f, TraversableWithIndex j g) => TraversableWithIndex (Either i j) (Product f g) where
itraverse f (Pair a b) = Pair <$> itraverse (f . Left) a <*> itraverse (f . Right) b
instance FunctorWithIndex i m => FunctorWithIndex (e, i) (ReaderT e m) where
imap f (ReaderT m) = ReaderT $ \k -> imap (f . (,) k) (m k)
instance FunctorWithIndex i w => FunctorWithIndex (s, i) (TracedT s w) where
imap f (TracedT w) = TracedT $ imap (\k' g k -> f (k, k') (g k)) w
instance FunctorWithIndex [Int] Tree where
imap f (Node a as) = Node (f [] a) $ imap (\i -> imap (f . (:) i)) as
instance FoldableWithIndex [Int] Tree where
ifoldMap f (Node a as) = f [] a `mappend` ifoldMap (\i -> ifoldMap (f . (:) i)) as
instance TraversableWithIndex [Int] Tree where
itraverse f (Node a as) = Node <$> f [] a <*> itraverse (\i -> itraverse (f . (:) i)) as
skip :: a -> ()
skip _ = ()
ifoldMapBy :: FoldableWithIndex i t => (r -> r -> r) -> r -> (i -> a -> r) -> t a -> r
ifoldMapBy f z g = reifyFold f z (ifoldMap (\i a -> M (g i a)))
ifoldMapByOf :: (forall s. IndexedGetting i (M r s) t a) -> (r -> r -> r) -> r -> (i -> a -> r) -> t -> r
ifoldMapByOf l f z g = reifyFold f z (ifoldMapOf l (\i a -> M (g i a)))