Skip to content

Instantly share code, notes, and snippets.

@viktor-evdokimov
Forked from hoheinzollern/zipper.scala
Last active October 19, 2016 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save viktor-evdokimov/d621ee082a93426a97673abce4f2eac2 to your computer and use it in GitHub Desktop.
Save viktor-evdokimov/d621ee082a93426a97673abce4f2eac2 to your computer and use it in GitHub Desktop.
Zipper scala implementation
sealed abstract class Tree[A]
case class Item[A] (item: A) extends Tree[A]
case class Section[A] (s: List[Tree[A]]) extends Tree[A]
sealed abstract class Path[A]
case class Top[A] extends Path[A]
case class Node[A] (l: List[Tree[A]], p: Path[A], r: List[Tree[A]]) extends Path[A]
case class Location[A] (t: Tree[A], p: Path[A])
object zipper {
def goLeft[A](loc: Location[A]): Location[A] = loc.p match {
case Top() => throw new Exception("left of top")
case Node(l :: left, up, right) => Location(l, Node(left, up, loc.t :: right))
case Node(List(), up, right) => throw new Exception("left of first")
}
def goRight[A](loc: Location[A]): Location[A] = loc.p match {
case Top() => throw new Exception("right of top")
case Node(left, up, r :: right) => Location(r, Node(loc.t :: left, up, right))
case _ => throw new Exception("right of last")
}
def goUp[A](loc: Location[A]): Location[A] = loc.p match {
case Top() => throw new Exception("up of top")
case Node(left, up, right) => Location(Section((left reverse) ::: (loc.t :: right)), up)
}
def goDown[A](loc: Location[A]): Location[A] = loc.t match {
case Item(_) => throw new Exception("down of item")
case Section(t1 :: trees) => Location(t1, Node(Nil, loc.p, trees))
case _ => throw new Exception("down of empty")
}
def change[A](loc: Location[A], t: Tree[A]): Location[A] = Location(t, loc.p)
def insertRight[A](loc: Location[A], r: Tree[A]): Location[A] = loc.p match {
case Top() => throw new Exception("insert of top")
case Node(left, up, right) => Location(loc.t, Node(left, up, r :: right))
}
def insertLeft[A](loc: Location[A], l: Tree[A]): Location[A] = loc.p match {
case Top() => throw new Exception("insert of top")
case Node(left, up, right) => Location(loc.t, Node(l :: left, up, right))
}
def insertDown[A](loc: Location[A], t1: Tree[A]): Location[A] = loc.t match {
case Item(_) => throw new Exception("down of item")
case Section(sons) => Location(t1, Node(Nil, loc.p, sons))
}
def delete[A](loc: Location[A]): Location[A] = loc.p match {
case Top() => throw new Exception("delete of top")
case Node(left, up, r::right) => Location(r, Node(left, up, right))
case Node(l :: left, up, Nil) => Location(l, Node(left, up, Nil))
case Node(Nil, up, Nil) => Location(Section(Nil), up)
}
def main(args: Array[String]) {
val x = Section(
Section(Item("a") :: Item("*") :: Item("b") :: Nil) ::
Item("+") ::
Section(Item("c") :: Item("*") :: Item("d") :: Nil) :: Nil
)
println (x)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment