{-# LANGUAGE CPP #-}{-# LANGUAGE GADTs #-}{-# LANGUAGE Rank2Types #-}{-# LANGUAGE FlexibleContexts #-}{-# LANGUAGE FlexibleInstances #-}{-# LANGUAGE UndecidableInstances #-}{-# LANGUAGE MultiParamTypeClasses #-}{-# LANGUAGE FunctionalDependencies #-}#ifdef DEFAULT_SIGNATURES{-# LANGUAGE DefaultSignatures #-}#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706#define MPTC_DEFAULTS#endif#endif#ifdef TRUSTWORTHY{-# LANGUAGE Trustworthy #-}-- vector, hashable#endif#ifndef MIN_VERSION_containers#define MIN_VERSION_containers(x,y,z) 1#endif--------------------------------------------------------------------------------- |-- Module : Control.Lens.Indexed-- Copyright : (C) 2012-13 Edward Kmett-- License : BSD-style (see the file LICENSE)-- Maintainer : Edward Kmett <ekmett@gmail.com>-- Stability : provisional-- Portability : Rank2Types---- (The classes in here need to be defined together for @DefaultSignatures@ to work.)-------------------------------------------------------------------------------moduleControl.Lens.Indexed(-- * IndexingIndexable(..),Conjoined(..),Indexed(..),(<.),(<.>),(.>),reindexed,icompose,indexing,indexing64-- * Indexed Functors,FunctorWithIndex(..)-- * Indexed Foldables,FoldableWithIndex(..),ifolding-- ** Indexed Foldable Combinators,iany,iall,itraverse_,ifor_,imapM_,iforM_,iconcatMap,ifind,ifoldrM,ifoldlM,itoList-- * Converting to Folds,withIndex,asIndex-- * Restricting by Index,indices,index-- * Indexed Traversables,TraversableWithIndex(..)-- * Indexed Traversable Combinators,ifor,imapM,iforM,imapAccumR,imapAccumL)whereimportControl.ApplicativeimportControl.Applicative.BackwardsimportControl.Monad(void,liftM)importControl.Monad.Trans.State.LazyasLazyimportControl.Lens.FoldimportControl.Lens.Internal.FoldimportControl.Lens.Internal.GetterimportControl.Lens.Internal.IndexedimportControl.Lens.Internal.LevelimportControl.Lens.Internal.MagmaimportControl.Lens.SetterimportControl.Lens.TraversalimportControl.Lens.TypeimportData.FoldableimportData.Functor.IdentityimportData.Functor.ReverseimportData.HashableimportData.HashMap.LazyasHashMapimportData.IntMapasIntMapimportData.MapasMapimportData.MonoidimportData.Profunctor.UnsafeimportData.Sequencehiding(index)importData.TraversableimportData.Tuple(swap)importData.Vector(Vector)importqualifiedData.VectorasVinfixr9<.>,<.,.>-- $setup-- >>> :set -XNoOverloadedStrings-- >>> import Control.Lens-- | Compose an 'Indexed' function with a non-indexed function.---- Mnemonically, the @<@ points to the indexing we want to preserve.(<.)::Indexableip=>(Indexedist->r)->((a->b)->s->t)->pab->r(<.)fgh=f.Indexed$g.indexedh{-# INLINE (<.) #-}-- | Compose a non-indexed function with an 'Indexed' function.---- Mnemonically, the @>@ points to the indexing we want to preserve.---- This is the same as @('.')@. ---- @f '.' g@ (and @f '.>' g@) gives you the index of @g@ unless @g@ is index-preserving, like a-- 'Prism', 'Iso' or 'Equality', in which case it'll pass through the index of @f@.(.>)::(st->r)->(kab->st)->kab->r(.>)=(.){-# INLINE (.>) #-}-- | Remap the index.reindexed::Indexablejp=>(i->j)->(Indexediab->r)->pab->rreindexedijfg=f.Indexed$indexedg.ij{-# INLINE reindexed #-}-- | Composition of 'Indexed' functions.---- Mnemonically, the @\<@ and @\>@ points to the fact that we want to preserve the indices.(<.>)::Indexable(i,j)p=>(Indexedist->r)->(Indexedjab->s->t)->pab->rf<.>g=icompose(,)fg{-# INLINE (<.>) #-}-- | Composition of 'Indexed' functions with a user supplied function for combining indices.icompose::Indexablepc=>(i->j->p)->(Indexedist->r)->(Indexedjab->s->t)->cab->ricomposeijkistrjabstcab=istr.Indexed$\i->jabst.Indexed$\j->indexedcab$ijkij{-# INLINE icompose #-}--------------------------------------------------------------------------------- Converting to Folds--------------------------------------------------------------------------------- | Fold a container with indices returning both the indices and the values.---- The result is only valid to compose in a 'Traversal', if you don't edit the-- index as edits to the index have no effect.withIndex::(Indexableip,Functorf)=>Overloadingp(Indexedi)fst(i,s)(j,t)withIndexf=Indexed$\ia->snd<$>indexedfi(i,a){-# INLINE withIndex #-}-- | When composed with an 'IndexedFold' or 'IndexedTraversal' this yields an-- ('Indexed') 'Fold' of the indices.asIndex::(Indexableip,Functorf,Gettablef)=>Overloading'p(Indexedi)fsiasIndexf=Indexed$\i_->coerce(indexedfii){-# INLINE asIndex #-}--------------------------------------------------------------------------------- Restricting by index--------------------------------------------------------------------------------- | This allows you to filter an 'IndexedFold', 'IndexedGetter', 'IndexedTraversal' or 'IndexedLens' based on a predicate-- on the indices.---- >>> ["hello","the","world","!!!"]^..traversed.indices even-- ["hello","world"]---- >>> over (traversed.indices (>0)) Prelude.reverse $ ["He","was","stressed","o_O"]-- ["He","saw","desserts","O_o"]indices::(Indexableip,Applicativef)=>(i->Bool)->Overloading'p(Indexedi)faaindicespf=Indexed$\ia->ifpithenindexedfiaelsepurea{-# INLINE indices #-}-- | This allows you to filter an 'IndexedFold', 'IndexedGetter', 'IndexedTraversal' or 'IndexedLens' based on an index.---- >>> ["hello","the","world","!!!"]^?traversed.index 2-- Just "world"index::(Indexableip,Eqi,Applicativef)=>i->Overloading'p(Indexedi)faaindexjf=Indexed$\ia->ifj==ithenindexedfiaelsepurea{-# INLINE index #-}--------------------------------------------------------------------------------- FunctorWithIndex--------------------------------------------------------------------------------- | A 'Functor' with an additional index.---- Instances must satisfy a modified form of the 'Functor' laws:---- @-- 'imap' f '.' 'imap' g ≡ 'imap' (\\i -> f i '.' g i)-- 'imap' (\\_ a -> a) ≡ 'id'-- @classFunctorf=>FunctorWithIndexif|f->iwhere-- | Map with access to the index.imap::(i->a->b)->fa->fb#ifdef MPTC_DEFAULTSdefaultimap::TraversableWithIndexif=>(i->a->b)->fa->fbimap=ioveritraversed{-# INLINE imap #-}#endif-- | The 'IndexedSetter' for a 'FunctorWithIndex'.---- If you don't need access to the index, then 'mapped' is more flexible in what it accepts.imapped::FunctorWithIndexif=>IndexedSetteri(fa)(fb)abimapped=conjoinedmapped(isetsimap){-# INLINE imapped #-}--------------------------------------------------------------------------------- FoldableWithIndex--------------------------------------------------------------------------------- | A container that supports folding with an additional index.classFoldablef=>FoldableWithIndexif|f->iwhere---- | Fold a container by mapping value to an arbitrary 'Monoid' with access to the index @i@.---- When you don't need access to the index then 'foldMap' is more flexible in what it accepts.---- @-- 'foldMap' ≡ 'ifoldMap' '.' 'const'-- @ifoldMap::Monoidm=>(i->a->m)->fa->m#ifdef MPTC_DEFAULTSdefaultifoldMap::(TraversableWithIndexif,Monoidm)=>(i->a->m)->fa->mifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}#endif-- | The 'IndexedFold' of a 'FoldableWithIndex' container.ifolded::IndexedFoldi(fa)aifolded=conjoinedfolded$\f->coerce.getFolding.ifoldMap(\i->Folding#.indexedfi){-# INLINE ifolded #-}-- | Right-associative fold of an indexed container with access to the index @i@.---- When you don't need access to the index then 'Data.Foldable.foldr' is more flexible in what it accepts.---- @-- 'Data.Foldable.foldr' ≡ 'ifoldr' '.' 'const'-- @ifoldr::(i->a->b->b)->b->fa->bifoldrfzt=appEndo(ifoldMap(\i->Endo#.fi)t)z-- | Left-associative fold of an indexed container with access to the index @i@.---- When you don't need access to the index then 'Data.Foldable.foldl' is more flexible in what it accepts.---- @-- 'Data.Foldable.foldl' ≡ 'ifoldl' '.' 'const'-- @ifoldl::(i->b->a->b)->b->fa->bifoldlfzt=appEndo(getDual(ifoldMap(\i->Dual#.Endo#.flip(fi))t))z-- | /Strictly/ fold right over the elements of a structure with access to the index @i@.---- When you don't need access to the index then 'foldr'' is more flexible in what it accepts.---- @-- 'foldr'' ≡ 'ifoldr'' '.' 'const'-- @ifoldr'::(i->a->b->b)->b->fa->bifoldr'fz0xs=ifoldlf'idxsz0wheref'ikxz=k$!fixz-- | Fold over the elements of a structure with an index, associating to the left, but /strictly/.---- When you don't need access to the index then 'Control.Lens.Fold.foldlOf'' is more flexible in what it accepts.---- @-- 'Control.Lens.Fold.foldlOf'' l ≡ 'ifoldlOf'' l '.' 'const'-- @ifoldl'::(i->b->a->b)->b->fa->bifoldl'fz0xs=ifoldrf'idxsz0wheref'ixkz=k$!fizx-- | 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'.ifolding::FoldableWithIndexif=>(s->fa)->IndexedFoldisaifoldingsfaiagb=coerce.itraverse_(indexediagb).sfa{-# INLINE ifolding #-}-- | Return whether or not any element in a container satisfies a predicate, with access to the index @i@.---- When you don't need access to the index then 'any' is more flexible in what it accepts.---- @-- 'any' ≡ 'iany' '.' 'const'-- @iany::FoldableWithIndexif=>(i->a->Bool)->fa->Boolianyf=getAny#.ifoldMap(\i->Any#.fi){-# INLINE iany #-}-- | Return whether or not all elements in a container satisfy a predicate, with access to the index @i@.---- When you don't need access to the index then 'all' is more flexible in what it accepts.---- @-- 'all' ≡ 'iall' '.' 'const'-- @iall::FoldableWithIndexif=>(i->a->Bool)->fa->Booliallf=getAll#.ifoldMap(\i->All#.fi){-# INLINE iall #-}-- | Traverse elements with access to the index @i@, discarding the results.---- When you don't need access to the index then 'traverse_' is more flexible in what it accepts.---- @-- 'traverse_' l = 'itraverse' '.' 'const'-- @itraverse_::(FoldableWithIndexit,Applicativef)=>(i->a->fb)->ta->f()itraverse_f=getTraversed#.ifoldMap(\i->Traversed#.void.fi){-# INLINE itraverse_ #-}-- | Traverse elements with access to the index @i@, discarding the results (with the arguments flipped).---- @-- 'ifor_' ≡ 'flip' 'itraverse_'-- @---- When you don't need access to the index then 'for_' is more flexible in what it accepts.---- @-- 'for_' a ≡ 'ifor_' a '.' 'const'-- @ifor_::(FoldableWithIndexit,Applicativef)=>ta->(i->a->fb)->f()ifor_=flipitraverse_{-# INLINE ifor_ #-}-- | Run monadic actions for each target of an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal' with access to the index,-- discarding the results.---- When you don't need access to the index then 'Control.Lens.Fold.mapMOf_' is more flexible in what it accepts.---- @-- 'mapM_' ≡ 'imapM' '.' 'const'-- @imapM_::(FoldableWithIndexit,Monadm)=>(i->a->mb)->ta->m()imapM_f=getSequenced#.ifoldMap(\i->Sequenced#.liftMskip.fi){-# INLINE imapM_ #-}-- | Run monadic actions for each target of an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal' with access to the index,-- discarding the results (with the arguments flipped).---- @-- 'iforM_' ≡ 'flip' 'imapM_'-- @---- When you don't need access to the index then 'Control.Lens.Fold.forMOf_' is more flexible in what it accepts.---- @-- 'Control.Lens.Fold.forMOf_' l a ≡ 'iforMOf' l a '.' 'const'-- @iforM_::(FoldableWithIndexit,Monadm)=>ta->(i->a->mb)->m()iforM_=flipimapM_{-# INLINE iforM_ #-}-- | Concatenate the results of a function of the elements of an indexed container with access to the index.---- When you don't need access to the index then 'concatMap' is more flexible in what it accepts.---- @-- 'concatMap' ≡ 'iconcatMap' '.' 'const'-- 'iconcatMap' ≡ 'ifoldMap'-- @iconcatMap::FoldableWithIndexif=>(i->a->[b])->fa->[b]iconcatMap=ifoldMap{-# INLINE iconcatMap #-}-- | Searches a container with a predicate that is also supplied the index, returning 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 'find' is more flexible in what it accepts.---- @-- 'find' ≡ 'ifind' '.' 'const'-- @ifind::FoldableWithIndexif=>(i->a->Bool)->fa->Maybe(i,a)ifindp=ifoldr(\iay->ifpiathenJust(i,a)elsey)Nothing{-# INLINE ifind #-}-- | Monadic fold right over the elements of a structure with an index.---- When you don't need access to the index then 'foldrM' is more flexible in what it accepts.---- @-- 'foldrM' ≡ 'ifoldrM' '.' 'const'-- @ifoldrM::(FoldableWithIndexif,Monadm)=>(i->a->b->mb)->b->fa->mbifoldrMfz0xs=ifoldlf'returnxsz0wheref'ikxz=fixz>>=k{-# INLINE ifoldrM #-}-- | Monadic fold over the elements of a structure with an index, associating to the left.---- When you don't need access to the index then 'foldlM' is more flexible in what it accepts.---- @-- 'foldlM' ≡ 'ifoldlM' '.' 'const'-- @ifoldlM::(FoldableWithIndexif,Monadm)=>(i->b->a->mb)->b->fa->mbifoldlMfz0xs=ifoldrf'returnxsz0wheref'ixkz=fizx>>=k{-# INLINE ifoldlM #-}-- | Extract the key-value pairs from a structure.---- When you don't need access to the indices in the result, then 'Data.Foldable.toList' is more flexible in what it accepts.---- @-- 'Data.Foldable.toList' ≡ 'Data.List.map' 'fst' '.' 'itoList'-- @itoList::FoldableWithIndexif=>fa->[(i,a)]itoList=ifoldr(\ic->((i,c):))[]{-# INLINE itoList #-}--------------------------------------------------------------------------------- TraversableWithIndex--------------------------------------------------------------------------------- | A 'Traversable' with an additional index.---- An instance must satisfy a (modified) form of the 'Traversable' laws:---- @-- 'itraverse' ('const' 'Identity') ≡ 'Identity'-- 'fmap' ('itraverse' f) '.' 'itraverse' g ≡ 'Data.Functor.Compose.getCompose' '.' 'itraverse' (\\i -> 'Data.Functor.Compose.Compose' '.' 'fmap' (f i) '.' g i)-- @class(FunctorWithIndexit,FoldableWithIndexit,Traversablet)=>TraversableWithIndexit|t->iwhere-- | Traverse an indexed container.itraverse::Applicativef=>(i->a->fb)->ta->f(tb)#ifdef MPTC_DEFAULTSdefaultitraverse::Applicativef=>(Int->a->fb)->ta->f(tb)itraverse=traversed.#Indexed{-# INLINE itraverse #-}#endif-- | The 'IndexedTraversal' of a 'TraversableWithIndex' container.itraversed::IndexedTraversali(ta)(tb)abitraversed=conjoinedtraverse(itraverse.indexed){-# INLINE itraversed #-}-- | Traverse with an index (and the arguments flipped).---- @-- 'for' a ≡ 'ifor' a '.' 'const'-- 'ifor' ≡ 'flip' 'itraverse'-- @ifor::(TraversableWithIndexit,Applicativef)=>ta->(i->a->fb)->f(tb)ifor=flipitraverse{-# INLINE ifor #-}-- | Map each element of a structure to a monadic action,-- evaluate these actions from left to right, and collect the results, with access-- the index.---- When you don't need access to the index 'mapM' is more liberal in what it can accept.---- @-- 'mapM' ≡ 'imapM' '.' 'const'-- @imapM::(TraversableWithIndexit,Monadm)=>(i->a->mb)->ta->m(tb)imapMf=unwrapMonad#.itraverse(\i->WrapMonad#.fi){-# INLINE imapM #-}-- | Map each element of a structure to a monadic action,-- evaluate these actions from left to right, and collect the results, with access-- its position (and the arguments flipped).---- @-- 'forM' a ≡ 'iforM' a '.' 'const'-- 'iforM' ≡ 'flip' 'imapM'-- @iforM::(TraversableWithIndexit,Monadm)=>ta->(i->a->mb)->m(tb)iforM=flipimapM{-# INLINE iforM #-}-- | Generalizes 'Data.Traversable.mapAccumR' to add access to the index.---- 'imapAccumROf' accumulates state from right to left.---- @-- 'Control.Lens.Traversal.mapAccumR' ≡ 'imapAccumR' '.' 'const'-- @imapAccumR::TraversableWithIndexit=>(i->s->a->(s,b))->s->ta->(s,tb)imapAccumRfs0a=swap(Lazy.runState(forwards(itraverse(\ic->Backwards(Lazy.state(\s->swap(fisc))))a))s0){-# INLINE imapAccumR #-}-- | Generalizes 'Data.Traversable.mapAccumL' to add access to the index.---- 'imapAccumLOf' accumulates state from left to right.---- @-- 'Control.Lens.Traversal.mapAccumLOf' ≡ 'imapAccumL' '.' 'const'-- @imapAccumL::TraversableWithIndexit=>(i->s->a->(s,b))->s->ta->(s,tb)imapAccumLfs0a=swap(Lazy.runState(itraverse(\ic->Lazy.state(\s->swap(fisc)))a)s0){-# INLINE imapAccumL #-}--------------------------------------------------------------------------------- Instances-------------------------------------------------------------------------------instanceFunctorWithIndexif=>FunctorWithIndexi(Backwardsf)whereimapf=Backwards.imapf.forwardsinstanceFoldableWithIndexif=>FoldableWithIndexi(Backwardsf)whereifoldMapf=ifoldMapf.forwardsinstanceTraversableWithIndexif=>TraversableWithIndexi(Backwardsf)whereitraversef=fmapBackwards.itraversef.forwardsinstanceFunctorWithIndexif=>FunctorWithIndexi(Reversef)whereimapf=Reverse.imapf.getReverseinstanceFoldableWithIndexif=>FoldableWithIndexi(Reversef)whereifoldMapf=getDual.ifoldMap(\i->Dual#.fi).getReverseinstanceTraversableWithIndexif=>TraversableWithIndexi(Reversef)whereitraversef=fmapReverse.forwards.itraverse(\i->Backwards.fi).getReverseinstanceFunctorWithIndex()Identitywhereimapf(Identitya)=Identity(f()a)instanceFoldableWithIndex()IdentitywhereifoldMapf(Identitya)=f()ainstanceTraversableWithIndex()Identitywhereitraversef(Identitya)=Identity<$>f()ainstanceFunctorWithIndexk((,)k)whereimapf(k,a)=(k,fka){-# INLINE imap #-}instanceFoldableWithIndexk((,)k)whereifoldMap=uncurry{-# INLINE ifoldMap #-}instanceTraversableWithIndexk((,)k)whereitraversef(k,a)=(,)k<$>fka{-# INLINE itraverse #-}-- | The position in the list is available as the index.instanceFunctorWithIndexInt[]whereimap=ioveritraversed{-# INLINE imap #-}instanceFoldableWithIndexInt[]whereifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}instanceTraversableWithIndexInt[]whereitraverse=itraverseOftraversed{-# INLINE itraverse #-}-- | The position in the 'Seq' is available as the index.instanceFunctorWithIndexIntSeqwhereimap=ioveritraversed{-# INLINE imap #-}instanceFoldableWithIndexIntSeqwhereifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}instanceTraversableWithIndexIntSeqwhereitraverse=itraverseOftraversed{-# INLINE itraverse #-}instanceFunctorWithIndexIntVectorwhereimap=V.imap{-# INLINE imap #-}instanceFoldableWithIndexIntVectorwhereifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}ifoldr=V.ifoldrifoldl=V.ifoldl.flipifoldr'=V.ifoldr'ifoldl'=V.ifoldl'.flipinstanceTraversableWithIndexIntVectorwhereitraversef=sequenceA.V.imapf{-# INLINE itraverse #-}instanceFunctorWithIndexIntIntMapwhereimap=ioveritraversed{-# INLINE imap #-}instanceFoldableWithIndexIntIntMapwhereifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}instanceTraversableWithIndexIntIntMapwhere#if MIN_VERSION_containers(0,5,0)itraverse=IntMap.traverseWithKey#elseitraversef=sequenceA.IntMap.mapWithKeyf#endif{-# INLINE itraverse #-}instanceFunctorWithIndexk(Mapk)whereimap=ioveritraversed{-# INLINE imap #-}instanceFoldableWithIndexk(Mapk)whereifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}instanceTraversableWithIndexk(Mapk)where#if MIN_VERSION_containers(0,5,0)itraverse=Map.traverseWithKey#elseitraversef=sequenceA.Map.mapWithKeyf#endif{-# INLINE itraverse #-}instance(Eqk,Hashablek)=>FunctorWithIndexk(HashMapk)whereimap=ioveritraversed{-# INLINE imap #-}instance(Eqk,Hashablek)=>FoldableWithIndexk(HashMapk)whereifoldMap=ifoldMapOfitraversed{-# INLINE ifoldMap #-}instance(Eqk,Hashablek)=>TraversableWithIndexk(HashMapk)whereitraverse=HashMap.traverseWithKey{-# INLINE itraverse #-}instanceFunctorWithIndexr((->)r)whereimapfgx=fx(gx){-# INLINE imap #-}instanceFunctorWithIndexi(Leveli)whereimapf=gowherego(Twonlr)=Twon(gol)(gor)go(Oneia)=Onei(fia)goZero=Zero{-# INLINE imap #-}instanceFoldableWithIndexi(Leveli)whereifoldMapf=gowherego(Two_lr)=gol`mappend`gorgo(Oneia)=fiagoZero=mempty{-# INLINE ifoldMap #-}instanceTraversableWithIndexi(Leveli)whereitraversef=gowherego(Twonlr)=Twon<$>gol<*>gorgo(Oneia)=Onei<$>fiagoZero=pureZero{-# INLINE itraverse #-}instanceFunctorWithIndexi(Magmaitb)whereimapf(MagmaApxy)=MagmaAp(imapfx)(imapfy)imap_(MagmaPurex)=MagmaPureximapf(MagmaFmapxyx)=MagmaFmapxy(imapfx)imapf(Magmaia)=Magmai(fia){-# INLINE imap #-}instanceFoldableWithIndexi(Magmaitb)whereifoldMapf(MagmaApxy)=ifoldMapfx`mappend`ifoldMapfyifoldMap_MagmaPure{}=memptyifoldMapf(MagmaFmap_x)=ifoldMapfxifoldMapf(Magmaia)=fia{-# INLINE ifoldMap #-}instanceTraversableWithIndexi(Magmaitb)whereitraversef(MagmaApxy)=MagmaAp<$>itraversefx<*>itraversefyitraverse_(MagmaPurex)=pure(MagmaPurex)itraversef(MagmaFmapxyx)=MagmaFmapxy<$>itraversefxitraversef(Magmaia)=Magmai<$>fia{-# INLINE itraverse #-}--------------------------------------------------------------------------------- Misc.-------------------------------------------------------------------------------skip::a->()skip_=(){-# INLINE skip #-}