-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hash typeclass #1712
Hash typeclass #1712
Changes from 84 commits
9587384
a1ef839
b7fb209
04c1f96
e6e6159
66468e0
92f808c
69d4259
932903d
c8b3d5e
650e4f5
bb043a6
d087613
a4f96b5
7edb0c5
8abefa0
703070b
b8ee98f
5ebd13d
8a950f8
0cd2b48
c3f6378
48034eb
987ab6d
a432ace
9f9fd1a
ab539d1
951561f
927a0c7
0101cf2
1005e3e
cf3218a
6ea5667
d4baf94
222fc29
522b9ad
fcb355c
9397e2a
2cc9854
54ce4f8
37af90e
e114dc3
52eceac
737e2ec
4ddd79f
a7d3e3a
1225a06
517bd3c
ece3413
177edf5
e170d22
916415c
0dd4a12
49fa9ae
bf96364
f645496
a59f9c7
79b7f1a
4cedb1f
d397983
f772a7a
6906f1f
f6e2b0b
91115c0
d2bc3ac
32b9bec
3f22bc5
a4007e8
93b0c1c
02402c5
200aa23
86b6947
14e2c5c
f7e6b7e
a9b8313
ef2e4f5
8856f8b
34ae266
a89b861
9392100
c24deb4
cc034ea
54b04eb
136e203
526757b
49403c6
601e18d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package cats | ||
package instances | ||
|
||
import cats.functor._ | ||
|
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is untested There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A question: where should tests for instances of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never mind, i've found it in |
||
|
||
} | ||
|
||
} |
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] | ||
} |
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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OrderLaws's parent is also None. But EqLaws are listed below in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems like we should have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't find |
||
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: _*) | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be also
Cartesian[Hash]
: you can hash each item then combine them in one of many ways. Maybe the fact that there are many ways to combine means it should not be implicit, but we can give functions that do so.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to
ContravariantCartesian
. Thanks! I didn't know the existence ofCartesian
before. I made it implicit: the standard way to combine items isscala.util.hashing.MurmurHash3.productHash
.