Here is what I think is most interesting about zippers:

  1. take any algebraic data type and convert it to an algebraic equation
  2. take the (partial) derivative of that equation over any (type) variables
  3. convert that result back to a data type

You now have the zipper (without the focus) for the original data type

for example d/da. List a produces (List a)^2 i.e. a pair of lists -- put the focus in and now you have the list zipper:data ListZipper a = ListZipper [a] a [a]

you can do trivial data types, such as:

data TwoOrThree a = TwoOrThree a a (Maybe a)

which algebraically is

2 * a * (1 + a)

and the partial derivative (zipper) is:

4 * a + 2

which as a data type is:

data TwoOrThreeDerivative a = Four a a a a | Two Bool

But when you have a relatively complicated data type, finding the derivative/zipper can be tricky work that is hard to hold in your head at all times.