Skip to content

Commit

Permalink
Merge pull request #4319 from armanbilge/issue/4284
Browse files Browse the repository at this point in the history
Deprecate `HashLaws#sameAsUniversalHash`
  • Loading branch information
johnynek authored Oct 18, 2022
2 parents 9b5d664 + e4630d3 commit 5fe56f0
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 20 deletions.
21 changes: 14 additions & 7 deletions core/src/main/scala/cats/TraverseFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ package cats

import cats.data.State

import scala.collection.immutable.{HashSet, TreeSet}
import scala.collection.immutable.{IntMap, TreeSet}

/**
* `TraverseFilter`, also known as `Witherable`, represents list-like structures
Expand Down Expand Up @@ -141,12 +141,19 @@ trait TraverseFilter[F[_]] extends FunctorFilter[F] {
* 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
traverseFilter(fa) { a =>
State { (distinct: IntMap[List[A]]) =>
val ahash = H.hash(a)
distinct.get(ahash) match {
case None => (distinct.updated(ahash, a :: Nil), Some(a))
case Some(existing) =>
if (Traverse[List].contains_(existing, a))
(distinct, None)
else
(distinct.updated(ahash, a :: existing), Some(a))
}
}
}.run(IntMap.empty).value._2
}

object TraverseFilter {
Expand Down
5 changes: 2 additions & 3 deletions free/src/test/scala-2.13+/cats/free/FreeStructuralSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
package cats.free

import cats.{Applicative, Eq, Eval, Functor, Show, Traverse}
import cats.kernel.laws.discipline.{EqTests, PartialOrderTests}
import cats.kernel.laws.discipline.{EqTests, HashTests, PartialOrderTests}
import cats.syntax.all._
import cats.tests.CatsSuite

Expand All @@ -46,8 +46,7 @@ class FreeStructuralSuite extends CatsSuite {

Show[Free[Option, Int]]

// TODO HashLaws#sameAsUniversalHash is really dodgy
// checkAll("Free[Option, Int]", HashTests[Free[Option, Int]].hash)
checkAll("Free[Option, Int]", HashTests[Free[Option, Int]].hash)
checkAll("Free[Option, Int]", PartialOrderTests[Free[Option, Int]].partialOrder)
checkAll("Free[ExprF, String]", EqTests[Free[ExprF, String]].eqv)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ trait HashLaws[A] extends EqLaws[A] {
def hashCompatibility(x: A, y: A): IsEq[Boolean] =
(!E.eqv(x, y) || (Hash.hash(x) == Hash.hash(y))) <-> true

@deprecated("This law is no longer enforced", "2.9.0")
def sameAsUniversalHash(x: A, y: A): IsEq[Boolean] =
((E.hash(x) == x.hashCode) && (Hash.fromUniversalHashCode[A].hash(x) == x.hashCode()) &&
(E.eqv(x, y) == Hash.fromUniversalHashCode[A].eqv(x, y))) <-> true

@deprecated("This law is no longer enforced", "2.9.0")
def sameAsScalaHashing(x: A, y: A, scalaHashing: Hashing[A]): IsEq[Boolean] =
((E.hash(x) == Hash.fromHashing(scalaHashing).hash(x)) &&
(E.eqv(x, y) == Hash.fromHashing(scalaHashing).eqv(x, y))) <-> true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ trait HashTests[A] extends EqTests[A] {
new DefaultRuleSet(
"hash",
Some(eqv),
"hash compatibility" -> forAll(laws.hashCompatibility _),
"same as universal hash" -> forAll(laws.sameAsUniversalHash _),
"same as scala hashing" -> forAll((x: A, y: A) => laws.sameAsScalaHashing(x, y, hashA))
"hash compatibility" -> forAll(laws.hashCompatibility _)
)

}
Expand Down
9 changes: 2 additions & 7 deletions tests/shared/src/test/scala/cats/tests/FunctionSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import cats.{
}
import cats.arrow.{ArrowChoice, Choice, CommutativeArrow}
import cats.kernel._
import cats.kernel.laws.HashLaws
import cats.kernel.laws.discipline.{
BandTests,
BoundedSemilatticeTests,
Expand All @@ -45,6 +44,7 @@ import cats.kernel.laws.discipline.{
CommutativeSemigroupTests,
EqTests,
GroupTests,
HashTests,
MonoidTests,
OrderTests,
PartialOrderTests,
Expand Down Expand Up @@ -136,12 +136,7 @@ class FunctionSuite extends CatsSuite {
checkAll("Function0[Grp]", GroupTests[Function0[Grp]].group)
checkAll("Function0[CGrp]", CommutativeGroupTests[Function0[CGrp]].commutativeGroup)
checkAll("Function0[Distributive]", DistributiveTests[Function0].distributive[Int, Int, Int, Id, Function0])

property("Function0[Hsh]") {
forAll { (x: Function0[Hsh], y: Function0[Hsh]) =>
HashLaws[Function0[Hsh]].hashCompatibility(x, y)
}
}
checkAll("Function0[Hsh]", HashTests[Function0[Hsh]].hash)

// Test for Arrow applicative
Applicative[String => *]
Expand Down

0 comments on commit 5fe56f0

Please sign in to comment.