zipper

Create a zipper, focused on the top-left value.
Construct a Zipper that can explore anything, and start it at the Top.
Not on Stackage, so not searched. Generic zipper for families of recursive datatypes
A zipper is a structure for walking a value and manipulating it in constant time. This module was inspired by the paper: Michael D. Adams. Scrap Your Zippers: A Generic Zipper for Heterogeneous Types, Workshop on Generic Programming 2010.
Zipper structure, whose root type is the first type argument, and whose focus type is the second type argument.
This module provides a two-dimensional text zipper data structure. This structure represents a body of text and an editing cursor which can be moved throughout the text, along with a set of editing transformations. Text zippers are generalized over the set of data types that might be used to store lists of characters (e.g., String, Text, etc.). As a result, the most general way to create a text zipper is to use mkZipper and provide all of the functions required to manipulate the underlying text data. Implementations using Text and String are provided.
Creation date: Thu Jul 23 08:42:37 2020.
This module provides a Zipper with fairly strong type checking guarantees. The code here is inspired by Brandon Simmons' zippo package, but uses a different approach to represent the Zipper that makes the whole thing look like his breadcrumb trail, and can move side-to-side through traversals. Some examples types: Since individual levels of a Zipper are managed by an arbitrary IndexedTraversal, you can move left and right through the IndexedTraversal selecting neighboring elements.
>>> zipper ("hello","world") & downward _1 & fromWithin traverse & focus .~ 'J' & rightmost & focus .~ 'y' & rezip
("Jelly","world")
This is particularly powerful when compiled with plate, uniplate or biplate for walking down into self-similar children in syntax trees and other structures. Given keys in ascending order you can jump directly to a given key with moveTo. When used with traversals for balanced tree-like structures such as an IntMap or Map, searching for a key with moveTo can be done in logarithmic time.
This is the type of a Zipper. It visually resembles a "breadcrumb trail" as used in website navigation. Each breadcrumb in the trail represents a level you can move up to. This type operator associates to the left, so you can use a type like
Top :>> (String,Double) :>> String :>> Char
to represent a Zipper from (String,Double) down to Char that has an intermediate crumb for the String containing the Char. You can construct a Zipper into *any* data structure with zipper. You can repackage up the contents of a Zipper with rezip.
>>> rezip $ zipper 42
42
The combinators in this module provide lot of things you can do to the Zipper while you have it open. Note that a value of type h :> s :> a doesn't actually contain a value of type h :> s -- as we descend into a level, the previous level is unpacked and stored in Coil form. Only one value of type _ :> _ exists at any particular time for any particular Zipper.
Based on «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» (http://michaeldadams.org/papers/scrap_your_zippers/). Compared to the original syz package, this implementation (based on GTraversable) gives more flexibility as to where a zipper may point to and what is considered as siblings. Specifically, a zipper may point to any element which gtraverse applies its function to.

Example

syz

Consider the classical example: lists. With syz, a list is interpreted as a right-balanced tree.
>>> let z = fromJust . down' $ toZipper ['a'..'d']

>>> getHole z :: Maybe Char
Just 'a'
The zipper z points to the first element of the list. Now let's move to the right:
>>> let z' = fromJust . right $ z

>>> getHole z' :: Maybe Char
Nothing

>>> getHole z' :: Maybe [Char]
Just "bcd"
Instead of pointing to the second element of the list, as one might expect, the zipper z' points to the tail of the list. In order to actually move to the second element, we need another down':
>>> let z'' = fromJust . down' $ z'

>>> getHole z'' :: Maybe Char
Just 'b'

traverse-with-class

GTraversable-based zippers behave more intuitively in this regard, thanks to the uniform instance for lists.
>>> let z = fromJust . down' $ toZipper ['a'..'d'] :: Zipper Typeable [Char]

>>> getHole z :: Maybe Char
Just 'a'
So far it's more or less the same as with syz. We needed to add a type annotation for the zipper itself to clarify the context which should be available at each hole (Typeable in this case). Now let's see what's to the right of us:
>>> let z' = fromJust . right $ z

>>> getHole z' :: Maybe Char
Just 'b'
That is, we jumped right to the second element of the list. Likewise,
>>> let z'' = rightmost z

>>> getHole z'' :: Maybe Char
Just 'd'
So, unlike in syz, all of the list elements are siblings.
A generic zipper with a root object of type root.
This is an infinite bidirectional zipper