From 086495251013d76420f361de3d995d9eb0465b9e Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Tue, 19 Jan 2016 00:50:37 +0100 Subject: [PATCH 1/5] cats#813 - Adds CoflatMap type class to the Vector Instance --- core/src/main/scala/cats/std/vector.scala | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/std/vector.scala b/core/src/main/scala/cats/std/vector.scala index 88d9797ceb..c1d496eee6 100644 --- a/core/src/main/scala/cats/std/vector.scala +++ b/core/src/main/scala/cats/std/vector.scala @@ -4,9 +4,13 @@ package std import cats.data.Streaming import cats.syntax.show._ +import scala.annotation.tailrec +import scala.collection.+: +import scala.collection.mutable.{ArrayBuffer, ListBuffer} + trait VectorInstances { - implicit val vectorInstance: Traverse[Vector] with MonadCombine[Vector] = - new Traverse[Vector] with MonadCombine[Vector] { + implicit val vectorInstance: Traverse[Vector] with MonadCombine[Vector] with CoflatMap[Vector] = + new Traverse[Vector] with MonadCombine[Vector] with CoflatMap[Vector] { def empty[A]: Vector[A] = Vector.empty[A] @@ -23,6 +27,15 @@ trait VectorInstances { override def map2[A, B, Z](fa: Vector[A], fb: Vector[B])(f: (A, B) => Z): Vector[Z] = fa.flatMap(a => fb.map(b => f(a, b))) + def coflatMap[A, B](fa: Vector[A])(f: Vector[A] => B): Vector[B] = { + @tailrec def loop(buf: ArrayBuffer[B], as: Vector[A]): Vector[B] = + as match { + case _ +: rest => loop(buf += f(as), rest) + case _ => buf.to[Vector] + } + loop(ArrayBuffer.empty[B], fa) + } + def foldLeft[A, B](fa: Vector[A], b: B)(f: (B, A) => B): B = fa.foldLeft(b)(f) From 5d8750642e0c22ccdf95c3ce963b42dccc0dd130 Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Tue, 19 Jan 2016 00:51:25 +0100 Subject: [PATCH 2/5] cats#813 - Provides CoflatMap tests for VectorTests --- tests/src/test/scala/cats/tests/VectorTests.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/src/test/scala/cats/tests/VectorTests.scala b/tests/src/test/scala/cats/tests/VectorTests.scala index 423e101a15..a15b6c2020 100644 --- a/tests/src/test/scala/cats/tests/VectorTests.scala +++ b/tests/src/test/scala/cats/tests/VectorTests.scala @@ -1,13 +1,17 @@ package cats package tests -import cats.laws.discipline.{MonadCombineTests, SerializableTests, TraverseTests, MonoidalTests} +import cats.laws.discipline.{MonadCombineTests, CoflatMapTests, SerializableTests, TraverseTests, MonoidalTests} import cats.laws.discipline.eq.tuple3Eq class VectorTests extends CatsSuite { + checkAll("Vector[Int]", MonoidalTests[Vector].monoidal[Int, Int, Int]) checkAll("Monoidal[Vector]", SerializableTests.serializable(Monoidal[Vector])) + checkAll("Vector[Int]", CoflatMapTests[Vector].coflatMap[Int, Int, Int]) + checkAll("CoflatMap[Vector]", SerializableTests.serializable(CoflatMap[Vector])) + checkAll("Vector[Int]", MonadCombineTests[Vector].monadCombine[Int, Int, Int]) checkAll("MonadCombine[Vector]", SerializableTests.serializable(MonadCombine[Vector])) From 4da172f83ba00973a828be145bdf62ca02c9b8a8 Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Tue, 19 Jan 2016 11:51:58 +0100 Subject: [PATCH 3/5] cats#813 - Removes non-necessary import --- core/src/main/scala/cats/std/vector.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/std/vector.scala b/core/src/main/scala/cats/std/vector.scala index c1d496eee6..28df6c2946 100644 --- a/core/src/main/scala/cats/std/vector.scala +++ b/core/src/main/scala/cats/std/vector.scala @@ -6,7 +6,7 @@ import cats.syntax.show._ import scala.annotation.tailrec import scala.collection.+: -import scala.collection.mutable.{ArrayBuffer, ListBuffer} +import scala.collection.mutable.ArrayBuffer trait VectorInstances { implicit val vectorInstance: Traverse[Vector] with MonadCombine[Vector] with CoflatMap[Vector] = From c20f6ed73d9df6500224823a447e09731d861a48 Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Tue, 19 Jan 2016 15:53:37 +0100 Subject: [PATCH 4/5] cats#813 - Changes the coflatMap implementation in order to use ListBuffer instead of ArrayBuffer --- core/src/main/scala/cats/std/vector.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/std/vector.scala b/core/src/main/scala/cats/std/vector.scala index 28df6c2946..b7cb2ba76b 100644 --- a/core/src/main/scala/cats/std/vector.scala +++ b/core/src/main/scala/cats/std/vector.scala @@ -6,7 +6,7 @@ import cats.syntax.show._ import scala.annotation.tailrec import scala.collection.+: -import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.ListBuffer trait VectorInstances { implicit val vectorInstance: Traverse[Vector] with MonadCombine[Vector] with CoflatMap[Vector] = @@ -28,12 +28,12 @@ trait VectorInstances { fa.flatMap(a => fb.map(b => f(a, b))) def coflatMap[A, B](fa: Vector[A])(f: Vector[A] => B): Vector[B] = { - @tailrec def loop(buf: ArrayBuffer[B], as: Vector[A]): Vector[B] = + @tailrec def loop(buf: ListBuffer[B], as: Vector[A]): Vector[B] = as match { case _ +: rest => loop(buf += f(as), rest) case _ => buf.to[Vector] } - loop(ArrayBuffer.empty[B], fa) + loop(ListBuffer.empty[B], fa) } def foldLeft[A, B](fa: Vector[A], b: B)(f: (B, A) => B): B = From 7ee5f2fe56879beffa0ffb868f5fd62b6f4d858b Mon Sep 17 00:00:00 2001 From: Juan Pedro Moreno Date: Tue, 19 Jan 2016 19:55:10 +0100 Subject: [PATCH 5/5] cats#813 - Addresses a code review comment, changing the coflatMap implementation in order to use VectorBuilder instead of ListBuffer --- core/src/main/scala/cats/std/vector.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/scala/cats/std/vector.scala b/core/src/main/scala/cats/std/vector.scala index b7cb2ba76b..bb32ea8988 100644 --- a/core/src/main/scala/cats/std/vector.scala +++ b/core/src/main/scala/cats/std/vector.scala @@ -6,7 +6,7 @@ import cats.syntax.show._ import scala.annotation.tailrec import scala.collection.+: -import scala.collection.mutable.ListBuffer +import scala.collection.immutable.VectorBuilder trait VectorInstances { implicit val vectorInstance: Traverse[Vector] with MonadCombine[Vector] with CoflatMap[Vector] = @@ -28,12 +28,12 @@ trait VectorInstances { fa.flatMap(a => fb.map(b => f(a, b))) def coflatMap[A, B](fa: Vector[A])(f: Vector[A] => B): Vector[B] = { - @tailrec def loop(buf: ListBuffer[B], as: Vector[A]): Vector[B] = + @tailrec def loop(builder: VectorBuilder[B], as: Vector[A]): Vector[B] = as match { - case _ +: rest => loop(buf += f(as), rest) - case _ => buf.to[Vector] + case _ +: rest => loop(builder += f(as), rest) + case _ => builder.result() } - loop(ListBuffer.empty[B], fa) + loop(new VectorBuilder[B], fa) } def foldLeft[A, B](fa: Vector[A], b: B)(f: (B, A) => B): B =