module Data.Generics.Fixplate.Traversals where
import Control.Monad (liftM)
import Data.Foldable
import Data.Traversable
import Prelude hiding (foldl,foldr,mapM,mapM_,concat,concatMap)
import Data.Generics.Fixplate.Base
import Data.Generics.Fixplate.Open
children :: Foldable f => Mu f -> [Mu f]
children = foldr (:) [] . unFix
universe :: Foldable f => Mu f -> [Mu f]
universe x = x : concatMap universe (children x)
transform :: Functor f => (Mu f -> Mu f) -> Mu f -> Mu f
transform h = go where
go = h . Fix . fmap go . unFix
transformM :: (Traversable f, Monad m)
=> (Mu f -> m (Mu f)) -> Mu f -> m (Mu f)
transformM action = go where
go (Fix x) = do
y <- mapM go x
action (Fix y)
topDownTransform :: Functor f => (Mu f -> Mu f) -> Mu f -> Mu f
topDownTransform h = go where
go = Fix . fmap go . unFix . h
topDownTransformM :: (Traversable f, Monad m) => (Mu f -> m (Mu f)) -> Mu f -> m (Mu f)
topDownTransformM h = go where
go x = do
Fix y <- h x
liftM Fix (mapM go y)
descend :: Functor f => (Mu f -> Mu f) -> Mu f -> Mu f
descend h = Fix . fmap h . unFix
descendM :: (Traversable f, Monad m) => (Mu f -> m (Mu f)) -> Mu f -> m (Mu f)
descendM action = liftM Fix . mapM action . unFix
rewrite :: Functor f => (Mu f -> Maybe (Mu f)) -> Mu f -> Mu f
rewrite h = transform g where
g x = maybe x (rewrite h) (h x)
rewriteM :: (Traversable f, Monad m) => (Mu f -> m (Maybe (Mu f))) -> Mu f -> m (Mu f)
rewriteM h = transformM g where
g x = h x >>= \y -> maybe (return x) (rewriteM h) y
restructure :: Functor f => (f (Mu g) -> g (Mu g)) -> Mu f -> Mu g
restructure h = go where
go = Fix . h . fmap go . unFix
restructureM :: (Traversable f, Monad m) => (f (Mu g) -> m (g (Mu g))) -> Mu f -> m (Mu g)
restructureM action = go where
go (Fix x) = do
y <- mapM go x
liftM Fix (action y)
context :: Traversable f => Mu f -> Attr f (Mu f -> Mu f)
context = go id where
go h = Fix . Ann h . fmap g . holes . unFix where
g (y,replace) = go (h . Fix . replace) y where
contextList :: Traversable f => Mu f -> [(Mu f, Mu f -> Mu f)]
contextList = map h . universe . context where
h this@(Fix (Ann g x)) = (forget this, g)
foldLeft :: Foldable f => (a -> Mu f -> a) -> a -> Mu f -> a
#ifdef __GLASGOW_HASKELL__
foldLeft h x0 t = go x0 t where
go !x !t = foldl go (h x t) (unFix t)
#else
foldLeft h x0 t = go x0 t where
go x t = x `seq` t `seq` foldl go (h x t) (unFix t)
#endif
foldLeftLazy :: Foldable f => (a -> Mu f -> a) -> a -> Mu f -> a
foldLeftLazy h x0 t = go x0 t where
go x t = foldl go (h x t) $ unFix t
foldRight :: Foldable f => (Mu f -> a -> a) -> a -> Mu f -> a
foldRight h x0 t = go t x0 where
go t x = h t $ foldr go x $ unFix t