Advertisement
Guest User

Untitled

a guest
Apr 19th, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.26 KB | None | 0 0
  1. import scala.language.higherKinds
  2. import scala.language.implicitConversions
  3.  
  4. object monadHelper {
  5.  
  6. /////////////////////////////////////////////////////////////////////////////
  7.  
  8. // TODO: use standard monad library
  9.  
  10. trait Functor[M[_]] {
  11. def map[A, B](self: M[A], f: A => B): M[B]
  12. }
  13.  
  14. trait Monad[M[_]] extends Functor[M] {
  15. def unit[A](value: A): M[A]
  16. def flatMap[A, B](self: M[A], f: A => M[B]): M[B]
  17. }
  18.  
  19. implicit class MonadInterface[M[_], A](val self: M[A]) extends AnyVal {
  20. def map[B](f: A => B)(implicit m: Functor[M]): M[B] = m.map(self, f)
  21. def flatMap[B](f: A => M[B])(implicit m: Monad[M]): M[B] = m.flatMap(self, f)
  22. def foreach(f: A => Unit)(implicit m: Functor[M]) = map(f)
  23. }
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26.  
  27. }
  28.  
  29. object lazyMonad {
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32.  
  33. // minimal operational monad
  34.  
  35. sealed trait Opr[F[_], A]
  36. case class Pure[F[_], A](value: A) extends Opr[F, A]
  37. case class Bind[F[_], A, B](head: F[A], tail: A => Opr[F, B]) extends Opr[F, B]
  38.  
  39. object Opr {
  40. def apply[F[_], A](value: A): Opr[F, A] = Pure(value)
  41. def lift[F[_], A](from: F[A]): Opr[F, A] = bind(from) { (res: A) => Pure(res) }
  42. def bind[F[_], A, B](head: F[A])(tail: A => Opr[F, B]): Opr[F, B] = Bind(head, tail)
  43. }
  44.  
  45. /////////////////////////////////////////////////////////////////////////////
  46.  
  47. // Lazy implementation
  48.  
  49. sealed trait Lazy[+A] {
  50. def forceMemo: Option[A]
  51.  
  52. def isForced: Boolean = forceMemo.isDefined
  53.  
  54. def force: A = forceMemo match {
  55. case Some(memo) => memo
  56. case None => {
  57. var cont: Opr[Lazy, A] = Opr.lift(this)
  58. while (true) {
  59. cont match {
  60. case Pure(value) => return value
  61. case Bind(head, tail) => head.forceMemo match {
  62. case None => cont = head.forceImpl(tail)
  63. case Some(memo) => cont = tail(memo)
  64. }
  65. }
  66. }
  67. ??? // TODO: report proper exception
  68. }
  69. }
  70.  
  71. def forceImpl[R](cont: A => Opr[Lazy, R]): Opr[Lazy, R]
  72.  
  73. override def toString: String = {
  74. if (isForced) {
  75. s"Lazy(${force.toString})"
  76. } else {
  77. "Lazy(#)"
  78. }
  79. }
  80. }
  81.  
  82. case class SimpleLazy[A](promise: () => A) extends Lazy[A] {
  83. var forceMemo: Option[A] = None
  84.  
  85. def forceImpl[R](cont: A => Opr[Lazy, R]): Opr[Lazy, R] = {
  86. val result = promise()
  87. forceMemo = Some(result)
  88. cont(result)
  89. }
  90. }
  91.  
  92. case class MappedLazy[A, B](head: Lazy[A], tail: A => Lazy[B]) extends Lazy[B] {
  93. var forceMemo: Option[B] = None
  94.  
  95. def forceImpl[R](cont: B => Opr[Lazy, R]): Opr[Lazy, R] = {
  96. Opr.bind(head) { (mid: A) =>
  97. Opr.bind(tail(mid)) { (res: B) =>
  98. forceMemo = Some(res)
  99. cont(res)
  100. }
  101. }
  102. }
  103. }
  104.  
  105. object Lazy {
  106. def apply[A](promise: => Lazy[A]): Lazy[A] = SimpleLazy(() => promise).join
  107. def unit[A](value: => A): Lazy[A] = SimpleLazy(() => value)
  108. }
  109.  
  110. implicit class LazyInterface[A](val self: Lazy[A]) extends AnyVal {
  111. def map[B](f: A => B): Lazy[B] = flatMap { (a: A) =>
  112. val b: B = f(a)
  113. Lazy.unit(b)
  114. }
  115.  
  116. def flatMap[B](f: A => Lazy[B]): Lazy[B] = MappedLazy(self, f)
  117. }
  118.  
  119. // implicit def makeLazy[A](promise: => A): Lazy[A] = SimpleLazy(() => promise)
  120.  
  121. trait LazyFamily[A] {
  122. def join(nested: Lazy[A]): A
  123. }
  124.  
  125. implicit def joinImplForLazy[A]: LazyFamily[Lazy[A]] = new LazyFamily[Lazy[A]] {
  126. def join(nested: Lazy[Lazy[A]]): Lazy[A] = nested.flatMap(a => a)
  127. }
  128.  
  129. implicit class LazyInterface2[A](val self: Lazy[A]) extends AnyVal {
  130. def join(implicit impl: LazyFamily[A]): A = impl.join(self)
  131. }
  132.  
  133. /////////////////////////////////////////////////////////////////////////////
  134.  
  135. }
  136.  
  137. object lazyList {
  138. // usage example
  139.  
  140. import lazyMonad._
  141. import monadHelper._
  142.  
  143. /////////////////////////////////////////////////////////////////////////////
  144.  
  145. implicit val lazyMonadInstance: Monad[Lazy] = new Monad[Lazy] {
  146. def unit[A](value: A) = Lazy.unit(value)
  147. def map[A, B](self: Lazy[A], f: A => B): Lazy[B] = self.map(f)
  148. def flatMap[A, B](self: Lazy[A], f: A => Lazy[B]): Lazy[B] = self.flatMap(f)
  149. }
  150.  
  151. /////////////////////////////////////////////////////////////////////////////
  152.  
  153. trait ListF[+A, +R]
  154. case object NullF extends ListF[Nothing, Nothing]
  155. case class ConsF[A, R](head: A, tail: R) extends ListF[A, R]
  156.  
  157. class LazyList[+A](val impl: Lazy[ListF[A, LazyList[A]]]) /* extends AnyVal */ {
  158. override def toString: String = impl.toString
  159. }
  160.  
  161. val LazyNull: LazyList[Nothing] = new LazyList(Lazy.unit(NullF))
  162.  
  163. implicit def joinImplForLazyList[A]: LazyFamily[LazyList[A]] = new LazyFamily[LazyList[A]] {
  164. def join(nested: Lazy[LazyList[A]]): LazyList[A] = new LazyList(nested.flatMap(_.impl))
  165. }
  166.  
  167. implicit class LazyListInterface[A](val self: LazyList[A]) extends AnyVal {
  168. def demolish[R](caseNull: => R)(caseCons: (A, LazyList[A]) => R): Lazy[R] = {
  169. self.impl.map { (impl: ListF[A, LazyList[A]]) =>
  170. impl match {
  171. case NullF => caseNull
  172. case ConsF(head, tail) => caseCons(head, tail)
  173. }
  174. }
  175. }
  176. def #::[AA >: A](head: => AA): LazyList[AA] = new LazyList(Lazy.unit(ConsF(head, self)))
  177. def isEmpty: Boolean = demolish(true) { (_: A, _: LazyList[A]) => false }.force
  178. def isNonEmpty: Boolean = !isEmpty
  179. def head: A = demolish(???) { (h: A, _: LazyList[A]) => h }.force
  180. def tail: LazyList[A] = demolish(???) { (_: A, t: LazyList[A]) => t }.force
  181. def foldRight[R](init: R)(f: (A, R) => R): Lazy[R] = self.demolish(Lazy.unit(init)) { (h: A, t: LazyList[A]) => t.foldRight(init)(f).map(tt => f(h, tt)) }.flatMap(a => a)
  182. def zip[B](that: LazyList[B]): LazyList[(A, B)] = demolish[LazyList[(A, B)]](LazyNull) { (h1: A, t1: LazyList[A]) => that.demolish[LazyList[(A, B)]](LazyNull) { (h2: B, t2: LazyList[B]) => (h1, h2) #:: t1.zip(t2) }.join }.join
  183. def map[B](f: A => B): LazyList[B] = demolish[LazyList[B]](LazyNull) { (h: A, t: LazyList[A]) => f(h) #:: new LazyListInterface(t).map(f) }.join
  184. def take(n: Int): LazyList[A] = {
  185. if (n <= 0) { LazyNull } else { demolish[LazyList[A]](LazyNull) { (h: A, t: LazyList[A]) => h #:: t.take(n - 1) }.join }
  186. }
  187. }
  188.  
  189. object LazyList {
  190. def apply[A](elems: Lazy[A]*): LazyList[A] = {
  191. lazy val loop: (Int) => LazyList[A] = { (i: Int) =>
  192. if (i >= elems.length) {
  193. LazyNull
  194. } else {
  195. elems(i).map(_ #:: loop(i + 1)).join
  196. }
  197. }
  198. loop(0)
  199. }
  200. }
  201.  
  202. /////////////////////////////////////////////////////////////////////////////
  203.  
  204. }
  205.  
  206. object main {
  207. import lazyMonad._
  208. import lazyList._
  209.  
  210. /////////////////////////////////////////////////////////////////////////////
  211.  
  212. lazy val fibs: LazyList[Int] = 0 #:: 1 #:: Lazy.unit {
  213. fibs.zip(fibs.tail).map { case (a, b) => a + b }
  214. }.join
  215.  
  216. lazy val nats: LazyList[Int] = 0 #:: Lazy.unit(nats.map(_ + 1)).join
  217.  
  218. def main(args: Array[String]) = {
  219. // calculations are cached
  220. println(s"fibs: $fibs")
  221. println(s"fibs.take(20).sum: ${fibs.take(20).foldRight(0)(_ + _).force}")
  222. println(s"fibs: $fibs")
  223. // deep recursion does not cause stack overflow
  224. println(s"nats.take(10^6).sum: ${nats.take(1000000).foldRight(0)(_ + _).force}")
  225. }
  226.  
  227. /////////////////////////////////////////////////////////////////////////////
  228.  
  229. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement