uniplate-1.2.0.3: Uniform type generic traversals.ContentsIndex
Data.Generics.Uniplate
Contents
The Class
The Operations
Queries
Transformations
Others
Description

RECOMMENDATION Use Data.Generics.UniplateStr instead.

This is the main Uniplate module, which defines all the essential operations in a Haskell 98 compatible manner.

Most functions have an example of a possible use for the function. To illustate, I have used the Expr type as below:

 data Expr = Val Int
           | Neg Expr
           | Add Expr Expr
Synopsis
type UniplateType on = on -> ([on], [on] -> on)
class Uniplate on where
uniplate :: UniplateType on
universe :: Uniplate on => on -> [on]
children :: Uniplate on => on -> [on]
transform :: Uniplate on => (on -> on) -> on -> on
transformM :: (Monad m, Uniplate on) => (on -> m on) -> on -> m on
rewrite :: Uniplate on => (on -> Maybe on) -> on -> on
rewriteM :: (Monad m, Uniplate on) => (on -> m (Maybe on)) -> on -> m on
descend :: Uniplate on => (on -> on) -> on -> on
descendM :: (Monad m, Uniplate on) => (on -> m on) -> on -> m on
contexts :: Uniplate on => on -> [(on, on -> on)]
holes :: Uniplate on => on -> [(on, on -> on)]
para :: Uniplate on => (on -> [r] -> r) -> on -> r
The Class
type UniplateType on = on -> ([on], [on] -> on)

The type of replacing all the children of a node

Taking a value, the function should return all the immediate children of the same type, and a function to replace them.

class Uniplate on where
The standard Uniplate class, all operations require this
Methods
uniplate :: UniplateType on

The underlying method in the class

 uniplate (Add (Val 1) (Neg (Val 2))) = ([Val 1, Neg (Val 2)], \[a,b] -> Add a b)
 uniplate (Val 1)                     = ([]                  , \[]    -> Val 1  )
The Operations
Queries
universe :: Uniplate on => on -> [on]

Get all the children of a node, including itself and all children.

 universe (Add (Val 1) (Neg (Val 2))) =
     [Add (Val 1) (Neg (Val 2)), Val 1, Neg (Val 2), Val 2]

This method is often combined with a list comprehension, for example:

 vals x = [Val i | i <- universe x]
children :: Uniplate on => on -> [on]

Get the direct children of a node. Usually using universe is more appropriate.

children = fst . uniplate
Transformations
transform :: Uniplate on => (on -> on) -> on -> on

Transform every element in the tree, in a bottom-up manner.

For example, replacing negative literals with literals:

 negLits = transform f
    where f (Neg (Lit i)) = Lit (negate i)
          f x = x
transformM :: (Monad m, Uniplate on) => (on -> m on) -> on -> m on
Monadic variant of transform
rewrite :: Uniplate on => (on -> Maybe on) -> on -> on

Rewrite by applying a rule everywhere you can. Ensures that the rule cannot be applied anywhere in the result:

 propRewrite r x = all (isNothing . r) (universe (rewrite r x))

Usually transform is more appropriate, but rewrite can give better compositionality. Given two single transformations f and g, you can construct f mplus g which performs both rewrites until a fixed point.

rewriteM :: (Monad m, Uniplate on) => (on -> m (Maybe on)) -> on -> m on
Monadic variant of rewrite
descend :: Uniplate on => (on -> on) -> on -> on
Perform a transformation on all the immediate children, then combine them back. This operation allows additional information to be passed downwards, and can be used to provide a top-down transformation.
descendM :: (Monad m, Uniplate on) => (on -> m on) -> on -> m on
Monadic variant of descend
Others
contexts :: Uniplate on => on -> [(on, on -> on)]

Return all the contexts and holes.

 propUniverse x = universe x == map fst (contexts x)
 propId x = all (== x) [b a | (a,b) <- contexts x]
holes :: Uniplate on => on -> [(on, on -> on)]

The one depth version of contexts

 propChildren x = children x == map fst (holes x)
 propId x = all (== x) [b a | (a,b) <- holes x]
para :: Uniplate on => (on -> [r] -> r) -> on -> r
Perform a fold-like computation on each value, technically a paramorphism
Produced by Haddock version 0.8