-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Luka Jacobowitz
committed
Oct 4, 2017
1 parent
8c60716
commit 15995be
Showing
3 changed files
with
75 additions
and
116 deletions.
There are no files selected for viewing
66 changes: 19 additions & 47 deletions
66
kernel-laws/src/main/scala/cats/kernel/laws/HashLaws.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,27 @@ | ||
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]] | ||
} | ||
} | ||
trait HashLaws[A] extends EqLaws[A] { | ||
override implicit def E: Hash[A] | ||
|
||
def hashCompatibility(x: A, y: A): IsEq[Boolean] = | ||
(!E.eqv(x, y) || (Hash.hash(x) == Hash.hash(y))) <-> true | ||
|
||
|
||
/** | ||
* @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, | ||
"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, | ||
"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, | ||
"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: _*) | ||
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 | ||
|
||
|
||
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 | ||
|
||
} | ||
|
||
object HashLaws { | ||
def apply[A](implicit ev: Hash[A]): HashLaws[A] = | ||
new HashLaws[A] { def E: Hash[A] = ev } | ||
} |
30 changes: 30 additions & 0 deletions
30
kernel-laws/src/main/scala/cats/kernel/laws/discipline/HashTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package cats | ||
package kernel | ||
package laws | ||
package discipline | ||
|
||
import cats.kernel.instances.boolean._ | ||
import org.scalacheck.Arbitrary | ||
import org.scalacheck.Prop.forAll | ||
|
||
import scala.util.hashing.Hashing | ||
|
||
trait HashTests[A] extends EqLawTests[A] { | ||
|
||
def laws: HashLaws[A] | ||
|
||
def hash(implicit arbA: Arbitrary[A], arbF: Arbitrary[A => A], eqA: Eq[A], hashA: Hashing[A]): RuleSet = | ||
new DefaultRuleSet( | ||
"hash", | ||
Some(eqv), | ||
"hash compatibility" -> forAll(laws.hashCompatibility _), | ||
"same as universal hash" -> forAll(laws.sameAsUniversalHash _), | ||
"same as universal hash" -> forAll((x: A, y: A) => laws.sameAsScalaHashing(x, y, hashA)) | ||
) | ||
|
||
} | ||
|
||
object HashTests { | ||
def apply[A: Hash]: HashTests[A] = | ||
new HashTests[A] { def laws: HashLaws[A] = HashLaws[A] } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters