Skip to content

Commit

Permalink
Strict derivation for Hash
Browse files Browse the repository at this point in the history
  • Loading branch information
joroKr21 committed Dec 17, 2023
1 parent 036b65e commit 122933d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 1 deletion.
3 changes: 2 additions & 1 deletion core/src/main/scala-3/cats/derived/DerivedEq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Make sure that A satisfies one of the following conditions:
type DerivedEq[A] = Derived[Eq[A]]
object DerivedEq:
type Or[A] = Derived.Or[Eq[A]]

inline def apply[A]: Eq[A] =
import DerivedEq.given
summonInline[DerivedEq[A]].instance
Expand Down Expand Up @@ -42,5 +43,5 @@ object DerivedEq:
[t] => (eqt: F[t], x: t, y: t) => eqt.eqv(x, y)

object Strict:
given product[A](using inst: => K0.ProductInstances[Eq, A]): DerivedEq[A] =
given product[A](using => K0.ProductInstances[Eq, A]): DerivedEq[A] =
new Product[Eq, A] {}
10 changes: 10 additions & 0 deletions core/src/main/scala-3/cats/derived/DerivedHash.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,16 @@ Make sure that A satisfies one of the following conditions:
type DerivedHash[A] = Derived[Hash[A]]
object DerivedHash:
type Or[A] = Derived.Or[Hash[A]]

inline def apply[A]: Hash[A] =
import DerivedHash.given
summonInline[DerivedHash[A]].instance

inline def strict[A]: Hash[A] =
import DerivedHash.given
import Strict.product
summonInline[DerivedHash[A]].instance

// These instances support singleton types unlike the instances in Cats' kernel.
given boolean[A <: Boolean]: DerivedHash[A] = Hash.fromUniversalHashCode
given byte[A <: Byte]: DerivedHash[A] = Hash.fromUniversalHashCode
Expand Down Expand Up @@ -57,3 +63,7 @@ object DerivedHash:

final override def hash(x: A): Int =
inst.fold[Int](x)([t] => (h: F[t], x: t) => h.hash(x))

object Strict:
given product[A <: scala.Product](using => K0.ProductInstances[Hash, A]): DerivedHash[A] =
new Product[Hash, A] {}
2 changes: 2 additions & 0 deletions core/src/main/scala-3/cats/derived/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ object semiauto:

object strict:
extension (x: Eq.type) inline def derived[A]: Eq[A] = DerivedEq.strict[A]
extension (x: Hash.type) inline def derived[A]: Hash[A] = DerivedHash.strict[A]

object semiauto:
inline def eq[A]: Eq[A] = DerivedEq.strict[A]
inline def hash[A]: Hash[A] = DerivedHash.strict[A]

object auto:
object eq:
Expand Down
17 changes: 17 additions & 0 deletions core/src/test/scala-3/cats/derived/HashSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class HashSuite extends KittensSuite:
import semiInstances.given
validate("semiauto.hash")

locally:
import strictInstances.given
validate("strict.semiauto.hash")
testNoInstance("strict.semiauto.hash", "Top")

locally:
import derivedInstances.*
val instance = "derived.hash"
Expand Down Expand Up @@ -58,6 +63,18 @@ object HashSuite:
given Hash[EnumK0] = semiauto.hash
given Hash[Singletons[Int]] = semiauto.hash

object strictInstances:
given Hash[IList[Int]] = strict.semiauto.hash
given Hash[Inner] = strict.semiauto.hash
given Hash[Outer] = strict.semiauto.hash
given Hash[Interleaved[Int]] = strict.semiauto.hash
given Hash[Tree[Int]] = strict.semiauto.hash
given Hash[Recursive] = strict.semiauto.hash
given Hash[EnumK0] = strict.semiauto.hash
given Hash[Singletons[Int]] =
given [A <: Singleton: ValueOf]: Hash[A] = Hash.fromUniversalHashCode
strict.semiauto.hash

object derivedInstances:
case class IList[A](x: ADTs.IList[A]) derives Hash
case class Inner(x: ADTs.Inner) derives Hash
Expand Down

0 comments on commit 122933d

Please sign in to comment.