-- | Uniplate-style traversals.{-# LANGUAGE CPP #-}moduleData.Generics.Fixplate.Traversalswhere--------------------------------------------------------------------------------importControl.Monad(liftM)importData.FoldableimportData.TraversableimportPreludehiding(foldl,foldr,mapM,mapM_,concat,concatMap)importData.Generics.Fixplate.BaseimportData.Generics.Fixplate.Open--import Data.Generics.Fixplate.Misc#ifdef WITH_QUICKCHECKimportTest.QuickCheckimportData.Generics.Fixplate.Test.Tools#endif---------------------------------------------------------------------------------- * Queries-- | The list of direct descendants.children::Foldablef=>Muf->[Muf]children=foldr(:)[].unFix-- | The list of all substructures. Together with list-comprehension syntax-- this is a powerful query tool. For example the following is how you get-- the list of all variable names in an expression:---- > variables expr = [ s | Fix (Var s) <- universe expr ]--universe::Foldablef=>Muf->[Muf]universex=x:concatMapuniverse(childrenx)---------------------------------------------------------------------------------- * Traversals-- | Bottom-up transformation.transform::Functorf=>(Muf->Muf)->Muf->Muftransformh=gowherego=h.Fix.fmapgo.unFixtransformM::(Traversablef,Monadm)=>(Muf->m(Muf))->Muf->m(Muf)transformMaction=gowherego(Fixx)=doy<-mapMgoxaction(Fixy)-- | Top-down transformation. This provided only for completeness;-- usually, it is 'transform' what you want use instead.topDownTransform::Functorf=>(Muf->Muf)->Muf->MuftopDownTransformh=gowherego=Fix.fmapgo.unFix.htopDownTransformM::(Traversablef,Monadm)=>(Muf->m(Muf))->Muf->m(Muf)topDownTransformMh=gowheregox=doFixy<-hxliftMFix(mapMgoy)-- | Non-recursive top-down transformation.descend::Functorf=>(Muf->Muf)->Muf->Mufdescendh=Fix.fmaph.unFixdescendM::(Traversablef,Monadm)=>(Muf->m(Muf))->Muf->m(Muf)descendMaction=liftMFix.mapMaction.unFix-- | Bottom-up transformation until a normal form is reached.rewrite::Functorf=>(Muf->Maybe(Muf))->Muf->Mufrewriteh=transformgwheregx=maybex(rewriteh)(hx)rewriteM::(Traversablef,Monadm)=>(Muf->m(Maybe(Muf)))->Muf->m(Muf)rewriteMh=transformMgwheregx=hx>>=\y->maybe(returnx)(rewriteMh)y---------------------------------------------------------------------------------- * Context-- | We /annotate/ the nodes of the tree with functions which replace that-- particular subtree.context::Traversablef=>Muf->Attrf(Muf->Muf)context=goidwheregoh=Fix.Annh.fmapg.holes.unFixwhereg(y,replace)=go(h.Fix.replace)ywhere-- | Flattened version of 'context'.contextList::Traversablef=>Muf->[(Muf,Muf->Muf)]contextList=maph.universe.contextwherehthis@(Fix(Anngx))=(forgetthis,g)---------------------------------------------------------------------------------- * Folds-- | (Strict) left fold. Since @Mu f@ is not a functor, but a data type, we cannot make-- it an instance of the @Foldable@ type class.foldLeft::Foldablef=>(a->Muf->a)->a->Muf->a#ifdef __GLASGOW_HASKELL__foldLefthx0t=gox0twherego!x!t=foldlgo(hxt)(unFixt)#else foldLefthx0t=gox0twheregoxt=x`seq`t`seq`foldlgo(hxt)(unFixt)#endiffoldLeftLazy::Foldablef=>(a->Muf->a)->a->Muf->afoldLeftLazyhx0t=gox0twheregoxt=foldlgo(hxt)$unFixtfoldRight::Foldablef=>(Muf->a->a)->a->Muf->afoldRighthx0t=gotx0wheregotx=ht$foldrgox$unFixt--------------------------------------------------------------------------------#ifdef WITH_QUICKCHECK-- * TestsuniverseNaive::Foldablef=>Muf->[Muf]universeNaivex=x:concatMapuniverseNaive(childrenx)runtests_Traversals::IO()runtests_Traversals=doquickCheckprop_leftFoldquickCheckprop_leftFoldLazyquickCheckprop_rightFoldquickCheckprop_universe1quickCheckprop_universe2prop_universe1::FixTLabel->Boolprop_universe1tree=universetree==universeNaivetreeprop_universe2::FixTLabel->Boolprop_universe2tree=universetree==foldRight(:)[]treeprop_leftFold::FixTLabel->Boolprop_leftFoldtree=foldLeft(\xs(Fix(TreeFls))->(l:xs))[]tree==foldl(flip(:))[](fromFixTtree)prop_leftFoldLazy::FixTLabel->Boolprop_leftFoldLazytree=foldLeftLazy(\xs(Fix(TreeFls))->(l:xs))[]tree==foldl(flip(:))[](fromFixTtree)prop_rightFold::FixTLabel->Boolprop_rightFoldtree=foldRight(\(Fix(TreeFls))xs->(l:xs))[]tree==foldr(:)[](fromFixTtree)#endif--------------------------------------------------------------------------------