From 3dd9407eca65815fc91cac6b8816ffa49d36979f Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 11 Sep 2020 21:00:09 +0200 Subject: [PATCH 1/5] Update snakeyaml to 1.27 --- project/build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.sbt b/project/build.sbt index 5ee483f878..f329d76a03 100644 --- a/project/build.sbt +++ b/project/build.sbt @@ -1 +1 @@ -libraryDependencies += "org.yaml" % "snakeyaml" % "1.26" +libraryDependencies += "org.yaml" % "snakeyaml" % "1.27" From efc432c74d4dbd3af35955e7ca3de81a07a361a8 Mon Sep 17 00:00:00 2001 From: takayahilton Date: Sat, 12 Sep 2020 06:03:25 +0900 Subject: [PATCH 2/5] Add method `distinct` to TraverseFilter It comes from Data.Witherable's hashNub and ordNub. --- core/src/main/scala/cats/TraverseFilter.scala | 31 +++++++++++++ .../cats/tests/ScalaVersionSpecific.scala | 1 + .../cats/tests/TraverseFilterSuite.scala | 43 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/src/test/scala/cats/tests/TraverseFilterSuite.scala diff --git a/core/src/main/scala/cats/TraverseFilter.scala b/core/src/main/scala/cats/TraverseFilter.scala index 3135fdc6d1..3ec382c1df 100644 --- a/core/src/main/scala/cats/TraverseFilter.scala +++ b/core/src/main/scala/cats/TraverseFilter.scala @@ -1,7 +1,10 @@ package cats +import cats.data.State import simulacrum.{noop, typeclass} + import scala.annotation.implicitNotFound +import scala.collection.immutable.{HashSet, TreeSet} /** * `TraverseFilter`, also known as `Witherable`, represents list-like structures @@ -85,6 +88,32 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] { override def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B] = traverseFilter[Id, A, B](fa)(f) + + /** + * Removes duplicate elements from a list, keeping only the first occurrence. + */ + def ordDistinct[A](fa: F[A])(implicit O: Order[A]): F[A] = { + implicit val ord: Ordering[A] = O.toOrdering + + traverseFilter[State[TreeSet[A], *], A, A](fa)(a => + State(alreadyIn => if (alreadyIn(a)) (alreadyIn, None) else (alreadyIn + a, Some(a))) + ) + .run(TreeSet.empty) + .value + ._2 + } + + /** + * Removes duplicate elements from a list, keeping only the first occurrence. + * This is usually faster than ordDistinct, especially for things that have a slow comparion (like String). + */ + def hashDistinct[A](fa: F[A])(implicit H: Hash[A]): F[A] = + traverseFilter[State[HashSet[A], *], A, A](fa)(a => + State(alreadyIn => if (alreadyIn(a)) (alreadyIn, None) else (alreadyIn + a, Some(a))) + ) + .run(HashSet.empty) + .value + ._2 } object TraverseFilter { @@ -119,6 +148,8 @@ object TraverseFilter { typeClassInstance.filterA[G, A](self)(f)(G) def traverseEither[G[_], B, C](f: A => G[Either[C, B]])(g: (A, C) => G[Unit])(implicit G: Monad[G]): G[F[B]] = typeClassInstance.traverseEither[G, A, B, C](self)(f)(g)(G) + def ordDistinct(implicit O: Order[A]): F[A] = typeClassInstance.ordDistinct(self) + def hashDistinct(implicit H: Hash[A]): F[A] = typeClassInstance.hashDistinct(self) } trait AllOps[F[_], A] extends Ops[F, A] with FunctorFilter.AllOps[F, A] { type TypeClassType <: TraverseFilter[F] diff --git a/tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala b/tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala index 9922ffd075..e9ae4bbc89 100644 --- a/tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala +++ b/tests/src/test/scala-2.13+/cats/tests/ScalaVersionSpecific.scala @@ -164,3 +164,4 @@ trait ScalaVersionSpecificTraverseSuite { self: TraverseSuiteAdditional => class TraverseLazyListSuite extends TraverseSuite[LazyList]("LazyList") class TraverseLazyListSuiteUnderlying extends TraverseSuite.Underlying[LazyList]("LazyList") +class TraverseFilterLazyListSuite extends TraverseFilterSuite[LazyList]("LazyList") diff --git a/tests/src/test/scala/cats/tests/TraverseFilterSuite.scala b/tests/src/test/scala/cats/tests/TraverseFilterSuite.scala new file mode 100644 index 0000000000..bd1e447c31 --- /dev/null +++ b/tests/src/test/scala/cats/tests/TraverseFilterSuite.scala @@ -0,0 +1,43 @@ +package cats.tests + +import cats.data.Chain +import cats.instances.all._ +import cats.laws.discipline.arbitrary.catsLawsArbitraryForChain +import cats.syntax.eq._ +import cats.syntax.foldable._ +import cats.syntax.traverseFilter._ +import cats.{Traverse, TraverseFilter} +import org.scalacheck.Arbitrary +import org.scalacheck.Prop.forAll + +import scala.collection.immutable.Queue + +abstract class TraverseFilterSuite[F[_]: TraverseFilter](name: String)(implicit + ArbFInt: Arbitrary[F[Int]], + ArbFString: Arbitrary[F[String]] +) extends CatsSuite { + + implicit def T: Traverse[F] = implicitly[TraverseFilter[F]].traverse + + test(s"TraverseFilter[$name].ordDistinct") { + forAll { (fa: F[Int]) => + fa.ordDistinct.toList === fa.toList.distinct + } + } + + test(s"TraverseFilter[$name].hashDistinct") { + forAll { (fa: F[String]) => + fa.hashDistinct.toList === fa.toList.distinct + } + } +} + +class TraverseFilterListSuite extends TraverseFilterSuite[List]("list") + +class TraverseFilterVectorSuite extends TraverseFilterSuite[Vector]("vector") + +class TraverseFilterChainSuite extends TraverseFilterSuite[Chain]("chain") + +class TraverseFilterQueueSuite extends TraverseFilterSuite[Queue]("queue") + +class TraverseFilterStreamSuite extends TraverseFilterSuite[Stream]("stream") From 87c5e5317df8f3da9a302ac199561c4d4f148c60 Mon Sep 17 00:00:00 2001 From: Enrico Benini Date: Mon, 14 Sep 2020 06:42:57 +0200 Subject: [PATCH 3/5] fixes #3599 (#3604) Has commented here: https://github.com/typelevel/cats/issues/3599#issuecomment-691477329 The jekyll command to lunch the microsite locally is wrong. This fix it. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d53235b160..a70bd220f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -208,7 +208,7 @@ run `sbt docs/makeMicrosite` 2. In a shell, navigate to the generated site directory in `cats-docs/target/site` -3. Start jekyll with `jekyll serve` +3. Start jekyll with `jekyll serve -b /cats` 4. Navigate to http://localhost:4000/cats/ in your browser From 0d5045a72211546974e8f914cdd93b51e40b8f68 Mon Sep 17 00:00:00 2001 From: tanaka takaya Date: Tue, 15 Sep 2020 02:26:10 +0900 Subject: [PATCH 4/5] update scalajs badge (#3605) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 650a460978..151f168aa4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [![Financial Contributors on Open Collective](https://opencollective.com/typelevel/all/badge.svg?label=financial+contributors)](https://opencollective.com/typelevel) [![Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/typelevel/cats) [![codecov.io](http://codecov.io/github/typelevel/cats/coverage.svg?branch=master)](http://codecov.io/github/typelevel/cats?branch=master) [![Latest version](https://index.scala-lang.org/typelevel/cats/cats-core/latest.svg?color=orange&v=1)](https://index.scala-lang.org/typelevel/cats/cats-core) -[![Scala.js](http://scala-js.org/assets/badges/scalajs-0.6.14.svg)](http://scala-js.org) +[![Scala.js](http://scala-js.org/assets/badges/scalajs-1.2.0.svg)](http://scala-js.org) ### Overview From 9a34e18d65f3a0513eca4df88dcce8df357fa790 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 14 Sep 2020 21:37:53 +0200 Subject: [PATCH 5/5] Update scalafmt-core to 2.7.1 --- .scalafmt.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index fac85cbc12..db614a130f 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version=2.7.0 +version=2.7.1 align.openParenCallSite = true align.openParenDefnSite = true maxColumn = 120