@hackage pez0.0.2

A Potentially-Excellent Zipper library

  • Categories

    • License

      BSD-3-Clause

    • Maintainer

      brandon.m.simmons@gmail.com

    • Versions

    PEZ is a generic zipper library. It uses lenses from the fclabels package to reference a "location" to move to in the zipper. The zipper is restricted to types in the Typeable class, allowing the user to "move up" through complex data structures such as mutually-recursive types.

    Both the Typeable class and fclabels lenses can be derived in GHC, making it easy for the programmer to use a zipper with a minimum of boilerplate.

    First import the library, which brings in the Typeable and fclabels modules. You will also want to enable a few extensions:

    {-# LANGUAGE TemplateHaskell, DeriveDataTypeable, TypeOperators #-}
    module Main where
    
    import Data.Typeable.Zipper

    Create a datatype, deriving an instance of the Typeable class, and generate a lens using functions from fclabels:

    data Tree a = Node { _leftNode :: Tree a,
                         _val      :: a,
                         _rightNode :: Tree a }
                | Nil
                deriving (Typeable,Show)
    
    $(mkLabelsNoTypes [''Tree])

    Now we can go crazy using Tree in a Zipper:

    treeBCD = Node (Node Nil 'b' Nil) 'c' (Node Nil 'd' Nil)
    
    descendLeft :: Zipper1 (Tree a) -> Zipper1 (Tree a)
    descendLeft z = case (viewf z) of
                         Nil -> z
                         _   -> descendLeft $ moveTo leftNode z
    
    insertLeftmost :: a -> Tree a -> Tree a
    insertLeftmost x = close . setL focus x . descendLeft . zipper
    
    treeABCD = insertLeftmost 'a' treeBCD

    Because of the flexibility of fclabels, this zipper library can be used to express moving about in reversible computations simply by defining such a lens, for instance:

    stringRep :: (Show b, Read b) => b :-> String
    stringRep = lens show (const . read)

    Please send any feature requests or bug reports along.