packages feed

LslPlus-0.3.2: src/Data/Generics/Extras/Schemes.hs

{-# LANGUAGE Rank2Types #-}
module Data.Generics.Extras.Schemes (
    downup,
    downupSkipping,
    everythingTwice,
    everythingButTwice,
    everythingBut,
    everywhereButM
 ) where

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

import Data.Data
import Data.Generics.Aliases
import Control.Monad

everythingButTwice :: GenericQ Bool -> (r -> r -> r) -> r -> GenericQ r -> GenericQ r -> GenericQ r
everythingButTwice q k def f g x | q x = def
                                 | otherwise = (foldl k (f x) (gmapQ (everythingButTwice q k def f g) x) `k` (g x))

everythingTwice :: (r -> r -> r) -> GenericQ r -> GenericQ r -> GenericQ r
everythingTwice k f g x
  = foldl k (f x) (gmapQ (everythingTwice k f g) x) `k` (g x)


downup :: Monad m => GenericM m -> GenericM m -> GenericM m

downup down up x = do x' <- down x
                      x'' <- gmapM (downup down up) x'
                      up x''

downupSkipping :: Monad m => GenericQ Bool -> GenericM m -> GenericM m -> GenericM m
downupSkipping skip down up x | skip x = return x
                              | otherwise = do x' <- down x
                                               x'' <- gmapM (downupSkipping skip down up) x'
                                               up x''
                                               
-- | Monadic variation on everywhere
everywhereButM :: Monad m => GenericQ Bool -> GenericM m -> GenericM m

-- Bottom-up order is also reflected in order of do-actions
everywhereButM p f x | p x = return x
                     | otherwise = do x' <- gmapM (everywhereButM p f) x
                                      f x'

everythingBut :: GenericQ Bool -> (r -> r -> r) -> r -> GenericQ r -> GenericQ r
everythingBut p k def f x | p x = def
                          | otherwise = foldl k (f x) (gmapQ (everythingBut p k def f) x)