PageRenderTime 54ms CodeModel.GetById 16ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 1ms

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