Skip to content

Commit

Permalink
Hash typeclass (#1712)
Browse files Browse the repository at this point in the history
* cats.kernel.Hash and related instances (#1690)

* Hash laws

* all test passed

* Hash instances for tuples

* introduce implicit precedence in KernelBoiler: Order > PartialOrder > Eq; Hash > Eq.

* Add type alias in cats._; Add contravariant instance for `Hash`

* HashFunctions extends EqFunctions

* Move contravariant instances to separate trait, in accordance with (#1659)

* revert name change

* move EitherInstances1#EitherEq out

* Optimize hash computation on case classes without allocating a new object

* fixing the problem in CI build: method catsKernelStdOrderForChar()cats.kernel.instances.CharOrder in trait cats.kernel.instances.CharInstances has a different result type in current version, where it is cats.kernel.Order rather than cats.kernel.instances.CharOrder

* Full compliance with how Scala generates hash codes on case classes; +SetHash

* Cartesian[Hash]

* ContravariantCartesian[Hash]

* ContravariantCartesian[Hash]; Hash.fromHashing

* style issues

* remove unused import

* some test cases

* some test cases

* +test for Contravariant[Hash]

* +test for Contravariant[Hash]

* Add NEL/NEV one (#1707)

`NonEmptyList.one` is analogous to `_.pure[NonEmptyList]`.

Alternative for `NonEmptyList.of(x)` where you don't pay the price of
the varargs, which isn't used.

* move instances into separate trait (#1659)

* move instances into separate trait

* adding separate objects for piecemeal imports

* Adding implicit resolution tests for piecemeal imports for hierarchy

* Removing explicit implicitly and using apply method

* cats.kernel.Hash and related instances (#1690)

* Hash laws

* all test passed

* Hash instances for tuples

* introduce implicit precedence in KernelBoiler: Order > PartialOrder > Eq; Hash > Eq.

* Add type alias in cats._; Add contravariant instance for `Hash`

* HashFunctions extends EqFunctions

* Move contravariant instances to separate trait, in accordance with (#1659)

* revert name change

* move EitherInstances1#EitherEq out

* Optimize hash computation on case classes without allocating a new object

* fixing the problem in CI build: method catsKernelStdOrderForChar()cats.kernel.instances.CharOrder in trait cats.kernel.instances.CharInstances has a different result type in current version, where it is cats.kernel.Order rather than cats.kernel.instances.CharOrder

* Full compliance with how Scala generates hash codes on case classes; +SetHash

* Cartesian[Hash]

* ContravariantCartesian[Hash]

* ContravariantCartesian[Hash]; Hash.fromHashing

* style issues

* remove unused import

* some test cases

* some test cases

* +test for Contravariant[Hash]

* +test for Contravariant[Hash]

* cats.kernel.Hash and related instances (#1690)

* Hash laws

* all test passed

* Hash instances for tuples

* introduce implicit precedence in KernelBoiler: Order > PartialOrder > Eq; Hash > Eq.

* Add type alias in cats._; Add contravariant instance for `Hash`

* HashFunctions extends EqFunctions

* Move contravariant instances to separate trait, in accordance with (#1659)

* revert name change

* move EitherInstances1#EitherEq out

* Optimize hash computation on case classes without allocating a new object

* fixing the problem in CI build: method catsKernelStdOrderForChar()cats.kernel.instances.CharOrder in trait cats.kernel.instances.CharInstances has a different result type in current version, where it is cats.kernel.Order rather than cats.kernel.instances.CharOrder

* Full compliance with how Scala generates hash codes on case classes; +SetHash

* Cartesian[Hash]

* ContravariantCartesian[Hash]

* ContravariantCartesian[Hash]; Hash.fromHashing

* style issues

* remove unused import

* some test cases

* some test cases

* +test for Contravariant[Hash]

* +test for Contravariant[Hash]

* Fix duplication error and style error

* fix merge error

* remove instance for Cartesian[Hash]: it does not satisfy associativity

* +identityHash, +`hash` postfix method

* all tests passed

* increase coverage

* accidentally removed plugin, restore it

* all tests passed

* increase coverage

* increase coverage, ## => hashCode, kernelBoiler

* suppress mimaReportBinaryIssues

* Remove cats.functor

* Remove cats.functor
  • Loading branch information
ctongfei authored and LukaJCB committed Oct 4, 2017
1 parent a915afb commit c131fe4
Show file tree
Hide file tree
Showing 41 changed files with 759 additions and 81 deletions.
118 changes: 117 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,123 @@ val binaryCompatibleVersion = "0.8.0"
val binaryCompatibleExceptions = {
import com.typesafe.tools.mima.core._
import com.typesafe.tools.mima.core.ProblemFilters._
Seq( //todo: remove these once we release 1.0.0-RC1
Seq( // todo: remove these once we release 1.0.0-RC1
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.QueueInstances.*"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.QueueInstances1.*"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.QueueInstances2.*"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.DurationInstances.*"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.MapInstances.catsKernelStdEqForMap"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.MapInstances.catsKernelStdMonoidForMap"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.MapInstances.catsKernelStdHashForMap"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple12"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple7"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple4"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple13"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple11"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple1"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple7"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple16"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple22"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple1"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple14"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple4"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple20"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple19"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple10"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple17"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple18"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple3"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple9"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple6"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple3"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple12"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple22"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple6"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple19"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple10"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple9"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple21"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple15"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple13"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple16"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple20"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple14"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple5"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple2"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple8"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple17"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple5"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple15"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple21"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple11"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdPartialOrderForTuple2"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple8"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.TupleInstances.catsKernelStdEqForTuple18"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple9"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple16"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple22"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple3"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple6"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple21"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple18"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple12"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple15"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple8"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple2"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple5"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple20"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple14"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple17"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple4"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple11"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple7"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple1"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple10"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple19"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple13"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.StreamInstances1.catsKernelStdHashForStream"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.ListInstances1.catsKernelStdHashForList"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.SetInstances.catsKernelStdPartialOrderForSet"),
exclude[UpdateForwarderBodyProblem]("cats.kernel.instances.SetInstances.catsKernelStdSemilatticeForSet"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.SetInstances.catsKernelStdHashForSet"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.VectorInstances1.catsKernelStdHashForVector"),
exclude[DirectMissingMethodProblem]("cats.kernel.instances.BitSetInstances.catsKernelStdPartialOrderForBitSet"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.BitSetInstances.cats$kernel$instances$BitSetInstances$_setter_$catsKernelStdOrderForBitSet_="),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.BitSetInstances.catsKernelStdOrderForBitSet"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple9"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple16"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple22"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple3"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple6"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple21"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple18"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple12"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple15"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple8"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple2"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple5"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple20"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple14"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple17"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple4"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple11"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple7"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple1"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple10"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple19"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.TupleInstances1.catsKernelStdHashForTuple13"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.EitherInstances1.catsStdEqForEither"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.EitherInstances.catsStdOrderForEither"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.EitherInstances.catsDataMonoidForEither"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.EitherInstances0.catsDataSemigroupForEither"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.EitherInstances0.catsStdHashForEither"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.EitherInstances0.catsStdPartialOrderForEither"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.OptionInstances1.catsKernelStdHashForOption"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.FunctionInstances0.catsKernelHashForFunction0"),
exclude[ReversedMissingMethodProblem]("cats.kernel.instances.EitherInstances0.catsStdHashForEither"),
exclude[DirectMissingMethodProblem]("cats.kernel.instances.all.package.catsKernelStdPartialOrderForBitSet"),
exclude[DirectMissingMethodProblem]("cats.kernel.instances.bitSet.package.catsKernelStdPartialOrderForBitSet"),
//todo: remove these once we release 1.0.0-RC1
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.QueueInstances.*"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.QueueInstances1.*"),
exclude[InheritedNewAbstractMethodProblem]("cats.kernel.instances.QueueInstances2.*"),
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/cats/instances/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ trait AllInstances
with EquivInstances
with FunctionInstances
with FutureInstances
with HashInstances
with ListInstances
with MapInstances
with MonoidInstances
Expand Down
16 changes: 16 additions & 0 deletions core/src/main/scala/cats/instances/hash.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cats
package instances


trait HashInstances {

implicit val catsContravariantForHash: Contravariant[Hash] =
new Contravariant[Hash] {
/**
* Derive a `Hash` for `B` given an `Hash[A]` and a function `B => A`.
*/
def contramap[A, B](ha: Hash[A])(f: B => A): Hash[B] = Hash.by(f)(ha)

}

}
2 changes: 2 additions & 0 deletions core/src/main/scala/cats/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ package object cats {
type Eq[A] = cats.kernel.Eq[A]
type PartialOrder[A] = cats.kernel.PartialOrder[A]
type Order[A] = cats.kernel.Order[A]
type Hash[A] = cats.kernel.Hash[A]
type Semigroup[A] = cats.kernel.Semigroup[A]
type Monoid[A] = cats.kernel.Monoid[A]
type Group[A] = cats.kernel.Group[A]

val Eq = cats.kernel.Eq
val PartialOrder = cats.kernel.PartialOrder
val Order = cats.kernel.Order
val Hash = cats.kernel.Hash
val Semigroup = cats.kernel.Semigroup
val Monoid = cats.kernel.Monoid
val Group = cats.kernel.Group
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/cats/syntax/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ trait AllSyntax
with FoldableSyntax
with FunctorSyntax
with GroupSyntax
with HashSyntax
with InvariantSyntax
with IorSyntax
with ListSyntax
Expand Down
18 changes: 18 additions & 0 deletions core/src/main/scala/cats/syntax/hash.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cats
package syntax

import cats.macros.Ops

trait HashSyntax {

implicit def catsSyntaxHash[A: Hash](a: A): HashOps[A] =
new HashOps[A](a)

}

final class HashOps[A: Hash](a: A) {
/**
* Gets the hash code of this object given an implicit `Hash` instance.
*/
def hash: Int = macro Ops.unop0[Int]
}
58 changes: 58 additions & 0 deletions kernel-laws/src/main/scala/cats/kernel/laws/HashLaws.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cats.kernel
package laws

import org.typelevel.discipline._
import org.scalacheck._
import org.scalacheck.Prop._

import scala.util.hashing._

object HashLaws {
def apply[A : Eq : Arbitrary]: HashLaws[A] =
new HashLaws[A] {
def Equ = implicitly[Eq[A]]
def Arb = implicitly[Arbitrary[A]]
}
}

/**
* @author Tongfei Chen
*/
trait HashLaws[A] extends Laws {

implicit def Equ: Eq[A]
implicit def Arb: Arbitrary[A]

def hash(implicit A: Hash[A]): HashProperties = new HashProperties(
name = "hash",
parent = None,
Rules.serializable(Equ),
"compatibility-hash" -> forAll { (x: A, y: A) =>
!(A.eqv(x, y)) ?|| (Hash.hash(x) == Hash.hash(y))
}
)

def sameAsUniversalHash(implicit A: Hash[A]): HashProperties = new HashProperties(
name = "sameAsUniversalHash",
parent = None,
Rules.serializable(Equ),
"same-as-universal-hash" -> forAll { (x: A, y: A) =>
(A.hash(x) == x.hashCode) && (Hash.fromUniversalHashCode[A].hash(x) == x.hashCode()) &&
(A.eqv(x, y) == Hash.fromUniversalHashCode[A].eqv(x, y))
}
)

def sameAsScalaHashing(implicit catsHash: Hash[A], scalaHashing: Hashing[A]): HashProperties = new HashProperties(
name = "sameAsScalaHashing",
parent = None,
Rules.serializable(Equ),
"same-as-scala-hashing" -> forAll { (x: A, y: A) =>
(catsHash.hash(x) == Hash.fromHashing(scalaHashing).hash(x)) &&
(catsHash.eqv(x, y) == Hash.fromHashing(scalaHashing).eqv(x, y))
}
)

class HashProperties(name: String, parent: Option[RuleSet], props: (String, Prop)*)
extends DefaultRuleSet(name, parent, props: _*)

}
Loading

0 comments on commit c131fe4

Please sign in to comment.