{-|
    SYB compatibility layer. This module serves as a drop-in
    replacement in some situations for some of the SYB operations.
    Users should also import "Data.Generics.Uniplate.Data".

    SYB is described in the paper: \"Scrap your boilerplate: a practical design
    pattern for generic programming\" by Ralf Lammel and Simon
    Peyton Jones.

    * <http://www.cs.vu.nl/boilerplate/>

    * <http://doi.acm.org/10.1145/604174.604179>

    * <http://www.cs.vu.nl/boilerplate/tldi03.pdf>
-}

module Data.Generics.SYB where

import Data.Generics.Uniplate.Operations


-- | @gmapT == 'descend'@
gmapT :: Uniplate a => (a -> a) -> a -> a
gmapT :: (a -> a) -> a -> a
gmapT = (a -> a) -> a -> a
forall on. Uniplate on => (on -> on) -> on -> on
descend


-- | Use 'children' and 'foldl'
gmapQl :: Uniplate a => (r -> r' -> r) -> r -> (a -> r') -> a -> r
gmapQl :: (r -> r' -> r) -> r -> (a -> r') -> a -> r
gmapQl r -> r' -> r
combine r
zero a -> r'
op = (r -> r' -> r) -> r -> [r'] -> r
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl r -> r' -> r
combine r
zero ([r'] -> r) -> (a -> [r']) -> a -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> r') -> [a] -> [r']
forall a b. (a -> b) -> [a] -> [b]
map a -> r'
op ([a] -> [r']) -> (a -> [a]) -> a -> [r']
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall on. Uniplate on => on -> [on]
children


-- | Use 'children' and 'foldr'
gmapQr :: Uniplate a => (r' -> r -> r) -> r -> (a -> r') -> a -> r
gmapQr :: (r' -> r -> r) -> r -> (a -> r') -> a -> r
gmapQr r' -> r -> r
combine r
zero a -> r'
op = (r' -> r -> r) -> r -> [r'] -> r
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr r' -> r -> r
combine r
zero ([r'] -> r) -> (a -> [r']) -> a -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> r') -> [a] -> [r']
forall a b. (a -> b) -> [a] -> [b]
map a -> r'
op ([a] -> [r']) -> (a -> [a]) -> a -> [r']
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall on. Uniplate on => on -> [on]
children


-- | Use 'children'
gmapQ :: Uniplate a => (a -> u) -> a -> [u]
gmapQ :: (a -> u) -> a -> [u]
gmapQ a -> u
f = (a -> u) -> [a] -> [u]
forall a b. (a -> b) -> [a] -> [b]
map a -> u
f ([a] -> [u]) -> (a -> [a]) -> a -> [u]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall on. Uniplate on => on -> [on]
children


-- | Use 'children' and '!!'
gmapQi :: Uniplate a => Int -> (a -> u) -> a -> u
gmapQi :: Int -> (a -> u) -> a -> u
gmapQi Int
i a -> u
f a
x = (a -> u) -> a -> [u]
forall a u. Uniplate a => (a -> u) -> a -> [u]
gmapQ a -> u
f a
x [u] -> Int -> u
forall a. [a] -> Int -> a
!! Int
i


-- | @gmapM == 'descendM'@
gmapM :: (Uniplate a, Applicative m) => (a -> m a) -> a -> m a
gmapM :: (a -> m a) -> a -> m a
gmapM = (a -> m a) -> a -> m a
forall on (m :: * -> *).
(Uniplate on, Applicative m) =>
(on -> m on) -> on -> m on
descendM



-- | @mkT == 'id'@
mkT :: (a -> a) -> (a -> a)
mkT :: (a -> a) -> a -> a
mkT = (a -> a) -> a -> a
forall a. a -> a
id


-- | @everywhere == 'transformBi'@
everywhere :: Biplate b a => (a -> a) -> b -> b
everywhere :: (a -> a) -> b -> b
everywhere = (a -> a) -> b -> b
forall from to. Biplate from to => (to -> to) -> from -> from
transformBi


-- | @mkM == id@
mkM :: (a -> m a) -> a -> m a
mkM :: (a -> m a) -> a -> m a
mkM = (a -> m a) -> a -> m a
forall a. a -> a
id


-- | @everywhereM == 'transformBiM'@
everywhereM :: (Biplate b a, Monad m, Applicative m) => (a -> m a) -> b -> m b
everywhereM :: (a -> m a) -> b -> m b
everywhereM = (a -> m a) -> b -> m b
forall (m :: * -> *) from to.
(Monad m, Applicative m, Biplate from to) =>
(to -> m to) -> from -> m from
transformBiM



-- | Only for use with 'everything'
mkQ :: r -> (a -> r) -> (r, a -> r)
mkQ :: r -> (a -> r) -> (r, a -> r)
mkQ = (,)


-- | Use 'universe' or 'universeBi', perhaps followed by a fold.
--
--   Not an exact equivalent to the SYB @everything@, as the
--   operators may be applied in different orders.
everything :: Biplate b a => (r -> r -> r) -> (r, a -> r) -> b -> r
everything :: (r -> r -> r) -> (r, a -> r) -> b -> r
everything r -> r -> r
combine (r
nil, a -> r
op) = (r -> r -> r) -> r -> [r] -> r
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl r -> r -> r
combine r
nil ([r] -> r) -> (b -> [r]) -> b -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> r) -> [a] -> [r]
forall a b. (a -> b) -> [a] -> [b]
map a -> r
op ([a] -> [r]) -> (b -> [a]) -> b -> [r]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> [a]
forall from to. Biplate from to => from -> [to]
universeBi