Guest User

Untitled

a guest
Dec 17th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.81 KB | None | 0 0
  1. sealed trait Tree[+A]
  2.  
  3. final case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
  4.  
  5. final case class Leaf[A](value: A) extends Tree[A]
  6.  
  7. implicit val treeMonad = new Monad[Tree] {
  8.  
  9. override def pure[A](value: A): Tree[A] = Leaf(value)
  10.  
  11. override def flatMap[A, B](initial: Tree[A])(func: A => Tree[B]): Tree[B] =
  12. initial match {
  13. case Branch(l, r) => Branch(flatMap(l)(func), flatMap(r)(func))
  14. case Leaf(value) => func(value)
  15. }
  16.  
  17. //@tailrec
  18. override def tailRecM[A, B](a: A)(func: (A) => Tree[Either[A, B]]): Tree[B] = {
  19. func(a) match {
  20. case Branch(l, r) =>
  21. Branch(
  22. flatMap(l) {
  23. case Right(l) => pure(l)
  24. case Left(l) => tailRecM(l)(func)
  25. },
  26. flatMap(r){
  27. case Right(r) => pure(r)
  28. case Left(r) => tailRecM(r)(func)
  29. }
  30. )
  31.  
  32. case Leaf(Left(value)) => tailRecM(value)(func)
  33.  
  34. case Leaf(Right(value)) => Leaf(value)
  35. }
  36. }
  37. }
  38.  
  39. override def tailRecM[A, B](a: A)(f: (A) => Tree[Either[A, B]]): Tree[B] = {
  40. @tailrec
  41. def go(toVisit: List[Tree[Either[A, B]]],
  42. toCollect: List[Tree[B]]): List[Tree[B]] = toVisit match {
  43. case (tree :: tail) =>
  44. tree match {
  45. case Branch(l, r) =>
  46. l match {
  47. case Branch(_, _) => go(l :: r :: tail, toCollect)
  48. case Leaf(Left(a)) => go(f(a) :: r :: tail, toCollect)
  49. case Leaf(Right(b)) => go(r :: tail, pure(b) +: toCollect)
  50. }
  51. case Leaf(Left(a)) => go(f(a) :: tail, toCollect)
  52. case Leaf(Right(b)) =>
  53. go(tail,
  54. if (toCollect.isEmpty) pure(b) +: toCollect
  55. else Branch(toCollect.head, pure(b)) :: toCollect.tail)
  56. }
  57. case Nil => toCollect
  58. }
  59.  
  60. go(f(a) :: Nil, Nil).head
  61. }
Add Comment
Please, Sign In to add comment