``Scrap Your Zippers: A Generic Zipper for Heterogeneous Types. Michael D. Adams. WGP '10: Proceedings of the 2010 ACM SIGPLAN workshop on Generic programming, 2010.''

See http://www.cs.indiana.edu/~adamsmd/papers/scrap_your_zippers/

- data Zipper root
- toZipper :: Data a => a -> Zipper a
- fromZipper :: Zipper a -> a
- left :: Zipper a -> Maybe (Zipper a)
- right :: Zipper a -> Maybe (Zipper a)
- down :: Zipper a -> Maybe (Zipper a)
- down' :: Zipper a -> Maybe (Zipper a)
- up :: Zipper a -> Maybe (Zipper a)
- query :: GenericQ b -> Zipper a -> b
- trans :: GenericT -> Zipper a -> Zipper a
- transM :: Monad m => GenericM m -> Zipper a -> m (Zipper a)
- getHole :: Typeable b => Zipper a -> Maybe b
- setHole :: Typeable a => a -> Zipper b -> Zipper b
- setHole' :: Typeable a => a -> Zipper b -> Maybe (Zipper b)
- moveQ :: Move a -> b -> (Zipper a -> b) -> Zipper a -> b
- leftQ :: b -> (Zipper a -> b) -> Zipper a -> b
- rightQ :: b -> (Zipper a -> b) -> Zipper a -> b
- downQ :: b -> (Zipper a -> b) -> Zipper a -> b
- upQ :: b -> (Zipper a -> b) -> Zipper a -> b
- moveT :: Move a -> Move a -> Zipper a -> (Zipper a -> Zipper a) -> Zipper a -> Zipper a
- leftT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper a
- rightT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper a
- downT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper a
- upT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper a
- moveM :: Monad m => Move a -> Move a -> m (Zipper a) -> (Zipper a -> m (Zipper a)) -> Zipper a -> m (Zipper a)
- rightM :: Monad m => m (Zipper a) -> (Zipper a -> m (Zipper a)) -> Zipper a -> m (Zipper a)
- downM :: Monad m => m (Zipper a) -> (Zipper a -> m (Zipper a)) -> Zipper a -> m (Zipper a)
- upM :: Monad m => m (Zipper a) -> (Zipper a -> m (Zipper a)) -> Zipper a -> m (Zipper a)
- leftmost :: Zipper a -> Zipper a
- rightmost :: Zipper a -> Zipper a
- zmapQ :: GenericQ b -> Zipper a -> [b]
- zmapT :: GenericT -> Zipper a -> Zipper a
- zmapM :: Monad m => GenericM m -> Zipper a -> m (Zipper a)
- zmapMp :: MonadPlus m => GenericM m -> Zipper a -> m (Zipper a)
- zeverywhere :: GenericT -> Zipper a -> Zipper a
- zeverywhere' :: GenericT -> Zipper a -> Zipper a
- zsomewhere :: MonadPlus m => GenericM m -> Zipper a -> m (Zipper a)
- zreduce :: GenericM Maybe -> Zipper a -> Zipper a

# Core types

# Core interface

## Injection and projection

toZipper :: Data a => a -> Zipper aSource

Create a zipper. The focus starts at the root of the object.

fromZipper :: Zipper a -> aSource

Move up a zipper to the root and return the root object.

## Basic movement

left :: Zipper a -> Maybe (Zipper a)Source

Move left. Returns `Nothing`

iff already at leftmost sibling.

right :: Zipper a -> Maybe (Zipper a)Source

Move right. Returns `Nothing`

iff already at rightmost sibling.

down :: Zipper a -> Maybe (Zipper a)Source

Move down. Moves to rightmost immediate child. Returns `Nothing`

iff at a leaf and thus no children exist.

down' :: Zipper a -> Maybe (Zipper a)Source

Move down. Move to the leftmost immediate child. Returns `Nothing`

iff at a leaf and thus no children exist.

up :: Zipper a -> Maybe (Zipper a)Source

Move up. Returns `Nothing`

iff already at root and thus no parent exists.

## Basic hole manipulation

transM :: Monad m => GenericM m -> Zipper a -> m (Zipper a)Source

Apply a generic monadic transformation to the hole

# Convenience hole manipulation interface

getHole :: Typeable b => Zipper a -> Maybe bSource

Get the value in the hole. Returns `Nothing`

iff `a`

is not the type of the value in the hole.

setHole :: Typeable a => a -> Zipper b -> Zipper bSource

Set the value in the hole. Does nothing iff `a`

is not the type of the value in the hole.

setHole' :: Typeable a => a -> Zipper b -> Maybe (Zipper b)Source

Set the value in the hole. Returns `Nothing`

iff `a`

is not the type of the value in the hole.

# Generic zipper traversals

## Traversal helpers

### Query

:: Move a | Move operation |

-> b | Default if can't move |

-> (Zipper a -> b) | Query if can move |

-> Zipper a | Zipper |

-> b |

Apply a generic query using the specified movement operation.

Apply a generic query to the left sibling if one exists.

Apply a generic query to the right sibling if one exists.

Apply a generic query to the parent if it exists.

Apply a generic query to the rightmost child if one exists.

### Transform

:: Move a | Move to |

-> Move a | Move back |

-> Zipper a | Default if can't move |

-> (Zipper a -> Zipper a) | Transformer if can move |

-> Zipper a | Zipper |

-> Zipper a |

Apply a generic transformer using the specified movement operations.

leftT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper aSource

Apply a generic transformer to the left sibling if one exists. Otherwise, leaves the zipper unchanged.

rightT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper aSource

Apply a generic transformer to the right sibling if one exists. Otherwise, leaves the zipper unchanged.

downT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper aSource

Apply a generic transformer to the rightmost child if one exists. Otherwise, leaves the zipper unchanged.

upT :: (Zipper a -> Zipper a) -> Zipper a -> Zipper aSource

Apply a generic transformer to the parent if it exists. Otherwise, leaves the zipper unchanged.

### Monadic Transform

:: Monad m | |

=> Move a | Move to |

-> Move a | Move back |

-> m (Zipper a) | Default if can't move |

-> (Zipper a -> m (Zipper a)) | Monadic transformer if can move |

-> Zipper a | Zipper |

-> m (Zipper a) |

Apply a generic monadic transformer using the specified movement operations.

:: Monad m | |

=> m (Zipper a) | Value to return if no right sibling exists. |

-> (Zipper a -> m (Zipper a)) | |

-> Zipper a | |

-> m (Zipper a) |

Apply a generic monadic transformer to the right sibling if one exists.

:: Monad m | |

=> m (Zipper a) | Value to return if no children exist. |

-> (Zipper a -> m (Zipper a)) | |

-> Zipper a | |

-> m (Zipper a) |

Apply a generic monadic transformer to the rightmost child if one exists.

:: Monad m | |

=> m (Zipper a) | Value to return if parent does not exist. |

-> (Zipper a -> m (Zipper a)) | |

-> Zipper a | |

-> m (Zipper a) |

Apply a generic monadic transformer to the parent if it exists.

### Movement

## Map traversals

zmapT :: GenericT -> Zipper a -> Zipper aSource

Apply a generic transformation to the immediate children.

zmapM :: Monad m => GenericM m -> Zipper a -> m (Zipper a)Source

Apply a generic monadic transformation to the immediate children.

zmapMp :: MonadPlus m => GenericM m -> Zipper a -> m (Zipper a)Source

Apply a generic monadic transformation to at least one child that does not fail.

## Tree traversals

zeverywhere :: GenericT -> Zipper a -> Zipper aSource

Apply a generic transformation everywhere in a bottom-up manner.

zeverywhere' :: GenericT -> Zipper a -> Zipper aSource

Apply a generic transformation everywhere in a top-down manner.

zsomewhere :: MonadPlus m => GenericM m -> Zipper a -> m (Zipper a)Source

Apply a generic monadic transformation once at the topmost leftmost successful location.

zreduce :: GenericM Maybe -> Zipper a -> Zipper aSource

Repeatedly apply a monadic `Maybe`

generic transformation at the
top-most, left-most position that the transformation returns
`Just`

. Behaves like iteratively applying `zsomewhere`

but is
more efficient because it re-evaluates the transformation
at only the parents of the last successful application.