{-|
    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 :: forall a. Uniplate a => (a -> a) -> a -> a
gmapT = forall a. Uniplate a => (a -> a) -> a -> a
descend


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


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


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


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


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



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


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


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


-- | @everywhereM == 'transformBiM'@
everywhereM :: (Biplate b a, Monad m, Applicative m) => (a -> m a) -> b -> m b
everywhereM :: forall b a (m :: * -> *).
(Biplate b a, Monad m, Applicative m) =>
(a -> m a) -> b -> m b
everywhereM = 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 :: forall r a. 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 :: forall b a r. Biplate b a => (r -> r -> r) -> (r, a -> r) -> b -> r
everything r -> r -> r
combine (r
nil, a -> r
op) = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl r -> r -> r
combine r
nil forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map a -> r
op forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall from to. Biplate from to => from -> [to]
universeBi