Skip to content

Instantly share code, notes, and snippets.

@igstan
Last active August 29, 2015 14:13
Show Gist options
  • Save igstan/a0354c2ce83cc272cff3 to your computer and use it in GitHub Desktop.
Save igstan/a0354c2ce83cc272cff3 to your computer and use it in GitHub Desktop.
object Zippers {
case class Zipper[A](before: List[A], focus: A, after: List[A]) {
/**
* Focus the element to the left, if any.
*/
def left: Option[Zipper[A]] = this match {
case Zipper(List(), _, _) => None
case Zipper(x :: xs, y, zs) => Some(Zipper(xs, x, y :: zs))
}
/**
* Focus the element to the right, if any.
*/
def right: Option[Zipper[A]] = this match {
case Zipper(_, _, List()) => None
case Zipper(xs, y, z :: zs) => Some(Zipper(y :: xs, z, zs))
}
/**
* Replace the focused element.
*/
def update(a: A): Zipper[A] = {
Zipper(before, a, after)
}
/**
* Delete the focused element.
*/
def delete: Zipper[A] = this match {
case Zipper(h @ List(), _, x :: xs) => Zipper(h, x, xs)
case Zipper(x :: xs, _, h) => Zipper(xs, x, h)
}
/**
* Insert to the left of the focus and set focus on the inserted element.
*/
def insertLeft(a: A): Zipper[A] = {
Zipper(before, a, focus :: after)
}
/**
* Insert to the right of the focus and set focus on the inserted element.
*/
def insertRight(a: A): Zipper[A] = {
Zipper(focus :: before, a, after)
}
}
def example(): Unit = {
val zipper = Zipper(List(4,3,2,1), 5, List(6,7,8,9))
val result = for {
a <- zipper.left // focused: 4
b <- a.left // focused: 3
c <- b.left // focused: 2
d = c.delete // deletes: 2
e = d.insertRight(42) // inserts: 42 after 1
f = e.insertLeft(41) // inserts: 41 before 42
} yield f
println(result)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment