    {-|
        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 combine :: r -> r' -> r
    combine zero :: r
    zero op :: 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 combine :: r' -> r -> r
    combine zero :: r
    zero op :: 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 f :: 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 i :: Int
    i f :: a -> u
    f x :: 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, Monad 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, Monad 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 :: Monad m => (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) => (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, 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 combine :: r -> r -> r
    combine (nil :: r
    nil, op :: 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