diff --git a/bench/src/main/scala/cats/bench/CatenableBench.scala b/bench/src/main/scala/cats/bench/CatenableBench.scala index 7d543b4518f..2565f18b5df 100644 --- a/bench/src/main/scala/cats/bench/CatenableBench.scala +++ b/bench/src/main/scala/cats/bench/CatenableBench.scala @@ -1,6 +1,7 @@ package cats.bench import cats.data.Catenable +import chain.Chain import org.openjdk.jmh.annotations.{Benchmark, Scope, State} @State(Scope.Thread) @@ -9,40 +10,54 @@ class CatenableBench { private val smallCatenable = Catenable(1, 2, 3, 4, 5) private val smallVector = Vector(1, 2, 3, 4, 5) private val smallList = List(1, 2, 3, 4, 5) + private val smallChain = Chain(smallList) private val largeCatenable = Catenable.fromSeq(0 to 1000000) private val largeVector = (0 to 1000000).toVector private val largeList = (0 to 1000000).toList + private val largeChain = (0 to 1000).foldLeft(Chain.empty[Int])((acc, _) => acc ++ Chain(0 to 1000)) - private val largeNestedCatenable = largeList.map(Catenable.singleton) - private val largeNestedVector = largeList.map(Vector(_)) - private val largeNestedList = largeList.map(List(_)) @Benchmark def mapSmallCatenable: Catenable[Int] = smallCatenable.map(_ + 1) @Benchmark def mapSmallVector: Vector[Int] = smallVector.map(_ + 1) @Benchmark def mapSmallList: List[Int] = smallList.map(_ + 1) + @Benchmark def mapSmallChain: Chain[Int] = smallChain.map(_ + 1) + @Benchmark def mapLargeCatenable: Catenable[Int] = largeCatenable.map(_ + 1) @Benchmark def mapLargeVector: Vector[Int] = largeVector.map(_ + 1) @Benchmark def mapLargeList: List[Int] = largeList.map(_ + 1) + @Benchmark def mapLargeChain: Chain[Int] = largeChain.map(_ + 1) + @Benchmark def foldLeftSmallCatenable: Int = smallCatenable.foldLeft(0)(_ + _) @Benchmark def foldLeftSmallVector: Int = smallVector.foldLeft(0)(_ + _) @Benchmark def foldLeftSmallList: Int = smallList.foldLeft(0)(_ + _) + @Benchmark def foldLeftSmallChain: Int = smallChain.foldLeft(0)(_ + _) + @Benchmark def foldLeftLargeCatenable: Int = largeCatenable.foldLeft(0)(_ + _) @Benchmark def foldLeftLargeVector: Int = largeVector.foldLeft(0)(_ + _) @Benchmark def foldLeftLargeList: Int = largeList.foldLeft(0)(_ + _) + @Benchmark def foldLeftLargeChain: Int = largeChain.foldLeft(0)(_ + _) + @Benchmark def consSmallCatenable: Catenable[Int] = 0 +: smallCatenable @Benchmark def consSmallVector: Vector[Int] = 0 +: smallVector @Benchmark def consSmallList: List[Int] = 0 +: smallList + @Benchmark def consSmallChain: Chain[Int] = 0 +: smallChain + @Benchmark def consLargeCatenable: Catenable[Int] = 0 +: largeCatenable @Benchmark def consLargeVector: Vector[Int] = 0 +: largeVector @Benchmark def consLargeList: List[Int] = 0 +: largeList + @Benchmark def consLargeChain: Chain[Int] = 0 +: largeChain + @Benchmark def createTinyCatenable: Catenable[Int] = Catenable(1) @Benchmark def createTinyVector: Vector[Int] = Vector(1) @Benchmark def createTinyList: List[Int] = List(1) + @Benchmark def createTinyChain: Chain[Int] = Chain.single(1) + @Benchmark def createSmallCatenable: Catenable[Int] = Catenable(1, 2, 3, 4, 5) @Benchmark def createSmallVector: Vector[Int] = Vector(1, 2, 3, 4, 5) @Benchmark def createSmallList: List[Int] = List(1, 2, 3, 4, 5) + @Benchmark def createSmallChain: Chain[Int] = Chain(Seq(1, 2, 3, 4, 5)) } diff --git a/core/src/main/scala/cats/data/Catenable.scala b/core/src/main/scala/cats/data/Catenable.scala index d865123a071..5a1b7c499b6 100644 --- a/core/src/main/scala/cats/data/Catenable.scala +++ b/core/src/main/scala/cats/data/Catenable.scala @@ -249,6 +249,9 @@ object Catenable extends CatenableInstances { /** Creates a catenable of 1 element. */ def singleton[A](a: A): Catenable[A] = Singleton(a) + /** Alias for singleton */ + def one[A](a: A): Catenable[A] = singleton(a) + /** Appends two catenables. */ def append[A](c: Catenable[A], c2: Catenable[A]): Catenable[A] = if (c.isEmpty) c2 @@ -279,6 +282,7 @@ object Catenable extends CatenableInstances { case _ => fromSeq(as) } + // scalastyle:off null class CatenableIterator[A](self: Catenable[A]) extends Iterator[A] { var c: Catenable[A] = if (self.isEmpty) null else self val rights = new collection.mutable.ArrayBuffer[Catenable[A]] @@ -303,6 +307,7 @@ object Catenable extends CatenableInstances { go } } + // scalastyle:on null } private[data] sealed abstract class CatenableInstances { diff --git a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala index 130966a9fda..dc287f781b5 100644 --- a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala +++ b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala @@ -279,9 +279,9 @@ object arbitrary extends ArbitraryInstances0 { implicit def catsLawsArbitraryForCatenable[A](implicit A: Arbitrary[A]): Arbitrary[Catenable[A]] = Arbitrary(Gen.sized { case 0 => Gen.const(Catenable.nil) - case 1 => A.arbitrary.map(Catenable.singleton) + case 1 => A.arbitrary.map(Catenable.one) case 2 => A.arbitrary.flatMap(a1 => A.arbitrary.flatMap(a2 => - Catenable.append(Catenable.singleton(a1), Catenable.singleton(a2)))) + Catenable.append(Catenable.one(a1), Catenable.one(a2)))) case n => Catenable.fromSeq(Range.apply(0, n)).foldLeft(Gen.const(Catenable.empty[A])) { (gen, _) => gen.flatMap(cat => A.arbitrary.map(a => cat :+ a)) }