Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize the foldM implementation for Vector #2552

Merged
merged 1 commit into from Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 12 additions & 0 deletions bench/src/main/scala/cats/bench/FoldBench.scala
Expand Up @@ -3,13 +3,17 @@ package cats.bench
import cats.data.Const
import cats.instances.string._
import cats.instances.list._
import cats.instances.vector._
import cats.instances.option._
import cats.{Foldable, Traverse}
import org.openjdk.jmh.annotations.{Benchmark, Scope, State}

@State(Scope.Benchmark)
class FoldBench {

val chars: List[String] = ('a' to 'z').map(_.toString).toList
val charsVector: Vector[String] = chars.toVector
val combineStringsSome: (String, String) => Option[String] = (s1, s2) => Some(s1 + s2)

/** Benchmark fold of Foldable[List] */
@Benchmark
Expand All @@ -21,4 +25,12 @@ class FoldBench {
def traverseConst(): String =
Traverse[List].traverse[Const[String, ?], String, String](chars)(Const(_)).getConst

@Benchmark
def vectorToListFoldM(): Option[String] =
Foldable[List].foldM(charsVector.toList, "")(combineStringsSome)

@Benchmark
def vectorIndexFoldM(): Option[String] =
Foldable[Vector].foldM(charsVector, "")(combineStringsSome)

}
10 changes: 7 additions & 3 deletions core/src/main/scala/cats/instances/vector.scala
Expand Up @@ -6,7 +6,6 @@ import cats.syntax.show._
import scala.annotation.tailrec
import scala.collection.+:
import scala.collection.immutable.VectorBuilder
import list._

trait VectorInstances extends cats.kernel.instances.VectorInstances {
implicit val catsStdInstancesForVector: Traverse[Vector] with Monad[Vector] with Alternative[Vector] with CoflatMap[Vector] =
Expand Down Expand Up @@ -89,8 +88,13 @@ trait VectorInstances extends cats.kernel.instances.VectorInstances {

override def isEmpty[A](fa: Vector[A]): Boolean = fa.isEmpty

override def foldM[G[_], A, B](fa: Vector[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] =
Foldable[List].foldM(fa.toList, z)(f)
override def foldM[G[_], A, B](fa: Vector[A], z: B)(f: (B, A) => G[B])(implicit G: Monad[G]): G[B] = {
val length = fa.length
G.tailRecM((z, 0)) { case (b, i) =>
if (i < length) G.map(f(b, fa(i)))(b => Left((b, i + 1)))
else G.pure(Right(b))
}
}

override def fold[A](fa: Vector[A])(implicit A: Monoid[A]): A = A.combineAll(fa)

Expand Down