/core/src/main/scala/scalaz/TreeLoc.scala

http://github.com/scalaz/scalaz · Scala · 463 lines · 347 code · 75 blank · 41 comment · 33 complexity · ff697cc9bde11108879a852ab4ae8cdc MD5 · raw file

  1. package scalaz
  2. import TreeLoc._
  3. import annotation.tailrec
  4. import EphemeralStream.{EStream, ##::, emptyEphemeralStream}
  5. /**
  6. * A rose-tree zipper. Represents a [[scalaz.Tree]] together with a position in that tree.
  7. * Provides navigation, persistent update, insertion, and deletes.
  8. *
  9. * @param tree The currently selected node.
  10. * @param lefts The left siblings of the current node.
  11. * @param rights The right siblings of the current node.
  12. * @param parents The parent contexts of the current node.
  13. */
  14. final case class TreeLoc[A](tree: Tree[A], lefts: TreeForest[A],
  15. rights: TreeForest[A], parents: Parents[A]) {
  16. import Tree._
  17. /** Select the parent of the current node. */
  18. def parent: Option[TreeLoc[A]] = parents match {
  19. case (pls, v, prs) ##:: ps => Some(loc(Node(v, combChildren(lefts, tree, rights)), pls, prs, ps))
  20. case s if s.isEmpty => None
  21. }
  22. /** Select the root node of the tree. */
  23. @tailrec
  24. def root: TreeLoc[A] =
  25. parent match {
  26. case Some(z) => z.root
  27. case None => this
  28. }
  29. /** Select the left sibling of the current node. */
  30. def left: Option[TreeLoc[A]] = lefts match {
  31. case t ##:: ts => Some(loc(t, ts, tree ##:: rights, parents))
  32. case s if s.isEmpty => None
  33. }
  34. /** Select the right sibling of the current node. */
  35. def right: Option[TreeLoc[A]] = rights match {
  36. case t ##:: ts => Some(loc(t, tree ##:: lefts, ts, parents))
  37. case s if s.isEmpty => None
  38. }
  39. /** Select the leftmost child of the current node. */
  40. def firstChild: Option[TreeLoc[A]] = tree.subForest match {
  41. case t ##:: ts => Some(loc(t, EphemeralStream.emptyEphemeralStream, ts, downParents))
  42. case s if s.isEmpty => None
  43. }
  44. /** Select the rightmost child of the current node. */
  45. def lastChild: Option[TreeLoc[A]] = tree.subForest.reverse match {
  46. case t ##:: ts => Some(loc(t, ts, EphemeralStream.emptyEphemeralStream, downParents))
  47. case s if s.isEmpty => None
  48. }
  49. /** Select the nth child of the current node. */
  50. def getChild(n: Int): Option[TreeLoc[A]] =
  51. for {lr <- splitChildren(EphemeralStream.emptyEphemeralStream, tree.subForest, n)
  52. ls = lr._1
  53. h <- ls.headOption
  54. t <- ls.tailOption
  55. } yield loc(h, t, lr._2, downParents)
  56. /** Select the first immediate child of the current node that satisfies the given predicate. */
  57. def findChild(p: Tree[A] => Boolean): Option[TreeLoc[A]] = {
  58. @tailrec
  59. def split(acc: TreeForest[A], xs: TreeForest[A]): Option[(TreeForest[A], Tree[A], TreeForest[A])] =
  60. (acc, xs) match {
  61. case (acc, (x ##:: xs)) => if (p(x)) Some((acc, x, xs)) else split(EphemeralStream.cons(x, acc), xs)
  62. case _ => None
  63. }
  64. for (ltr <- split(EphemeralStream.emptyEphemeralStream, tree.subForest)) yield loc(ltr._2, ltr._1, ltr._3, downParents)
  65. }
  66. /** Select the first descendant node of the current node that satisfies the given predicate. */
  67. def find(p: TreeLoc[A] => Boolean): Option[TreeLoc[A]] =
  68. Cobind[TreeLoc].cojoin(this).tree.flatten.filter(p).headOption
  69. /** Get the entire tree represented by this zipper. */
  70. def toTree: Tree[A] = root.tree
  71. /** Get the entire forest represented by this zipper. */
  72. def toForest: TreeForest[A] = combChildren(root.lefts, root.tree, root.rights)
  73. /** True if the current node is the root node. */
  74. def isRoot: Boolean = parents.isEmpty
  75. /** True if the current node has no left siblings. */
  76. def isFirst: Boolean = lefts.isEmpty
  77. /** True if the current node has no right siblings. */
  78. def isLast: Boolean = rights.isEmpty
  79. /** True if the current node has no children. */
  80. def isLeaf: Boolean = tree.subForest.isEmpty
  81. /** True if the current node is not the root node. */
  82. def isChild: Boolean = !isRoot
  83. /** True if the current node has children. */
  84. def hasChildren: Boolean = !isLeaf
  85. /** Replace the current node with the given one. */
  86. def setTree(t: Tree[A]): TreeLoc[A] = loc(t, lefts, rights, parents)
  87. /** Modify the current node with the given function. */
  88. def modifyTree(f: Tree[A] => Tree[A]): TreeLoc[A] = setTree(f(tree))
  89. /** Modify the label at the current node with the given function. */
  90. def modifyLabel(f: A => A): TreeLoc[A] = setLabel(f(getLabel))
  91. /** Get the label of the current node. */
  92. def getLabel: A = tree.rootLabel
  93. /** Set the label of the current node. */
  94. def setLabel(a: A): TreeLoc[A] = modifyTree((t: Tree[A]) => Node(a, t.subForest))
  95. /** Insert the given node to the left of the current node and give it focus. */
  96. def insertLeft(t: Tree[A]): TreeLoc[A] = loc(t, lefts, EphemeralStream.cons(tree, rights), parents)
  97. /** Insert the given node to the right of the current node and give it focus. */
  98. def insertRight(t: Tree[A]): TreeLoc[A] = loc(t, EphemeralStream.cons(tree, lefts), rights, parents)
  99. /** Insert the given node as the first child of the current node and give it focus. */
  100. def insertDownFirst(t: Tree[A]): TreeLoc[A] = loc(t, EphemeralStream.emptyEphemeralStream, tree.subForest, downParents)
  101. /** Insert the given node as the last child of the current node and give it focus. */
  102. def insertDownLast(t: Tree[A]): TreeLoc[A] = loc(t, tree.subForest.reverse, EphemeralStream.emptyEphemeralStream, downParents)
  103. /** Insert the given node as the nth child of the current node and give it focus. */
  104. def insertDownAt(n: Int, t: Tree[A]): Option[TreeLoc[A]] =
  105. for (lr <- splitChildren(EphemeralStream.emptyEphemeralStream, tree.subForest, n)) yield loc(t, lr._1, lr._2, downParents)
  106. /** Delete the current node and all its children. */
  107. def delete: Option[TreeLoc[A]] = rights match {
  108. case t ##:: ts => Some(loc(t, lefts, ts, parents))
  109. case _ => lefts match {
  110. case t ##:: ts => Some(loc(t, ts, rights, parents))
  111. case _ => for (loc1 <- parent) yield loc1.modifyTree((t: Tree[A]) => Node(t.rootLabel, emptyEphemeralStream))
  112. }
  113. }
  114. /**
  115. * The path from the focus to the root.
  116. */
  117. def path: EStream[A] = getLabel ##:: parents.map(_._2)
  118. /** Maps the given function over the elements. */
  119. def map[B](f: A => B): TreeLoc[B] = {
  120. val ff = (_: Tree[A]).map(f)
  121. TreeLoc.loc(tree map f, lefts map ff, rights map ff,
  122. parents.map {
  123. case (l, t, r) => (l map ff, f(t), r map ff)
  124. })
  125. }
  126. def cojoin: TreeLoc[TreeLoc[A]] = {
  127. val lft = (_: TreeLoc[A]).left
  128. val rgt = (_: TreeLoc[A]).right
  129. def dwn[A](tz: TreeLoc[A]): (TreeLoc[A], () => EStream[TreeLoc[A]]) = {
  130. val f = () => EphemeralStream.unfold(tz.firstChild) {
  131. (o: Option[TreeLoc[A]]) => for (c <- o) yield (c, c.right)
  132. }
  133. (tz, f)
  134. }
  135. def uf[A](a: TreeLoc[A], f: TreeLoc[A] => Option[TreeLoc[A]]): EStream[Tree[TreeLoc[A]]] = {
  136. EphemeralStream.unfold(f(a)) {
  137. (o: Option[TreeLoc[A]]) => for (c <- o) yield (Tree.unfoldTree(c)(dwn[A](_: TreeLoc[A])), f(c))
  138. }
  139. }
  140. val p = EphemeralStream.unfold(parent) {
  141. (o: Option[TreeLoc[A]]) => for (z <- o) yield ((uf(z, lft), z, uf(z, rgt)), z.parent)
  142. }
  143. TreeLoc.loc(Tree.unfoldTree(this)(dwn[A](_: TreeLoc[A])), uf(this, lft), uf(this, rgt), p)
  144. }
  145. private def downParents = (lefts, tree.rootLabel, rights) ##:: parents
  146. }
  147. sealed abstract class TreeLocInstances {
  148. implicit val treeLocInstance: Comonad[TreeLoc] with Traverse1[TreeLoc] = new Comonad[TreeLoc] with Traverse1[TreeLoc] {
  149. def copoint[A](p: TreeLoc[A]): A = p.tree.rootLabel
  150. override def map[A, B](fa: TreeLoc[A])(f: A => B): TreeLoc[B] = fa map f
  151. def cobind[A, B](fa: TreeLoc[A])(f: TreeLoc[A] => B): TreeLoc[B] = map(cojoin(fa))(f)
  152. override def cojoin[A](a: TreeLoc[A]): TreeLoc[TreeLoc[A]] = a.cojoin
  153. override def all[A](fa: TreeLoc[A])(f: A => Boolean) =
  154. Foldable[Tree].all(fa.tree)(f) && ForestT.all(fa.lefts)(f) && ForestT.all(fa.rights)(f) && ParentsT.all(fa.parents)(f)
  155. override def any[A](fa: TreeLoc[A])(f: A => Boolean) =
  156. Foldable[Tree].any(fa.tree)(f) || ForestT.any(fa.lefts)(f) || ForestT.any(fa.rights)(f) || ParentsT.any(fa.parents)(f)
  157. override def foldMap1[A, B](fa: TreeLoc[A])(f: A => B)(implicit B: Semigroup[B]) =
  158. foldMapLeft1(fa)(f)((b, a) => B.append(b, f(a)))
  159. override def foldMap[A, B](fa: TreeLoc[A])(f: A => B)(implicit B: Monoid[B]) =
  160. B.append(
  161. B.append(
  162. Foldable[Tree].foldMap(fa.tree)(f),
  163. ForestT.foldMap(fa.lefts)(f)
  164. ),
  165. B.append(
  166. ForestT.foldMap(fa.rights)(f),
  167. ParentsT.foldMap(fa.parents)(f)
  168. )
  169. )
  170. override def foldLeft[A, B](fa: TreeLoc[A], z: B)(f: (B, A) => B) =
  171. ParentsT.foldLeft(
  172. fa.parents, ForestT.foldLeft(
  173. fa.rights, ForestT.foldLeft(
  174. fa.lefts, Foldable[Tree].foldLeft(fa.tree, z)(f))(f))(f))(f)
  175. override def foldMapLeft1[A, B](fa: TreeLoc[A])(z: A => B)(f: (B, A) => B) =
  176. ParentsT.foldLeft(
  177. fa.parents, ForestT.foldLeft(
  178. fa.rights, ForestT.foldLeft(
  179. fa.lefts, Foldable1[Tree].foldMapLeft1(fa.tree)(z)(f))(f))(f))(f)
  180. override def traverse1Impl[G[_], A, B](fa: TreeLoc[A])(f: A => G[B])(implicit G: Apply[G]) = fa.lefts match {
  181. case l ##:: ls =>
  182. val lefts1 = ForestT1.traverse1(OneAnd(l, ls))(f)
  183. fa.rights match {
  184. case r ##:: rs =>
  185. val rights1 = ForestT1.traverse1(OneAnd(r, rs))(f)
  186. fa.parents match {
  187. case p ##:: ps =>
  188. G.apply4(fa.tree.traverse1(f), lefts1, rights1, ParentsT1.traverse1(OneAnd(p, ps))(f))(
  189. (tree, lefts, rights, parents) =>
  190. TreeLoc(
  191. tree = tree,
  192. lefts = lefts.head ##:: lefts.tail,
  193. rights = rights.head ##:: rights.tail,
  194. parents = parents.head ##:: parents.tail
  195. )
  196. )
  197. case s if s.isEmpty =>
  198. G.apply3(fa.tree.traverse1(f), lefts1, rights1)(
  199. (tree, lefts, rights) =>
  200. TreeLoc(
  201. tree = tree,
  202. lefts = lefts.head ##:: lefts.tail,
  203. rights = rights.head ##:: rights.tail,
  204. parents = emptyEphemeralStream
  205. )
  206. )
  207. }
  208. case s if s.isEmpty =>
  209. fa.parents match {
  210. case p ##:: ps =>
  211. G.apply3(fa.tree.traverse1(f), lefts1, ParentsT1.traverse1(OneAnd(p, ps))(f))(
  212. (tree, lefts, parents) =>
  213. TreeLoc(
  214. tree = tree,
  215. lefts = lefts.head ##:: lefts.tail,
  216. rights = emptyEphemeralStream,
  217. parents = parents.head ##:: parents.tail
  218. )
  219. )
  220. case s if s.isEmpty =>
  221. G.apply2(fa.tree.traverse1(f), lefts1)(
  222. (tree, lefts) =>
  223. TreeLoc(
  224. tree = tree,
  225. lefts = lefts.head ##:: lefts.tail,
  226. rights = emptyEphemeralStream,
  227. parents = emptyEphemeralStream
  228. )
  229. )
  230. }
  231. }
  232. case s if s.isEmpty =>
  233. fa.rights match {
  234. case r ##:: rs =>
  235. val rights1 = ForestT1.traverse1(OneAnd(r, rs))(f)
  236. fa.parents match {
  237. case p ##:: ps =>
  238. G.apply3(fa.tree.traverse1(f), rights1, ParentsT1.traverse1(OneAnd(p, ps))(f))(
  239. (tree, rights, parents) =>
  240. TreeLoc(
  241. tree = tree,
  242. lefts = emptyEphemeralStream,
  243. rights = rights.head ##:: rights.tail,
  244. parents = parents.head ##:: parents.tail
  245. )
  246. )
  247. case s if s.isEmpty =>
  248. G.apply2(fa.tree.traverse1(f), rights1)(
  249. (tree, rights) =>
  250. TreeLoc(
  251. tree = tree,
  252. lefts = emptyEphemeralStream,
  253. rights = rights.head ##:: rights.tail,
  254. parents = emptyEphemeralStream
  255. )
  256. )
  257. }
  258. case s if s.isEmpty =>
  259. fa.parents match {
  260. case p ##:: ps =>
  261. G.apply2(fa.tree.traverse1(f), ParentsT1.traverse1(OneAnd(p, ps))(f))(
  262. (tree, parents) =>
  263. TreeLoc(
  264. tree = tree,
  265. lefts = emptyEphemeralStream,
  266. rights = emptyEphemeralStream,
  267. parents = parents.head ##:: parents.tail
  268. )
  269. )
  270. case s if s.isEmpty =>
  271. G.map(fa.tree.traverse1(f))(t =>
  272. TreeLoc(t,
  273. emptyEphemeralStream,
  274. emptyEphemeralStream,
  275. emptyEphemeralStream)
  276. )
  277. }
  278. }
  279. }
  280. override def foldMapRight1[A, B](fa: TreeLoc[A])(z: A => B)(f: (A, => B) => B) =
  281. ParentsT.foldMapRight1Opt(fa.parents)(z)(f) match {
  282. case Some(p) =>
  283. fa.tree.foldRight(
  284. ForestT.foldRight(fa.lefts, ForestT.foldRight(fa.rights, p)(f))(f)
  285. )(f)
  286. case None =>
  287. ForestT.foldMapRight1Opt(fa.rights)(z)(f) match {
  288. case Some(r) =>
  289. fa.tree.foldRight(ForestT.foldRight(fa.lefts, r)(f))(f)
  290. case None =>
  291. ForestT.foldMapRight1Opt(fa.lefts)(z)(f) match {
  292. case Some(l) =>
  293. fa.tree.foldRight(l)(f)
  294. case None =>
  295. Foldable1[Tree].foldMapRight1(fa.tree)(z)(f)
  296. }
  297. }
  298. }
  299. private[this] val ForestT: Traverse[TreeForest] =
  300. Traverse[EStream].compose[Tree]
  301. private[this] val ForestT1: Traverse1[Lambda[a => OneAnd[EStream, Tree[a]]]] =
  302. Traverse1[Lambda[a => OneAnd[EStream, a]]].compose[Tree]
  303. private[this] implicit val ParentT: Traverse1[Parent] = new Traverse1[Parent] {
  304. override def all[A](fa: Parent[A])(f: A => Boolean) =
  305. ForestT.all(fa._1)(f) && f(fa._2) && ForestT.all(fa._3)(f)
  306. override def any[A](fa: Parent[A])(f: A => Boolean) =
  307. ForestT.any(fa._1)(f) || f(fa._2) || ForestT.any(fa._3)(f)
  308. override def foldLeft[A, B](fa: Parent[A], z: B)(f: (B, A) => B) =
  309. ForestT.foldLeft(fa._3, f(ForestT.foldLeft(fa._1, z)(f), fa._2))(f)
  310. override def foldMap[A, B](fa: Parent[A])(f: A => B)(implicit B: Monoid[B]) =
  311. B.append(B.append(ForestT.foldMap(fa._1)(f), f(fa._2)), ForestT.foldMap(fa._3)(f))
  312. override def traverse1Impl[G[_], A, B](fa: Parent[A])(f: A => G[B])(implicit G: Apply[G]): G[Parent[B]] = {
  313. (fa._1, fa._3) match {
  314. case (x ##:: xs, y ##:: ys) =>
  315. G.apply3(ForestT1.traverse1(OneAnd(x, xs))(f), f(fa._2), ForestT1.traverse1(OneAnd(y, ys))(f)) {
  316. case (l, c, r) =>
  317. (l.head ##:: l.tail, c, r.head ##:: r.tail)
  318. }
  319. case (x ##:: xs, _) =>
  320. G.apply2(ForestT1.traverse1(OneAnd(x, xs))(f), f(fa._2)) {
  321. case (l, c) =>
  322. (l.head ##:: l.tail, c, EphemeralStream.emptyEphemeralStream)
  323. }
  324. case (_, x ##:: xs) =>
  325. G.apply2(f(fa._2), ForestT1.traverse1(OneAnd(x, xs))(f)) {
  326. case (c, r) =>
  327. (emptyEphemeralStream, c, r.head ##:: r.tail)
  328. }
  329. case (x, y) if (x.isEmpty && y.isEmpty) =>
  330. G.map(f(fa._2))(c => (emptyEphemeralStream, c, emptyEphemeralStream))
  331. }
  332. }
  333. override def foldMapRight1[A, B](fa: Parent[A])(z: A => B)(f: (A, => B) => B): B =
  334. ForestT.foldMapRight1Opt(fa._3)(z)(f) match {
  335. case Some(r) =>
  336. ForestT.foldRight(fa._1, f(fa._2, r))(f)
  337. case None =>
  338. ForestT.foldRight(fa._1, z(fa._2))(f)
  339. }
  340. }
  341. private[this] val ParentsT: Traverse[Parents] =
  342. Traverse[EStream].compose[Parent]
  343. private[this] val ParentsT1: Traverse1[Lambda[a => OneAnd[EStream, Parent[a]]]] =
  344. Traverse1[Lambda[a => OneAnd[EStream, a]]].compose[Parent]
  345. }
  346. implicit def treeLocEqual[A](implicit A: Equal[A]): Equal[TreeLoc[A]] =
  347. new TreeLocEqual[A] { def E = A }
  348. implicit def treeLocOrder[A](implicit A: Order[A]): Order[TreeLoc[A]] =
  349. new Order[TreeLoc[A]] with TreeLocEqual[A] {
  350. override def E: Order[A] = A
  351. import std.tuple._
  352. override def order(a: TreeLoc[A], b: TreeLoc[A]) =
  353. Divide[Order].dividing4(Function.unlift(TreeLoc.unapply[A])).order(a, b)
  354. }
  355. }
  356. object TreeLoc extends TreeLocInstances {
  357. type TreeForest[A] =
  358. EStream[Tree[A]]
  359. type Parent[A] =
  360. (TreeForest[A], A, TreeForest[A])
  361. type Parents[A] =
  362. EStream[Parent[A]]
  363. def loc[A](t: Tree[A], l: TreeForest[A], r: TreeForest[A], p: Parents[A]): TreeLoc[A] =
  364. TreeLoc(t, l, r, p)
  365. def fromForest[A](ts: TreeForest[A]): Option[TreeLoc[A]] = ts match {
  366. case (t ##:: ts) => Some(loc(t, emptyEphemeralStream, ts, emptyEphemeralStream))
  367. case _ => None
  368. }
  369. private def combChildren[A](ls: EStream[A], t: A, rs: EStream[A]) =
  370. ls.foldLeft(t ##:: rs)((a, b) => b ##:: a)
  371. @tailrec
  372. private def splitChildren[A](acc: EStream[A], xs: EStream[A], n: Int): Option[(EStream[A], EStream[A])] =
  373. (acc, xs, n) match {
  374. case (acc, xs, 0) => Some((acc, xs))
  375. case (acc, (x ##:: xs), n) => splitChildren(EphemeralStream.cons(x, acc), xs, n - 1)
  376. case _ => None
  377. }
  378. }
  379. private trait TreeLocEqual[A] extends Equal[TreeLoc[A]] {
  380. implicit def E: Equal[A]
  381. import std.tuple._
  382. override final def equal(a: TreeLoc[A], b: TreeLoc[A]) = {
  383. Equal[Tree[A]].equal(a.tree, b.tree) &&
  384. Equal[TreeForest[A]].equal(a.lefts, b.lefts) &&
  385. Equal[TreeForest[A]].equal(a.rights, b.rights) &&
  386. Equal[Parents[A]].equal(a.parents, b.parents)
  387. }
  388. }