/core/src/main/scala/scalaz/Tree.scala

http://github.com/scalaz/scalaz · Scala · 302 lines · 220 code · 49 blank · 33 comment · 14 complexity · f1a9f36890af4cbfec879a128a48b267 MD5 · raw file

  1. package scalaz
  2. import scalaz.Free.Trampoline
  3. import scalaz.Trampoline._
  4. import scalaz.EphemeralStream._
  5. /**
  6. * A multi-way tree, also known as a rose tree. Also known as Cofree[Stream, A].
  7. */
  8. sealed abstract class Tree[A] {
  9. import Tree._
  10. /** The label at the root of this tree. */
  11. def rootLabel: A
  12. /** The child nodes of this tree. */
  13. def subForest: EStream[Tree[A]]
  14. def foldMapTrampoline[B: Monoid](f: A => B): Trampoline[B] = {
  15. for {
  16. root <- delay(f(rootLabel))
  17. subForests <- Foldable[EStream].foldMap[Tree[A], Trampoline[B]](subForest)(_.foldMapTrampoline(f))
  18. } yield Monoid[B].append(root, subForests)
  19. }
  20. /** Maps the elements of the Tree into a Monoid and folds the resulting Tree. */
  21. def foldMap[B: Monoid](f: A => B): B =
  22. foldMapTrampoline[B](f).run
  23. def foldRight[B](z: => B)(f: (A, => B) => B): B =
  24. Foldable[EStream].foldRight(flatten, z)(f)
  25. /** A 2D String representation of this Tree. */
  26. def drawTree(implicit sh: Show[A]): String = {
  27. val reversedLines = draw.run
  28. val first = new StringBuilder(reversedLines.head.toString.reverse)
  29. val rest = reversedLines.tail
  30. rest.foldLeft(first) { (acc, elem) =>
  31. acc.append("\n").append(elem.toString.reverse)
  32. }.append("\n").toString
  33. }
  34. /** A histomorphic transform. Each element in the resulting tree
  35. * is a function of the corresponding element in this tree
  36. * and the histomorphic transform of its children.
  37. **/
  38. def scanr[B](g: (A, EStream[Tree[B]]) => B): Tree[B] = {
  39. val c = Need(subForest.map(_.scanr(g)))
  40. Node(g(rootLabel, c.value), c.value)
  41. }
  42. /** A 2D String representation of this Tree, separated into lines.
  43. * Uses reversed StringBuilders for performance, because they are
  44. * prepended to.
  45. **/
  46. private def draw(implicit sh: Show[A]): Trampoline[Vector[StringBuilder]] = {
  47. import Trampoline._
  48. val branch = " -+" // "+- ".reverse
  49. val stem = " -`" // "`- ".reverse
  50. val trunk = " |" // "| ".reverse
  51. def drawSubTrees(s: EStream[Tree[A]]): Trampoline[Vector[StringBuilder]] = s match {
  52. case ts if ts.isEmpty =>
  53. done(Vector.empty[StringBuilder])
  54. case t ##:: ts if ts.isEmpty =>
  55. suspend(t.draw).map(subtree => new StringBuilder("|") +: shift(stem, " ", subtree))
  56. case t ##:: ts => for {
  57. subtree <- suspend(t.draw)
  58. otherSubtrees <- suspend(drawSubTrees(ts))
  59. } yield new StringBuilder("|") +: (shift(branch, trunk, subtree) ++ otherSubtrees)
  60. }
  61. def shift(first: String, other: String, s: Vector[StringBuilder]): Vector[StringBuilder] = {
  62. var i = 0
  63. while (i < s.length) {
  64. if (i == 0) s(i).append(first)
  65. else s(i).append(other)
  66. i += 1
  67. }
  68. s
  69. }
  70. drawSubTrees(subForest).map { subtrees =>
  71. new StringBuilder(sh.shows(rootLabel).reverse) +: subtrees
  72. }
  73. }
  74. /** Pre-order traversal. */
  75. def flatten: EStream[A] = {
  76. def squish(tree: Tree[A], xs: EStream[A]): EStream[A] =
  77. EphemeralStream.cons(tree.rootLabel, Foldable[EStream].foldRight(tree.subForest, xs)(squish(_, _)))
  78. squish(this, EphemeralStream.emptyEphemeralStream)
  79. }
  80. /** Breadth-first traversal. */
  81. def levels: EStream[EStream[A]] = {
  82. val f = (s: EStream[Tree[A]]) => {
  83. Foldable[EStream].foldMap(s)((_: Tree[A]).subForest)
  84. }
  85. EphemeralStream.iterate(EphemeralStream(this))(f) takeWhile (!_.isEmpty) map (_ map (_.rootLabel))
  86. }
  87. def toStrictTree: StrictTree[A] = {
  88. import std.vector.vectorInstance
  89. def trampolined(t: Tree[A]): Trampoline[StrictTree[A]] = {
  90. t match {
  91. case Tree.Leaf(root) =>
  92. Trampoline.done(StrictTree.Leaf(root))
  93. case Tree.Node(root, forest) =>
  94. for {
  95. strictForest <- Trampoline.suspend(Applicative[Trampoline].traverse(forest.toIList.toVector)(trampolined))
  96. } yield StrictTree(root, strictForest)
  97. }
  98. }
  99. trampolined(this).run
  100. }
  101. /** Binds the given function across all the subtrees of this tree. */
  102. def cobind[B](f: Tree[A] => B): Tree[B] = unfoldTree(this)(t => (f(t), () => t.subForest))
  103. /** A TreeLoc zipper of this tree, focused on the root node. */
  104. def loc: TreeLoc[A] = TreeLoc.loc(this, emptyEphemeralStream, emptyEphemeralStream, emptyEphemeralStream)
  105. /** Turns a tree of pairs into a pair of trees. */
  106. def unzip[A1, A2](p: A => (A1, A2)): (Tree[A1], Tree[A2]) = {
  107. val uz = Need(subForest.map(_.unzip(p)))
  108. val fst = Need(uz.value map (_._1))
  109. val snd = Need(uz.value map (_._2))
  110. val (a, b) = p(rootLabel)
  111. (Node(a, fst.value), Node(b, snd.value))
  112. }
  113. def foldNode[Z](f: A => EStream[Tree[A]] => Z): Z =
  114. f(rootLabel)(subForest)
  115. def map[B](f: A => B): Tree[B] =
  116. Node(f(rootLabel), subForest map (_ map f))
  117. def flatMap[B](f: A => Tree[B]): Tree[B] = {
  118. val r: Tree[B] = f(rootLabel)
  119. Node(r.rootLabel, r.subForest ++ subForest.map(_.flatMap(f)))
  120. }
  121. def traverse1[G[_] : Apply, B](f: A => G[B]): G[Tree[B]] = {
  122. val G = Apply[G]
  123. import EphemeralStream._
  124. std.boolean.fold(subForest.isEmpty,
  125. G.map(f(rootLabel))(Leaf(_)),
  126. G.apply2 (f(rootLabel),
  127. (OneAnd.oneAndTraverse[EStream]
  128. .traverse1
  129. (OneAnd(
  130. subForest.headOption.get, subForest.tailOption.get))
  131. (_.traverse1(f))))
  132. { case (h, t) => Node(h, t.head ##:: t.tail) }
  133. )
  134. }
  135. }
  136. sealed abstract class TreeInstances {
  137. implicit val treeInstance: Traverse1[Tree] with Monad[Tree] with Comonad[Tree] with Align[Tree] with Zip[Tree] = new Traverse1[Tree] with Monad[Tree] with Comonad[Tree] with Align[Tree] with Zip[Tree] {
  138. def point[A](a: => A): Tree[A] = Tree.Leaf(a)
  139. def cobind[A, B](fa: Tree[A])(f: Tree[A] => B): Tree[B] = fa cobind f
  140. def copoint[A](p: Tree[A]): A = p.rootLabel
  141. override def map[A, B](fa: Tree[A])(f: A => B) = fa map f
  142. def bind[A, B](fa: Tree[A])(f: A => Tree[B]): Tree[B] = fa flatMap f
  143. def traverse1Impl[G[_]: Apply, A, B](fa: Tree[A])(f: A => G[B]): G[Tree[B]] = fa traverse1 f
  144. override def foldRight[A, B](fa: Tree[A], z: => B)(f: (A, => B) => B): B = fa.foldRight(z)(f)
  145. override def foldMapRight1[A, B](fa: Tree[A])(z: A => B)(f: (A, => B) => B) = (fa.flatten.reverse: @unchecked) match {
  146. case h ##:: t => t.foldLeft(z(h))((b, a) => f(a, b))
  147. }
  148. override def foldLeft[A, B](fa: Tree[A], z: B)(f: (B, A) => B): B =
  149. fa.flatten.foldLeft(z)((b, a) => f(b, a))
  150. override def foldMapLeft1[A, B](fa: Tree[A])(z: A => B)(f: (B, A) => B): B = fa.flatten match {
  151. case h ##:: t => t.foldLeft(z(h))((b, a) => f(b, a))
  152. }
  153. override def foldMap[A, B](fa: Tree[A])(f: A => B)(implicit F: Monoid[B]): B = fa foldMap f
  154. def alignWith[A, B, C](f: (\&/[A, B]) => C) = {
  155. def align(ta: Tree[A], tb: Tree[B]): Tree[C] =
  156. Tree.Node(f(\&/(ta.rootLabel, tb.rootLabel)), Align[EStream].alignWith[Tree[A], Tree[B], Tree[C]]({
  157. case \&/.This(sta) => sta map {a => f(\&/.This(a))}
  158. case \&/.That(stb) => stb map {b => f(\&/.That(b))}
  159. case \&/(sta, stb) => align(sta, stb)
  160. })(ta.subForest, tb.subForest))
  161. align
  162. }
  163. def zip[A, B](aa: => Tree[A], bb: => Tree[B]) = {
  164. val a = aa
  165. val b = bb
  166. Tree.Node(
  167. (a.rootLabel, b.rootLabel),
  168. Zip[EStream].zipWith(a.subForest, b.subForest)(zip(_, _))
  169. )
  170. }
  171. }
  172. implicit def treeEqual[A](implicit A0: Equal[A]): Equal[Tree[A]] =
  173. new TreeEqual[A] { def A = A0 }
  174. implicit def treeOrder[A](implicit A0: Order[A]): Order[Tree[A]] =
  175. new Order[Tree[A]] with TreeEqual[A] {
  176. override def A: Order[A] = A0
  177. override def order(x: Tree[A], y: Tree[A]) =
  178. A.order(x.rootLabel, y.rootLabel) match {
  179. case Ordering.EQ =>
  180. Order[EStream[Tree[A]]].order(x.subForest, y.subForest)
  181. case x => x
  182. }
  183. }
  184. /* TODO
  185. def applic[A, B](f: Tree[A => B]) = a => Tree.node((f.rootLabel)(a.rootLabel), implicitly[Applic[newtypes.ZipStream]].applic(f.subForest.map(applic[A, B](_)).ʐ)(a.subForest ʐ).value)
  186. */
  187. }
  188. object Tree extends TreeInstances {
  189. /**
  190. * Node represents a tree node that may have children.
  191. *
  192. * You can use Node for tree construction or pattern matching.
  193. */
  194. object Node {
  195. def apply[A](root: => A, forest: => EStream[Tree[A]]): Tree[A] = {
  196. new Tree[A] {
  197. private[this] val rootc = Need(root)
  198. private[this] val forestc = Need(forest)
  199. def rootLabel = rootc.value
  200. def subForest = forestc.value
  201. override def toString = "<tree>"
  202. }
  203. }
  204. def unapply[A](t: Tree[A]): Option[(A, EStream[Tree[A]])] = Some((t.rootLabel, t.subForest))
  205. }
  206. /**
  207. * Leaf represents a tree node with no children.
  208. *
  209. * You can use Leaf for tree construction or pattern matching.
  210. */
  211. object Leaf {
  212. def apply[A](root: => A): Tree[A] = {
  213. Node(root, EphemeralStream.emptyEphemeralStream)
  214. }
  215. def unapply[A](t: Tree[A]): Option[A] = {
  216. t match {
  217. case Node(root, xs) if xs.isEmpty =>
  218. Some(root)
  219. case _ =>
  220. None
  221. }
  222. }
  223. }
  224. def unfoldForest[A, B](s: EStream[A])(f: A => (B, () => EStream[A])): EStream[Tree[B]] =
  225. s.map(unfoldTree(_)(f))
  226. def unfoldTree[A, B](v: A)(f: A => (B, () => EStream[A])): Tree[B] =
  227. f(v) match {
  228. case (a, bs) => Node(a, unfoldForest(bs.apply())(f))
  229. }
  230. }
  231. private trait TreeEqual[A] extends Equal[Tree[A]] {
  232. def A: Equal[A]
  233. override final def equal(a1: Tree[A], a2: Tree[A]) = {
  234. def corresponds[B](a1: EStream[Tree[A]], a2: EStream[Tree[A]]): Trampoline[Boolean] = {
  235. (a1.isEmpty, a2.isEmpty) match {
  236. case (true, true) => Trampoline.done(true)
  237. case (_, true) | (true, _) => Trampoline.done(false)
  238. case _ =>
  239. for {
  240. heads <- trampolined(a1.headOption.get, a2.headOption.get)
  241. tails <- corresponds(a1.tailOption.get, a2.tailOption.get)
  242. } yield heads && tails
  243. }
  244. }
  245. def trampolined(a1: Tree[A], a2: Tree[A]): Trampoline[Boolean] = {
  246. for {
  247. roots <- Trampoline.done(A.equal(a1.rootLabel, a2.rootLabel))
  248. subForests <- corresponds(a1.subForest, a2.subForest)
  249. } yield roots && subForests
  250. }
  251. trampolined(a1, a2).run
  252. }
  253. }