Guest User

Untitled

a guest
Dec 14th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.95 KB | None | 0 0
  1. package org.bykn.list
  2.  
  3. import cats.Applicative
  4.  
  5. import cats.implicits._
  6.  
  7. /**
  8. * Implementation of "Purely Functional Random Access Lists" by Chris Okasaki.
  9. * This gives O(1) cons and uncons, and 2 log_2 N lookup.
  10. */
  11. sealed abstract class TreeList[+A] {
  12. def uncons: Option[(A, TreeList[A])]
  13. def cons[A1 >: A](a1: A1): TreeList[A1]
  14. def get(idx: Long): Option[A]
  15. def size: Long
  16. def foldLeft[B](init: B)(fn: (B, A) => B): B
  17. def foldRight[B](fin: B)(fn: (A, B) => B): B
  18. def map[B](fn: A => B): TreeList[B]
  19. def drop(n: Long): TreeList[A]
  20.  
  21. /**
  22. * Split the list roughly in half
  23. */
  24. def split: (TreeList[A], TreeList[A])
  25.  
  26. def ::[A1 >: A](a1: A1): TreeList[A1] = cons(a1)
  27.  
  28. override def toString: String = {
  29. val strb = new java.lang.StringBuilder
  30. strb.append("TreeList(")
  31. def loop(first: Boolean, l: TreeList[A]): Unit =
  32. l.uncons match {
  33. case None => ()
  34. case Some((h, t)) =>
  35. if (!first) strb.append(", ")
  36. strb.append(h.toString)
  37. loop(false, t)
  38. }
  39.  
  40. loop(true, this)
  41. strb.append(")")
  42. strb.toString
  43. }
  44. }
  45.  
  46. object TreeList {
  47. sealed trait Nat {
  48. def value: Int
  49. }
  50. sealed abstract class NatEq[A <: Nat, B <: Nat] {
  51. def subst[F[_ <: Nat]](f: F[A]): F[B]
  52. }
  53. object NatEq {
  54. implicit def refl[A <: Nat]: NatEq[A, A] =
  55. new NatEq[A, A] {
  56. def subst[F[_ <: Nat]](f: F[A]): F[A] = f
  57. }
  58. }
  59.  
  60. object Nat {
  61. case class Succ[P <: Nat](prev: P) extends Nat {
  62. val value: Int = prev.value + 1
  63. }
  64. case object Zero extends Nat {
  65. def value: Int = 0
  66. }
  67.  
  68. def maybeEq[N1 <: Nat, N2 <: Nat](n1: N1, n2: N2): Option[NatEq[N1, N2]] =
  69. // I don't see how to prove this in scala, but it is true
  70. if (n1.value == n2.value) Some(NatEq.refl[N1].asInstanceOf[NatEq[N1, N2]])
  71. else None
  72. }
  73. sealed abstract class Tree[+N <: Nat, +A] {
  74. def value: A
  75. def depth: N
  76. def size: Long // this is 2^(depth + 1) - 1
  77. def get(idx: Long): Option[A]
  78. def map[B](fn: A => B): Tree[N, B]
  79. def foldRight[B](fin: B)(fn: (A, B) => B): B
  80. }
  81. case class Root[A](value: A) extends Tree[Nat.Zero.type, A] {
  82. def depth: Nat.Zero.type = Nat.Zero
  83. def size = 1L
  84. def get(idx: Long): Option[A] =
  85. if(idx == 0L) Some(value) else None
  86.  
  87. def map[B](fn: A => B) = Root(fn(value))
  88. def foldRight[B](fin: B)(fn: (A, B) => B): B = fn(value, fin)
  89. }
  90. case class Balanced[N <: Nat, A](value: A, left: Tree[N, A], right: Tree[N, A]) extends Tree[Nat.Succ[N], A] {
  91. val depth: Nat.Succ[N] = Nat.Succ(left.depth)
  92. val size = 1L + left.size + right.size
  93. def get(idx: Long): Option[A] =
  94. if (idx == 0L) Some(value)
  95. else if (idx <= left.size) left.get(idx - 1)
  96. else right.get(idx - (left.size + 1))
  97.  
  98. def map[B](fn: A => B) = Balanced[N, B](fn(value), left.map(fn), right.map(fn))
  99. def foldRight[B](fin: B)(fn: (A, B) => B): B = {
  100. val rightB = right.foldRight(fin)(fn)
  101. val leftB = left.foldRight(rightB)(fn)
  102. fn(value, leftB)
  103. }
  104. }
  105.  
  106. def traverseTree[F[_]: Applicative, A, B, N <: Nat](ta: Tree[N, A], fn: A => F[B]): F[Tree[N, B]] =
  107. ta match {
  108. case Root(a) => fn(a).map(Root(_))
  109. case Balanced(a, left, right) =>
  110. (fn(a), traverseTree(left, fn), traverseTree(right, fn)).mapN { (b, l, r) =>
  111. Balanced(b, l, r)
  112. }
  113. }
  114.  
  115. private case class Trees[A](treeList: List[Tree[Nat, A]]) extends TreeList[A] {
  116. def cons[A1 >: A](a1: A1): TreeList[A1] =
  117. treeList match {
  118. case h1 :: h2 :: rest =>
  119. def go[N1 <: Nat, N2 <: Nat, A2 <: A](t1: Tree[N1, A2], t2: Tree[N2, A2]): TreeList[A1] =
  120. Nat.maybeEq[N1, N2](t1.depth, t2.depth) match {
  121. case Some(eqv) =>
  122. type T[N <: Nat] = Tree[N, A2]
  123. Trees(Balanced[N2, A1](a1, eqv.subst[T](t1), t2) :: rest)
  124. case None =>
  125. Trees(Root(a1) :: treeList)
  126. }
  127. go(h1, h2)
  128. case lessThan2 => Trees(Root(a1) :: lessThan2)
  129. }
  130. def uncons: Option[(A, TreeList[A])] =
  131. treeList match {
  132. case Nil => None
  133. case Root(a) :: rest => Some((a, Trees(rest)))
  134. case Balanced(a, l, r) :: rest => Some((a, Trees(l :: r :: rest)))
  135. }
  136.  
  137. def get(idx: Long): Option[A] = {
  138. @annotation.tailrec
  139. def loop(idx: Long, treeList: List[Tree[Nat, A]]): Option[A] =
  140. if (idx < 0L) None
  141. else
  142. treeList match {
  143. case Nil => None
  144. case h :: tail =>
  145. if (h.size <= idx) loop(idx - h.size, tail)
  146. else h.get(idx)
  147. }
  148.  
  149. loop(idx, treeList)
  150. }
  151.  
  152. def size: Long = {
  153. @annotation.tailrec
  154. def loop(treeList: List[Tree[Nat, A]], acc: Long): Long =
  155. treeList match {
  156. case Nil => acc
  157. case h :: tail => loop(tail, acc + h.size)
  158. }
  159. loop(treeList, 0L)
  160. }
  161.  
  162. def foldLeft[B](init: B)(fn: (B, A) => B): B = {
  163. @annotation.tailrec
  164. def loop(init: B, rest: List[Tree[Nat, A]]): B =
  165. rest match {
  166. case Nil => init
  167. case Root(a) :: tail => loop(fn(init, a), tail)
  168. case Balanced(a, l, r) :: rest => loop(fn(init, a), l :: r :: rest)
  169. }
  170.  
  171. loop(init, treeList)
  172. }
  173.  
  174. def foldRight[B](fin: B)(fn: (A, B) => B): B =
  175. treeList.reverse.foldLeft(fin) { (b, treea) =>
  176. treea.foldRight(b)(fn)
  177. }
  178.  
  179. def map[B](fn: A => B) = Trees(treeList.map(_.map(fn)))
  180.  
  181. def drop(n: Long): TreeList[A] = {
  182. @annotation.tailrec
  183. def loop(n: Long, treeList: List[Tree[Nat, A]]): TreeList[A] =
  184. treeList match {
  185. case Nil => empty
  186. case _ if n == 0L => Trees(treeList)
  187. case h :: tail =>
  188. if (h.size <= n) loop(n - h.size, tail)
  189. else {
  190. h match {
  191. case Root(_) =>
  192. loop(n - 1, tail)
  193. case Balanced(a, l, r) =>
  194. if (n > l.size + 1L) loop(n - l.size - 1L, r :: tail)
  195. else if (n > 1L) loop(n - 1L, l :: r :: tail)
  196. else Trees(l :: r :: tail)
  197. }
  198. }
  199. }
  200.  
  201. loop(n, treeList)
  202. }
  203.  
  204. def split: (TreeList[A], TreeList[A]) =
  205. treeList match {
  206. case Nil => (empty, empty)
  207. case Root(_) :: Nil => (this, empty)
  208. case Balanced(a, l, r) :: Nil => (Trees(Root(a) :: l :: Nil), Trees(r :: Nil))
  209. case moreThanOne => (Trees(moreThanOne.init), Trees(moreThanOne.last :: Nil))
  210. }
  211. }
  212.  
  213. implicit class InvariantTreeList[A](val treeList: TreeList[A]) extends AnyVal {
  214. def traverse[F[_]: Applicative, B](fn: A => F[B]): F[TreeList[B]] =
  215. treeList match {
  216. case Trees(tls) => tls.traverse { tree => traverseTree(tree, fn) }.map(Trees(_))
  217. }
  218. }
  219.  
  220. val empty: TreeList[Nothing] = Trees[Nothing](Nil)
  221.  
  222. def fromList[A](list: List[A]): TreeList[A] = {
  223. def loop(rev: List[A], acc: TreeList[A]): TreeList[A] =
  224. rev match {
  225. case Nil => acc
  226. case h :: tail => loop(tail, acc.cons(h))
  227. }
  228.  
  229. loop(list.reverse, empty)
  230. }
  231. }
Add Comment
Please, Sign In to add comment